组件的三大核心属性

state

  1. state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)

  2. 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)

类式组件示例

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
    class Timer extends React.Component {
        // 初始化状态,这里的状态就是当前的秒数
        constructor(props) {
            super(props);
            // state初始化,这里可以直接使用 = 初始化
            this.state = {seconds: 0};
        }

        // 定义tick方法,用于给秒数+1
        // 注意: 状态数据只能调用setState方法更新,不可以直接操作
        // 3. 让自定义函数在构造器中初始化bind() 从而绑定this
        tick() {
            this.setState(state => ({
                seconds: state.seconds + 1
            }));
        }

        // 组件被挂载时,启用interval
        componentDidMount() {
            // 注意,这里的this对象是当前组件的实例
            // 自定义方法中this对象为undefined,解决办法有:
            // 1. 箭头函数
            // this.interval = setInterval(() => this.tick(), 1000);
            // 2. 强制绑定this: 通过函数对象的bind()
            this.interval = setInterval(function () {
                this.tick();
            }.bind(this), 1000);
        }

        // 组件被移除时,停止interval
        componentWillUnmount() {
            clearInterval(this.interval);
        }

        render() {
            return (
                <div>
                    Seconds: {this.state.seconds}
                </div>
            );
        }
    }

    ReactDOM.render(
        <Timer/>,
        document.getElementById('app')
    );
</script>
</body>
</html>

函数式组件示例(hooks)

<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
<div id="app"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">

    function Timer() {
        // 定义状态,返回当前状态值以及设置状态函数
        const [seconds, setSeconds] = React.useState(0);
        // Effect 影响、副作用
        // 是componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合
        // 用于告诉 React 组件需要在渲染后执行某些操作
        // useEffect 会在每次渲染后都执行
        React.useEffect(() => {
            let interval = setInterval(function () {
                setSeconds(seconds + 1);
            }.bind(this), 1000);
            // 返回可选的清除函数
            return function () {
                clearInterval(interval);
            }
        });
        return (<div>
            Seconds: {seconds}
        </div>);
    }

    ReactDOM.render(
        <Timer/>,
        document.getElementById('app')
    );
</script>
</body>

</html>

注意:

  1. 组件中render方法中的this为组件实例对象

  2. 组件自定义的方法中this为undefined,如何解决?

    1. 强制绑定this: 通过函数对象的bind()

    2. 箭头函数

  3. 状态数据,不能直接修改或更新

props

就像HTML标签的属性。

  1. 每个组件对象都会有props(properties的简写)属性

  2. 组件标签的所有属性都保存在props中

  3. 每个props都是只读的

作用:

  1. 通过标签属性从组件外向组件内传递变化的数据

  2. 注意: 组件内部不要修改props数据

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
    class Person extends React.Component {
        render() {
            return (
                <ul>
                    <li>姓名:{this.props.name}</li>
                    <li>年龄:{this.props.age}</li>
                    <li>性别:{this.props.sex}</li>
                </ul>
            );
        }
    }

    ReactDOM.render(
        <Person name="张三" age="12" sex="男"/>,
        document.getElementById('app')
    );
</script>
</body>
</html>

...批量传递props

下面的代码与上面的代码相同。

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
    class Person extends React.Component {
        render() {
            return (
                <ul>
                    <li>姓名:{this.props.name}</li>
                    <li>年龄:{this.props.age}</li>
                    <li>性别:{this.props.sex}</li>
                </ul>
            );
        }
    }

    const p = {name: "张三", age: "12", sex: "男"};
    ReactDOM.render(
        <Person {...p}/>,
        document.getElementById('app')
    );
</script>
</body>
</html>

对props进行限制

对上述组件的props添加指定的规则:

  1. name必传,且必须为字符串

  2. age可选,但是必须为数字类型,并给默认值0

  3. sex可选,并给默认值男

