React中组建实例的三大属性(state,props,refs)

223 阅读1分钟

1.state描述:

	1.state是组件对象最重要的属性,值是对象,(可以包含多个,key-value的组合)
	2.组件被称为“状态机”,通过更新组件的state来更新对应的页面显示(重新渲染组件)
	3.严重注意,状态必须通过setState更新,且更新是一种合并,不是覆盖

1.2.state完整写法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!-- 准备好一个容器 -->
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script src="../js/react.development.js"></script>
    <!-- 引入react-dom用于支持react操作dom -->
    <script src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../js/babel.min.js"></script>

    <script type="text/babel">
        // 1.创建组件
            class Weather extends React.Component{
                // 构造器调用几次———— 有一个实例,只调用一次
                constructor(props){
                    console.log('constructor');
                    super(props);
                    // 初始化状态
                    this.state = {
                        isHot:true,
                        wind:'微风'
                    };
                    // 解决changeWeather 中this的指向问题
                    this.changeWeather = this.changeWeather.bind(this);
                }

                    // render调用几次? —— 1+n次  1是初始化的那次,n状态更新的次数
                render(){
                    // 读取状态
                    console.log(this);
                    return <h1 onClick={this.changeWeather}>今天天气很{this.state.isHot?'炎热':'凉爽'},{this.state.wind} </h1>
                }

                // changeWeather调用几次? —— 点几次调用几次,点几次调用几次
             changeWeather(){
                //  changeWeather放在哪里,————Weather的原型对象上
                // 由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
                // 类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
                 console.log(this);
                //  获取原来的isHot值
                const isHot = this.state.isHot;
                // 严重注意状态(state)不可直接更改,下面就是直接更改,需要借助内置api进行更改
                // this.state.isHot = !isHot;  //错误写法
                // console.log(this.state.isHot);
                // 严重注意,状态必须通过setState更新,切更新是一种合并,不是覆盖
                this.setState({isHot:!isHot})
              }

 }
            // 2.渲染组件到页面
            ReactDOM.render(<Weather/>,document.getElementById('test'));

   
        </script>
</body>

</html>

点击事件有三种调用方式,react更推荐使用第三种,

<button id="btn1">按钮1</button>
<button id="btn2">按钮2</button>
<button onclick="demo()">按钮3</button>

<script type="text/javascript">
    const btn1 = document.getElementById('btn1');
    btn1.addEventListener('click',()=>{
        alert('按钮1被点击了');
    })

    const btn2 = document.getElementById('btn2');
    btn2.onclick = ()=>{
            alert('按钮2被点击了');
    }

     function demo(){
            alert('按钮3被点击了');
    }
</script>

1.3 state简写

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

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

<body>
    <!-- 准备好一个容器 -->
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script src="../js/react.development.js"></script>
    <!-- 引入react-dom用于支持react操作dom -->
    <script src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../js/babel.min.js"></script>

    <script type="text/babel">
        // 1.创建组件
            class Weather extends React.Component{
                // constructor(props){
                //     super(props);
                //     // this.state = {
                //     //     isHot:true,
                //     //     wind:'微风'
                //     // };
                //     // this.changeWeather = this.changeWeather.bind(this);
                // }
            // 初始化状态
                state = {  isHot:true,  wind:'微风'};

                render(){
                   
                    return <h1 onClick={this.changeWeather}>今天天气很{this.state.isHot?'炎热':'凉爽'},{this.state.wind} </h1>
                }

            //    自定义方法————要用赋值语句+箭头函数
             changeWeather = ()=>{
                const isHot = this.state.isHot;
                this.setState({isHot:!isHot})
              }
            }
            
            ReactDOM.render(<Weather/>,document.getElementById('test'));

    
        </script>
</body>

</html>

2.1对props进行限制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="test1"></div>
    <div id="test2"></div>
    <div id="test3"></div>

    <!-- 引入react核心库 -->
    <script src="../js/react.development.js"></script>
    <!-- 引入react-dom,用于支持 react操作dom-->
    <script src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为 js-->
    <script src="../js/babel.min.js"></script>
    <!-- 引入prop-Types,用于对组件标签属性进行限制 -->
    <script src="../js/prop-types.js"></script>


    <script type="text/babel">
        // 1.创建组件
        class Person extends React.Component{
            render(){
                console.log(this);
                // props是只读的
                const {name,age,sex} = this.props;
                // this.props.name='jack' 
                return (
                    <ul>
                         <li>姓名:{name}</li>
                         <li>性别:{sex}</li>
                         <li>年龄:{age+1}</li>
                    </ul>
                )
            }
        }
        // 对标签属性进行类型,必要性的限制
        Person.propTypes = {
            name:PropTypes.string.isRequired,  //限制name必传,且为字符串
            sex:PropTypes.string,   //限制sex为字符串
            age:PropTypes.number,   //限制age为数值
            speak:PropTypes.func,    //限制speak为函数
        }
        // 指定默认标签属性值
        Person.defaultProps={
            sex:'男',  //sex的默认值为男
            age:0    //age默认值为18
        }

        // 2.渲染组件到页面
            ReactDOM.render(<Person name="tom" speak={speak} />,document.getElementById('test1'));
            ReactDOM.render(<Person name="jerry" age={20} sex="男"/>,document.getElementById('test2'));

            const p ={name:'老刘',age:18,sex:'女'};

            // ReactDOM.render(<Person name={p.name} age={p.age} sex={p.sex}/>,document.getElementById('test3'));
            ReactDOM.render(<Person {...p}/>,document.getElementById('test3'));
    
        function speak(){
            console.log('我说话了');
        }
    
    </script>
