北京建网站公司飞沐,微信腾讯会议,静态网页模板下载后怎么修改,怎么做垂直网站目录 一、何为State二、如何定义State三、如何判断是否为State四、如何正确使用State1、用setState修改State2、State的更新是异步的①、代码示例 3、State更新会被合并①、组件状态例子②、当只需要修改状态title时#xff0c;只需要将修改后的title传给setState③、React会合… 目录 一、何为State二、如何定义State三、如何判断是否为State四、如何正确使用State1、用setState修改State2、State的更新是异步的①、代码示例 3、State更新会被合并①、组件状态例子②、当只需要修改状态title时只需要将修改后的title传给setState③、React会合并新的title到原来的组件状态中同时保留原有的状态content 4、setState里顺序更新 五、根据State类型更新1、状态的类型是不可变类型数字字符串布尔值nullundefined2、状态的类型是数组①、增加②、截取③、条件过滤 3、状态的类型是普通对象不包含字符串、数组①、使用ES6的Object.assgin方法②、使用对象扩展语法Object spread properties 六、State向下流动七、State与Props区别1、Props2、State3、二者区别 八、Props的使用1、props属性默认为“true”2、props扩展 一、何为State
React 的核心思想是组件化而组件中最重要的概念是State状态State是一个组件的UI数据模型是组件渲染时的数据依据。 状态state 和 属性props 类似都是一个组件所需要的一些数据集合但是state是私有的可以认为state是组件的“私有属性或者是局部属性”。
二、如何定义State
定义一个合适的State是正确创建组件的第一步。State必须能代表一个组件UI呈现的完整状态集即组件的任何UI改变都可以从State的变化中反映出来同时State还必须是代表一个组件UI呈现的最小状态集即State中的所有状态都是用于反映组件UI的变化没有任何多余的状态也不需要通过其他状态计算而来的中间状态
三、如何判断是否为State
组件中用到的一个变量是不是应该作为组件State可以通过下面的4条依据进行判断
这个变量是否是通过Props从父组件中获取如果是那么它不是一个状态。这个变量是否在组件的整个生命周期中都保持不变如果是那么它不是一个状态。这个变量是否可以通过其他状态State或者属性(Props)计算得到如果是那么它不是一个状态。这个变量是否在组件的render方法中使用如果不是那么它不是一个状态。这种情况下这个变量更适合定义为组件的一个普通属性例如组件中用到的定时器就应该直接定义为this.timer而不是this.state.timer。 并不是组件中用到的所有变量都是组件的状态当存在多个组件共同依赖一个状态时一般的做法是状态上移将这个状态放到这几个组件的公共父组件中。 四、如何正确使用State
1、用setState修改State 直接修改state组件并不会重新触发render() import React, { Component } from reactexport default class stateStudy extends Component {state {myText: 收藏,}render() {return (divh1欢迎来到React开发/h1button onClick{() {this.state({myText: 取消收藏})}}{this.state.myText}/button/div)}
} 这时点击收藏时报状态不是一个函数 正确的修改方式是使用setState() import React, { Component } from reactexport default class stateStudy extends Component {state {myText: 收藏,myTextShow: true}render() {return (divh1欢迎来到React开发/h1button onClick{() {this.setState({myTextShow: !this.state.myTextShow})}}{this.state.myTextShow ? 收藏 : 取消收藏}/button/div)}
} 2、State的更新是异步的
调用setState后setState会把要修改的状态放入一个队列中因而组件的state并不会立即改变之后React会优化真正的执行时机来优化性能所以优化过程中有可能会将多个setState的状态修改合并为一次状态修改因而state更新可能是异步的所以不要依赖当前的state计算下个State。当真正执行状态修改时依赖的this.state并不能保证是最新的State因为React会把多次State的修改合并成一次这时this.state将还是这几次State修改前的State 另外需要注意同样不能依赖当前的Props计算下个状态因为Props一般也是从父组件的State中获取依然无法确定在组件状态更新时的值 ①、代码示例 现在渲染一个button想每点击一下counter就3 class App extends React.Component {state {counter: 0,}handleClick () {const { counter } this.state;//或者 const counter this.state.counter;this.setState({ counter: counter 1 });this.setState({ counter: counter 1 });this.setState({ counter: counter 1 });}render() {return (divcounter is: {this.state.counter}button onClick{this.handleClick} 点我/button/div)}
}
ReactDOM.render(App /, document.getElementById(root)); 之所以1不是3是因为state的更新可能是异步的React会把传入多个setState的多个Object”batch“起来合并成一个。合并成一个就相当于把传入setState的多个Object进行shallow merge像这样 const update {counter: counter 1,counter: counter 1,counter: counter 1//因为上面三句话都一样所以会当一句话执行} 想要实现3的效果就可以按照下面的方式进行实现 class App extends React.Component {state {counter: 0,}handleClick () {this.setState(prev ({ counter: prev.counter 1 }));this.setState(prev ({ counter: prev.counter 1 }));this.setState(prev ({ counter: prev.counter 1 }));//这样是错的 this.setState(prev {counter: prev.counter 1});//这样是错的 this.setState(prev {counter:prev.counter});//这样是错的 this.setState(prev {counter:prev.counter});}render() {return (divcounter is: {this.state.counter}button onClick{this.handleClick} 点我/button/div)}
}
ReactDOM.render(App /, document.getElementById(root));
之所以成功是因为传入多个 setState 的多个 Object 会被 shallow Merge而传入多个 setState 的多个 function 会被 “queue” 起来queue 里的 function 接收到的 state(上面是 prev )都是前一个 function 操作过的 state。
3、State更新会被合并
①、组件状态例子
this.state {title : React,content : React is an wonderful JS library!
}
②、当只需要修改状态title时只需要将修改后的title传给setState
this.setState({title: Reactjs});
③、React会合并新的title到原来的组件状态中同时保留原有的状态content 合并后的State为 {title : Reactjs,content : React is an wonderful JS library!
}
4、setState里顺序更新 //history 为数组this.setState({history: history.concat([1]), //(1)current: history.length, //(2)nextPlayer: !nextPlayer, //(3)}); 执行setState时先更新history然后再用更新改变后的history计算current的值最后再更新nextPlayer 五、根据State类型更新 当状态发生变化时如何创建新的状态根据状态的类型分为以下三种情况 1、状态的类型是不可变类型数字字符串布尔值nullundefined 这种情况最简单直接给要修改的状态赋一个新值即可 //原state
this.state {count: 0,title : React,success:false
}
//改变state
this.setState({count: 1,title: bty,success: true
})
2、状态的类型是数组
数组是一个引用React 执行 diff 算法时比较的是两个引用而不是引用的对象。所以直接修改原对象引用值不发生改变的话React 不会重新渲染。因此修改状态的数组或对象时要返回一个新的数组或对象。
①、增加
如有一个数组类型的状态books当向books中增加一本书(chinese)时使用数组的concat方法或ES6的数组扩展语法
// 方法一将state先赋值给另外的变量然后使用concat创建新数组
let books this.state.books;
this.setState({books: books.concat([chinese])
})// 方法二使用preState、concat创建新数组
this.setState(preState ({books: preState.books.concat([chinese])
}))// 方法三ES6 spread syntax
this.setState(preState ({books: [...preState.books, chinese]
}))
②、截取
当从books中截取部分元素作为新状态时使用数组的slice方法
// 方法一将state先赋值给另外的变量然后使用slice创建新数组
let books this.state.books;
this.setState({books: books.slice(1,3)
})
//
// 方法二使用preState、slice创建新数组
this.setState(preState ({books: preState.books.slice(1,3)
}))
③、条件过滤
当从books中过滤部分元素后作为新状态时使用数组的filter方法
// 方法一将state先赋值给另外的变量然后使用filter创建新数组
var books this.state.books;
this.setState({books: books.filter(item {return item ! React; })
})// 方法二使用preState、filter创建新数组
this.setState(preState ({books: preState.books.filter(item {return item ! React; })
})) 注意不要使用push、pop、shift、unshift、splice等方法修改数组类型的状态因为这些方法都是在原数组的基础上修改而concat、slice、filter会返回一个新的数组。 3、状态的类型是普通对象不包含字符串、数组
对象是一个引用React执行diff算法时比较的是两个引用而不是引用的对象所以直接修改原对象引用值不发生改变的话React不会重新渲染。因此修改状态的数组或对象时要返回一个新的对象
①、使用ES6的Object.assgin方法
// 方法一将state先赋值给另外的变量然后使用Object.assign创建新对象
var owner this.state.owner;
this.setState({owner: Object.assign({}, owner, {name: Jason})
})// 方法二使用preState、Object.assign创建新对象
this.setState(preState ({owner: Object.assign({}, preState.owner, {name: Jason})
}))
②、使用对象扩展语法Object spread properties
// 方法一将state先赋值给另外的变量然后使用对象扩展语法创建新对象
var owner this.state.owner;
this.setState({owner: {...owner, name: Jason}
})// 方法二使用preState、对象扩展语法创建新对象
this.setState(preState ({owner: {...preState.owner, name: Jason}
})) 综上所述创建新的状态对象的关键是避免使用会直接修改原对象的方法而是使用可以返回一个新对象的方法。 六、State向下流动 我们说 props 是组件对外的接口state 是组件对内的接口。 一个组件可以选择将 state(状态) 向下传递作为其子组件的 props(属性) MyComponent title{this.state.title}/
这通常称为一个“从上到下”或者“单向”的数据流。任何 state(状态) 始终由某个特定组件所有并且从该 state(状态) 导出的任何数据 或 UI 只能影响树中 “下方” 的组件。
如果把组件树想像为 props(属性) 的瀑布所有组件的 state(状态) 就如同一个额外的水源汇入主流且只能随着主流的方向向下流动。
七、State与Props区别
1、Props
props是指组件间传递的一种方式props自然也是可以传递state的。因为React的数据流是自上而下的所以是从父组件向子组件进行的传递另外组件内部的this.props属性是只读的不可修改
2、State
state不同于props的一点是state是可以被改变的。不过不可以直接通过this.state的方式来修改而是需要通过this.setState()方法来修改state
3、二者区别
props是传递给组件的类似于函数的形参、是不可修改的state是在组件内被组件自己管理的类似于在一个函数内声明的变量是多变的、可修改的每次setState都异步更新
八、Props的使用
当一个组件被注入一些属性Props 值时属性值来源于它的父级元素所以人们常说属性在 React 中是单向流动的从父级到子元素
1、props属性默认为“true”
如果你没给 prop(属性) 传值那么他默认为 true 。下面两个 JSX 表达式是等价的
MyTextBox autocomplete /
MyTextBox autocomplete{true} /
通常情况下我们不建议使用这种类型因为这会与ES6中的对象shorthand混淆 。ES6 shorthand 中 {foo} 指的是 {foo: foo} 的简写而不是 {foo: true} 。这种行为只是为了与 HTML 的行为相匹配。 举个例子在 HTML 中 input type“radio” value“1” disabled / 与 input type“radio” value“1” disabled“true” / 是等价的。JSX 中的这种行为就是为了匹配 HTML 的行为。 2、props扩展
如果你已经有一个 object 类型的 props并且希望在 JSX 中传入你可以使用扩展操作符 … 传入整个 props 对象。这两个组件是等效的
function App1() {return Greeting firstNameBen lastNameHector /;
}function App2() {const props {firstName: Ben, lastName: Hector};return Greeting {...props} /;
}
显然下面的方法更方便因为它将数据进行了包装而且还简化了赋值的书写