在 React 当中, 当你更新组件的 state, 然后新的 state 就会重新渲染到页面中. 在这个时候不需要你操作任何 DOM. 你也可以认为组件在 React 当中是一个状态机 (State Machines). 当用户进行操作时会实现不同的状态, 然后再渲染到你的页面中, 让你的页面与数据始终保持一致.
如何定义 State
定义一个合适的 State, 是正确创建组件的第一步. State 必须能代表一个组件 UI 呈现的完整状态集, 即组件的任何 UI 改变, 都可以从 State 的变化中反映出来; 同时, State 还必须是代表一个组件 UI 呈现的最小状态集, 即 State 中的所有状态都是用于反映组件 UI 的变化, 没有任何多余的状态, 也不需要通过其他状态计算而来的中间状态.
组件中用到的一个变量是不是应该作为组件 State, 可以通过下面的 4 条依据进行判断:
1. 这个变量是否是通过 Props 从父组件中获取? 如果是, 那么它不是一个状态.
2. 这个变量是否在组件的整个生命周期中都保持不变? 如果是, 那么它不是一个状态.
3. 这个变量是否可以通过其他状态 (State) 或者属性 (Props) 计算得到? 如果是, 那么它不是一个状态.
4. 这个变量是否在组件的 render 方法中使用? 如果不是, 那么它不是一个状态. 这种情况下, 这个变量更适合定义为组件的一个普通属性, 例如组件中用到的定时器, 就应该直接定义为 this.timer, 而不是 this.state.timer.
如果对状态不好理解的朋友, 你可以认为状态即是数据!
State 与 Props 区别
props 是组件对外的接口, state 是组件对内的接口. 组件内可以引用其他组件, 组件之间的引用形成了一个树状结构 (组件树), 如果下层组件需要使用上层组件的数据或方法, 上层组件就可以通过下层组件的 props 属性进行传递, 因此 props 是组件对外的接口. 组件除了使用上层组件传递的数据外, 自身也可能需要维护管理数据, 这就是组件对内的接口 state. 根据对外接口 props 和对内接口 state, 组件计算出对应界面的 UI.
主要区别:
State 是可变的, 是一组用于反映组件 UI 变化的状态集合;
而 Props 对于使用它的组件来说, 是只读的, 要想修改 Props, 只能通过该组件的父组件修改.
在组件状态上移的场景中, 父组件正是通过子组件的 Props, 传递给子组件其所需要的状态
现在我们先来通过 ES6 类 React.Component 完成一个通过点击按钮对 DIV 进行显示与隐藏的操作, 效果如下:
咱们先将页面进行初始化:
- <!DOCTYPE html>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- #myDiv{
- width:200px;
- height:400px;
- background:red;
- color:yellow;
- border:1px solid green;
- }
- </style>
- <script src="https://zhangpeiyue.com/wp-content/uploads/2018/08/react.development.JS"></script>
- <script src="https://zhangpeiyue.com/wp-content/uploads/2018/08/react-dom.development.JS"></script>
- <script src="https://zhangpeiyue.com/wp-content/uploads/2018/08/babel.min_.JS"></script>
- </head>
- <body>
- <div id="wrap"></div>
- </body>
- <script type="text/babel">
- class MyComponent extends React.Component{
- constructor(props){
- super(props);
- // 为当前状态添加 isShow 属性
- this.state={
- // 值为 true 显示, false 为隐藏. 默认值为 true.
- isShow:true
- }
- }
- render(){
- // 返回组件的初始内容
- return <div>
- <input type="button" value="显示与隐藏"/>
- <div id="myDiv"> 我在这里呀!</div>
- </div>
- }
- }
- ReactDOM.render(
- <MyComponent/>,
- document.querySelector("#wrap")
- )
- </script>
- </HTML>
到目前为止, 页面已经初始化完毕了. 在上面的代码中为 state 添加了一个默认值为 true 的属性 isShow.isShow 用来控制 div 的显示与隐藏! 当 isShow 为 true 时显示, 为 false 时隐藏
接下来要完成的二件事.
第一件事是要为按钮增加一个点击事件, 事件与 changeState 方法进行绑定. 当点击按钮时改变 isShow 的状态, 也就是要为 isShow 进行取反操作.
注意:
1,onClick 中的 c 要大写.
2,onClick 后跟的方法不要用引号包裹, 而是用 {}
3, 在 ES6 的 class 中 React 是不会自动绑定 this 的, 所以需要自己通过 bind 绑定.
4,changeState 方法中, 不能直接修改 isShow 的值, 而是需要借助 setState 方法来进行设置.
第二件事是要为 id 为 myDiv 的 DIV 增加一个 style 属性, 该属性要根据 isShow 的状态来对 DIV 进行显示与隐藏
注意:
1,style 的值不要用双引号, 而是用 {}, 否则会报错
最终版代码:
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- #myDiv{
- width:200px;
- height:400px;
- background:red;
- color:yellow;
- border:1px solid green;
- }
- </style>
- <script src="https://zhangpeiyue.com/wp-content/uploads/2018/08/react.development.JS"></script>
- <script src="https://zhangpeiyue.com/wp-content/uploads/2018/08/react-dom.development.JS"></script>
- <script src="https://zhangpeiyue.com/wp-content/uploads/2018/08/babel.min_.JS"></script>
- </head>
- <body>
- <div id="wrap"></div>
- </body>
- <script type="text/babel">
- class MyComponent extends React.Component{
- constructor(props){
- super(props);
- // 为当前状态添加 isShow 属性
- this.state={
- // 值为 true 显示, false 为隐藏. 默认值为 true.
- isShow:true
- }
- }
- changeState(){
- // 此处不能直接修改 isShow 的值. 而是需要借助 setState 方法!
- this.setState({
- // 取反操作
- isShow:!this.state.isShow
- });
- }
- render(){
- // 返回组件的初始内容
- return <div>
- {/* 在 ES6 的 class 中 React 是不会自动绑定 this 的, 所以需要自己绑定 */}
- <input type="button" value="显示与隐藏" onClick={this.changeState.bind(this)} />
- <div id="myDiv" style={{display:this.state.isShow?'block':'none'}}> 我在这里呀!</div>
- </div>
- }
- }
- ReactDOM.render(
- <MyComponent/>,
- document.querySelector("#wrap")
- )
- </script>
- </HTML>
由上面的示例可以发现, 当你改变 isShow 的状态时, div 也会发生相对应的变化!
来源: http://www.jb51.net/article/147705.htm