</body>
</html>

2.2props对限制的简写

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

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

<body>
    <!-- 准备好一个容器 -->
    <div id="test1"></div>
    <div id="test2"></div>
    <div id="test3"></div>

    <!-- 引入react核心库 -->
    <script src="../js/react.development.js"></script>
    <!-- 引入react-dom,用于支持 react操作dom-->
    <script src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为 js-->
    <script src="../js/babel.min.js"></script>
    <!-- 引入prop-Types,用于对组件标签属性进行限制 -->
    <script src="../js/prop-types.js"></script>


    <script type="text/babel">
        // 1.创建组件
        class Person extends React.Component{

        constructor(props){
            // 构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
            super();
            console.log('constructor',this.props);
        }

              // 对标签属性进行限制,必要性的限制
         static  propTypes = {
            name:PropTypes.string.isRequired,  //限制name必传,且为字符串
            sex:PropTypes.string,   //限制sex为字符串
            age:PropTypes.number,   //限制age为数值
            speak:PropTypes.func,   //限制speak为函数
             }

            // 指定默认标签属性值
         static  defaultProps={
            sex:'男',  //sex的默认值为男
            age:0    //age默认值为18
        }
        
        render(){
                console.log(this);
                // props是只读的
                const {name,age,sex} = this.props;
                // this.props.name='jack'   //此行代码会报错,因为props是只读的
                return (
                    <ul >
                         <li>姓名:{name}</li>
                         <li>性别:{sex}</li>
                         <li>年龄:{age+1}</li>
                    </ul>
                )
            }

            
        }
      
       
        // 2.渲染组件到页面
            ReactDOM.render(<Person name="tom" speak={speak} />,document.getElementById('test1'));
            ReactDOM.render(<Person name="jerry" age={20} sex="男"/>,document.getElementById('test2'));

            const p ={name:'老刘',age:18,sex:'女'};

            // ReactDOM.render(<Person name={p.name} age={p.age} sex={p.sex}/>,document.getElementById('test3'));
            ReactDOM.render(<Person {...p}/>,document.getElementById('test3'));
    
        function speak(){
            console.log('我说话了');
        }
    
    </script>
</body>

</html>

2.3函数式组件使用props

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script src="../js/react.development.js"></script>
    <!-- 引入react-dom,用于支持 react操作dom-->
    <script src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为 js-->
    <script src="../js/babel.min.js"></script>
    <!-- 引入prop-Types,用于对组件标签属性进行限制 -->
    <script src="../js/prop-types.js"></script>

    <script type="text/babel">
    // 1.创建组件
        function Person(props){
            console.log(props);
            const {name,age,sex} = props
            return (
                <ul>
                    <li>姓名:{name}</li>
                    <li>性别:{sex}</li>
                    <li>年龄:{age}</li>
                </ul>
            )
        }

        // 只能这样限制
        // 对标签属性进行类型,必要性的限制
          Person.propTypes = {
            name:PropTypes.string.isRequired,  //限制name必传,且为字符串
            sex:PropTypes.string,   //限制sex为字符串
            age:PropTypes.number,   //限制age为数值
            speak:PropTypes.func,    //限制speak为函数
        }
        // 指定默认标签属性值
        Person.defaultProps={
            sex:'男',  //sex的默认值为男
            age:0    //age默认值为0
        }


        // 2.渲染组件到页面

        ReactDOM.render(<Person name="jerry" sex="女" />,document.getElementById('test'));

    </script>
</body>
</html>

3.1字符串形式的refs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <!-- 准备好一个容器 -->
    <div id="test"></div>

      <!-- 引入react核心库 -->
      <script src="../js/react.development.js"></script>
      <!-- 引入react-dom,用于支持 react操作dom-->
      <script src="../js/react-dom.development.js"></script>
      <!-- 引入babel,用于将jsx转为 js-->
      <script src="../js/babel.min.js"></script>

      <script type="text/babel">
        // 1.创建组件
        class Demo extends React.Component{
            render(){
                return(
                    <div>
                        <input  ref="input1" type="text" placeholder="点击按钮提示数据"/> &nbsp;
                        <button    onClick={this.showData}>点我提示左侧数据</button> &nbsp;
                        <input ref="input2" onBlur={this.showData2}  type="text"  placeholder="失去焦点提示数据" />
                    </div>
                )
            }
            // 展示左侧输入框的数据
            showData = ()=>{
                // 函数体
               console.log(this);
               const {input1} =this.refs;
               alert(input1.value);
            }
            // 展示右侧输入框的数据
            showData2 = ()=>{
                const {input2} = this.refs;
                alert(input2.value);
            }
        }
        // 2.渲染组件到页面
        ReactDOM.render(<Demo/>,document.getElementById('test'));
      </script>