15版本的React,直接使用React.PropTypes.string,在16版本,需要引入新的prop-types.js模块:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script>
<script type="text/babel">
    class Person extends React.Component {
        render() {
            return (
                <ul>
                    <li>姓名:{this.props.name}</li>
                    <li>年龄:{this.props.age}</li>
                    <li>性别:{this.props.sex}</li>
                </ul>
            );
        }
    }
    // 定义Person组件的props的属性规则
    Person.prototype = {
        name: PropTypes.string.isRequired,
        age: PropTypes.number,
    }
    // 默认属性值
    Person.defaultPrototype = {
        age: 0,
        sex: "男",
    }

    ReactDOM.render(
        <Person name="张三" age={12} sex={"男"}/>,
        document.getElementById('app')
    );
</script>
</body>
</html>

或者将规则写到类内部:

class Person extends React.Component {
    static prototype = {
        name: PropTypes.string.isRequired,
        age: PropTypes.number,
    }

    static defaultPrototype = {
        age: 0,
        sex: "男",
    }

    render() {
        return (
            <ul>
                <li>姓名:{this.props.name}</li>
                <li>年龄:{this.props.age}</li>
                <li>性别:{this.props.sex}</li>
            </ul>
        );
    }
}

函数式组件使用props

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script>
<script type="text/babel">

    function Person(props){
        return (
            <ul>
                <li>姓名:{props.name}</li>
                <li>年龄:{props.age}</li>
                <li>性别:{props.sex}</li>
            </ul>
        );
    }

    // 定义Person组件的props的属性规则
    Person.prototype = {
        name: PropTypes.string.isRequired,
        age: PropTypes.number,
    }
    // 默认属性值
    Person.defaultPrototype = {
        age: 0,
        sex: "男",
    }

    ReactDOM.render(
        <Person name="张三" age={12} sex={"男"}/>,
        document.getElementById('app')
    );
</script>
</body>
</html>

refs

类似选择器,可以给标签增加ref属性,并通过this.refs、回调等形式,获取到指定的元素。

字符串形式的ref (废弃)

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script>
<script type="text/babel">
    class Bt extends React.Component {
        render() {
            return (
                <div>
                    <input type="text" ref="content"/>
                    <button onClick={this.sayHello}>获取内容</button>
                </div>
            );
        }

        sayHello = () => {
            let {content} = this.refs;
            console.log(this.refs)
            alert(content.value);
        }
    }

    ReactDOM.render(<Bt/>, document.getElementById("app"))
</script>
</body>
</html>

字符串类型的ref效率有问题,会在未来的版本中移除

回调形式的ref

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script>
<script type="text/babel">
    class Bt extends React.Component {
        render() {
            return (
                <div>
                    <input type="text" ref={(currentNode) => {this.input1 = currentNode}}/>
                    <button onClick={this.sayHello}>获取内容</button>
                </div>
            );
        }

        sayHello = () => {
            alert(this.input1.value);
        }
    }

    ReactDOM.render(<Bt/>, document.getElementById("app"))
</script>
</body>
</html>

crateRef() 推荐

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script>
<script type="text/babel">
    class Bt extends React.Component {

        contentRef = React.createRef()

        render() {
            return (
                <div>
                    <input type="text" ref={this.contentRef}/>
                    <button onClick={this.sayHello}>获取内容</button>
                </div>
            );
        }

        sayHello = () => {
            console.log(this.contentRef);
            alert(this.contentRef.current.value);
        }
    }

    ReactDOM.render(<Bt/>, document.getElementById("app"))
</script>
</body>
</html>

构造器

在React中,构造的主要作用有两个:

  1. state初始化

  2. 为事件处理函数绑定实例

  3. 如果需要props,那么一定要重写默认构造,并调用super(props),否则可能会出现undefined错误

ss://YWVzLTI1Ni1nY206ZmFCQW9ENTRrODdVSkc3@134.195.198.95:2375#github.com/freefq%20-%20%E5%8C%97%E7%BE%8E%E5%9C%B0%E5%8C%BA%20%2037  

最后更新于