React入门 Part2

组件

组件是React的核心概念,是React应用程序的基石。组件将应用的UI拆分成独立的、可复用的模块,React应用程序正是由一个个组件搭建而成的。

定义一个组件有两种方法:

  • 使用ES6 class (类组件)
  • 使用函数(函数组件)

组件定义

使用class定义组件

使用class定义组件需要满足的两个条件:

  • class继承自React.Component;
  • class内部必须定义render方法,render方法返回代表该组件UI的React元素;

在使用class定义类组件后,需要使用export将类组件导出,以便在其他文件中使用。

在使用时,需要导入react-dom库,并使用ReactDOM.render()显示,该方法有两个参数:

  • 第一个参数:要显示的组件;
  • 第二个参数:组件要显示的位置;

使用class定义组件:

import React from 'react'

class PostList extends React.Component {
    render() {
        return (
            
帖子列表:
  • 帖子1
  • 帖子2
  • 帖子3
  • 帖子4
  • 帖子5
  • 帖子6
); } } export default PostList;

使用:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import reportWebVitals from './reportWebVitals';

import PostList from './p2/PostList';

ReactDOM.render(
  <React.StrictMode>
    <PostList></PostList>
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();

组件的props

组件的props属性用于把父组件中的数据或者方法传递给子组件,供子组件使用。

props属性是不可变的。

创建子组件:

import React from 'react'

class PostItem extends React.Component {
    render() {
        const {title, author, date} = this.props;
        return(
            
  • {title}
    创建人:{author}
    创建时间:{date}
  • ); } } export default PostItem;

    在父组件中使用:

    import React from 'react'
    import PostItem from './PostItem'
    
    //声明数据
    const data = [
        { title: "帖子1", author: "张三", date: "2021-02-15 11:11:11"},
        { title: "帖子2", author: "李四", date: "2021-02-15 12:11:11"},
        { title: "帖子3", author: "王五", date: "2021-02-15 13:11:11"},
        { title: "帖子4", author: "赵六", date: "2021-02-15 14:11:11"}
    ];
    
    class PostList extends React.Component {
        render() {
            return (
                
    帖子列表:
      { //循环显示 data.map(item => )}
    ); } } export default PostList;

    组件的state

    组件的state是组件内部的状态,state的变化最终将反映到组件UI的变化上。

    可以在组件的构造方法(constructor)中通过this.state定义组件的初始状态,并通过this.setState方法改变组件的状态,进而组件的UI也会随之重新渲染。

    注意点:

    • 在组件的构造方法constructor中,首先要调用super(props),这一步实际是调用React.Component中的构造方法,用于完成React组件的初始化工作;
    • 在constructor中,通过this.state定义了组件的状态;

    添加点击事件:

    import React from 'react'
    
    class PostItem extends React.Component {
    
        constructor(props) {
            super(props);
            //定义初始状态
            this.state = {
                vote: 0
            }
        }
        
        //定义点击事件
        handleClick() {
            let newVote = this.state.vote;
            newVote++;
            this.setState({
                vote: newVote
            });
        }
    
        render() {
            const {title, author, date} = this.props;
            return(
                
  • {title}
    创建人:{author}
    创建时间:{date}
      {this.state.vote}
  • ); } } export default PostItem;

    React组件正是由props和state两种类型的数据驱动渲染出组件UI。props是组件对外的接口,组件通过props接受外部传入的数据;state是组件对内的接口,组件内部状态的改变通过state来反映。props是只读的,不能从内部修改props;state是可变的,组件状态的变化通过修改state来实现。

    更改之后的PostList:

    import React from 'react'
    import PostItem from './PostItem'
    
    class PostList extends React.Component {
    
        constructor(props) {
            super(props);
            //数据
            this.state = {
                posts:[]
            };
            //定时器
            this.timer = null;
            //指定点击事件
            this.handleVote = this.handleVote.bind(this);
        }
    
        //初次渲染结束
        componentDidMount() {
            //异步模拟从服务端请求数据
            this.timer = setTimeout(() => {
                this.setState({
                    posts: [
                        {id: 1, title: "帖子1", author: "张三", date: "2021-02-15 11:11:11", vote: 0},
                        {id: 2, title: "帖子2", author: "李四", date: "2021-02-15 12:11:11", vote: 0},
                        {id: 3, title: "帖子3", author: "王五", date: "2021-02-15 13:11:11", vote: 0},
                        {id: 4, title: "帖子4", author: "赵六", date: "2021-02-15 14:11:11", vote: 0},
                    ]});
            }, 1000);
        }
    
        //组件卸载之前
        componentWillUnmount() {
            if(this.timer) {
                //清除计时器
                clearTimeout(this.timer);
            }
        }
    
        //处理点击
        handleVote(id) {
            //找到目标item
            const newPosts = this.state.posts.map(item => {
                const newItem = item.id === id ? {...item, vote: ++item.vote} : item;
                return newItem;
            });
            //更新state中数据
            this.setState({
                posts: newPosts
            });
        }
    
        render() {
            return (
                
    帖子列表:
      { this.state.posts.map(item => ) }
    ); } } export default PostList;

    升级之后的PostItme:

    import React from 'react'
    
    function PostItem(props) {
    
        const handleClick = () => {
            props.onVote(props.post.id);
        };
    
        const { post } = props;
    
        return(
            
  • {post.title}
    创建人:{post.author}
    创建时间:{post.date}
      {post.vote}
  • ); } export default PostItem;

    属性校验

    React提供了PropTypes这个对象,用于校验组件属性的类型。

    PropTypes包含组件属性所有可能的类型,可以通过定义一个对象实现组件属性类型的校验。

    使用PropTypes进行属性校验:

    import React from 'react'
    import PropTypes from 'prop-types'
    
    class PostItem extends React.Component {
    
        constructor(props) {
            super(props);
            console.log(JSON.stringify(props.post));
        }
    
        //定义点击事件
        handleClick() {
            this.props.onVote(this.props.post.id);
        }
    
        render() {
            return(
                
  • {this.props.post.title}
    创建人:{this.props.post.author}
    创建时间:{this.props.post.date}
      {this.props.post.vote}
  • ); } } //声明属性类型 PostItem.protoType = { post: PropTypes.object, onVote: PropTypes.func } export default PostItem;

    也可对对象的属性进行校验,需要用到shape方法:

    //声明属性类型
    PostItem.protoType = {
        //对象内属性校验
        post: PropTypes.shape({
            id: PropTypes.number,
            title: PropTypes.string,
            author: PropTypes.string,
            date: PropTypes.string,
            vote: PropTypes.number
        }).isRequired,
        //属性类型.是否必须
        onVote: PropTypes.func.isRequired
    }
    

    组件样式

    使用组件样式有两种方式:一种是外部css样式表,另一种是内联样式。

    外部CSS样式表

    此方式与开发Web应用时的方式相同,css样式表根据HTML标签类型、ID、class等选择器定义元素的样式。

    唯一的区别是,React元素要使用className来作为class的选择器。

    在src下创建style.css:

    .testDiv {
        width: 100%;
        height: 50px;
        background-color: blue;
    }
    

    使用该css:

    import React from 'react';
    
    import '../style.css'
    
    function MyDiv(props) {
        console.log("my div");
        return 
    Test
    ; } export default MyDiv;

    内联样式

    内联样式实际上是CSS in JS的写法:将CSS样式写到JS文件中,用JS对象表示CSS样式,然后通过DOM类型节点的sytle属性引用相应样式对象。

    当使用内联样式的时候,样式的属性名必须使用驼峰格式的命名。例如,background-color要写成backgroundColor。

    示例代码:

    import React from 'react';
    
    //声明样式
    const style = {
        width: "100%",
        height: "50px",
        backgroundColor: "red"
    }
    
    function AnthorMyDiv(props) {
        return 
    Test
    ; } export default AnthorMyDiv;

    组件和元素

    React元素是一个普通的JS对象,这个对象通过DOM节点或React组件描述界面是什么样子。

    JSX语法就是用来创建React元素的。

    React组件是一个class或者函数,它接收一些属性作为输入,返回一个React元素。

    React组件是由若干React元素组建而成的。

    你可能感兴趣的:(读书笔记,学习笔记,react)