</body>
</html>

3.2回调函数形式的ref

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <!-- 准备好一个容器 -->
    <div id="test"></div>

      <!-- 引入react核心库 -->
      <script src="../js/react.development.js"></script>
      <!-- 引入react-dom,用于支持 react操作dom-->
      <script src="../js/react-dom.development.js"></script>
      <!-- 引入babel,用于将jsx转为 js-->
      <script src="../js/babel.min.js"></script>

      <script type="text/babel">
        // 1.创建组件
        class Demo extends React.Component{
            state = {isHot:true};
            render(){
                const {isHot} = this.state
                return(
                    <div>
                        <h1 >今天天气很{isHot===true?'凉爽':'炎热'} </h1>
                      {/* <input  ref={(cNode)=>{this.input1=cNode;console.log('#',cNode)}} type="text" placeholder="点击按钮提示数据"/> &nbsp; */}
                      <input  ref={this.saveInput} type="text" placeholder="点击按钮提示数据" /> &nbsp;
                      <button onClick={this.showData}>点我提示数据</button> &nbsp;
                        <button onClick={this.changeData}>点我切换天气</button>
                    </div>
                )
            }
            saveInput = (cNode)=>{
                this.input1 = cNode;
                console.log('@',cNode);
            }

            changeData = ()=>{
                const {isHot} = this.state
               this.setState({isHot:!isHot});
               
            }
            // 展示左侧输入框的数据
            showData = ()=>{
                // 函数体

               const {input1} =this;
               alert(input1.value);
            }
        
        }
        // 2.渲染组件到页面
        ReactDOM.render(<Demo/>,document.getElementById('test'));
      </script>
</body>
</html>

3.3回调ref执行的次数问题

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 准备好一个容器 -->
        <div id="test"></div>

        <!-- 引入react核心库 -->
        <script src="../js/react.development.js"></script>
        <!-- 引入react-dom,用于支持react操作DOM -->
        <script src="../js/react-dom.development.js"></script>
        <!-- 引入babel,用于将jsx转为js -->
        <script src="../js/babel.min.js"></script>

        <script type="text/babel">
            // 创建组件
        class Demo extends React.Component{
            state= {isHot:false}

            render(){
                return(
                    <div>
                        <h2>今天天气很{this.state.isHot?'炎热':'凉爽'}</h2>
                     <input type="text" ref={(currentNode)=>{this.input1=currentNode;console.log('#',currentNode)}} />
                    <button onClick={this.showInfo}>点我提示输入的数据</button>   
                    <button onClick={this.changeWeather}>点我改变天气</button> 
                    </div>
                )
            }
            showInfo = ()=>{
                const {input1} = this;
                console.log(input1);
                alert(input1.value);
            }
            changeWeather = ()=>{
                const {isHot}= this.state;
                console.log(this);
                this.setState({isHot:!isHot});
            }
        }
        // 渲染组件到页面
        ReactDOM.render(<Demo/>, document.getElementById('test'));

        </script>
</body>
</html>

ref先执行一次空,然后再得到真实的dom,这是因为react每次运行完都清空了ref

3.4createRef

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 创建容器 -->
    <div id="test"></div>

    <!-- 引入react基础库 -->
    <script src="../js/react.development.js"></script>
    <!-- 引入react-dom库 用于支持react操作dom -->
    <script src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script src="../js/babel.min.js"></script>

    <script type="text/babel">
        // 创建组件
    class Demo extends React.Component{
        myRef = React.createRef();
        myRef2 = React.createRef();
        // react.createRef调用后可以返回一个容器,该容器可以存储被ref标记的节点
        // 该容器是ref专用
        render(){
            return(
                <div>
                <input  ref={this.myRef}   type="text"  placeholder="点击时触发"/>
                <button onClick={this.showData}>点我提示左侧数据</button>
                <input  ref={this.myRef2}  onBlur={this.showData2}  type="text" placeholder="鼠标离开时触发" />
                </div>
            )
        }

        showData = ()=>{
           alert(this.myRef.current.value);

        }
        showData2 = ()=>{
        alert(this.myRef2.current.value);
        }
    }

    // 渲染组件到页面
    ReactDOM.render(<Demo/>,document.getElementById('test'));
    </script>

</body>
</html>