state
只用于组件内部数据传递
首先要了解Virtual DOM (虚拟dom)是什么意思。
Virtual DOM 概况来讲,就是在数据和真实 DOM 之间建立了一层缓冲。对于开发者而言,数据变化了就调用 React 的渲染方法,而 React 并不是直接得到新的 DOM 进行替换,而是先生成 Virtual DOM,与上一次渲染得到的 Virtual DOM 进行比对,在渲染得到的 Virtual DOM 上发现变化,然后将变化的地方更新到真实 DOM 上。
就是说你不可用直接操作dom, 而是需要操作Virtual DOM
1 定义state 需要在构造函数中使用 this.state 即可。
2使用state 在jsx中 使用this.state.a 即可。
3改变state this.setState({a:this.state.a+1}) 即可(不能++)
class App extends Component {
constructor(){ //构造函数
super(); //必须执行的方法
this.state = { //定义
a:100,
b:200,
c:300
}
}
add(){ //改变
this.setState({a:this.state.a+1}) // 操作虚拟dom
}
render() {
return (
<div>// 使用
<p>{this.state.a}</p> //这里会根据点击来+1
<p>{this.state.b}</p>
<p>{this.state.c}</p>
<input type="button" value="点击" onClick={(this.add).bind(this)} /> //这里记得需要用到bind方法绑定
</div>
)
}
}
state只能在组件内部使用,在别的地点会报错。。。。。。。。
props
就是自定义在组件标签上的值就叫 props ,当props改变时才会使Virtual DOM 改变 从而改变真的视图。
1 props 定义 只需要在父组件定义即可
2 props 接收 只需要在子组件 this.props.a 即可接收
3 props 改变 这里不能直接改变需要通过传参改变state从而改变
父组件往子组件传值
<App a={12} /> //这里是我的父组件定义一个a=12。
class App extends Component {
constructor(props){ // 这里接收一个props参数,注意第一个参数一定是props
super();
this.state = {
a:props.a, //通过接收参数来定义一个state
b:200,
c:300
}
}
add(){
this.setState({a:this.state.a+1})//改变state
}
render() {
return (
<div>
<p>{this.props.a}</p> //从而改变dom
<p>{this.state.b}</p>
<p>{this.state.c}</p>
<input type="button" value="点击" onClick={(this.add).bind(this)} />
</div>
)
}
}
<p>{this.props.a}</p>//这是我的子组件 只需要 this.props.a即可接收到
这里还涉及到一个叫做PropTypes的东西,用来检测props传数据的类型
需要npm 下载和引入
App.propTypes = {
a: React.PropTypes.string.isRequired //isRequired设置 必传a属性。
b:React.PropTypes.number//不是必传属性
};
子组件修改父组件的值
想要在子组件修改父组件的值就有那么一点点困难了,
1首先我们在父组件定义好 a , b , c, d 四个属性值 其中d的值是通过当前组件state方法来定义的。
2然后在给父组件定义一个定义函数 add(number) ,add里面有一个参数。
3然后我们通过setState方法来让父组件的d赋值为number。
4然后还需要传一个add的函数过去。
//父组件
constructor(props){ //构造函数
super();
this.state = {
d:1111
}
}
add(number){
this.setState({'d':number})
}
render() {
return (
<div>
<h1>我有一个d状态他的值是{this.state.d}</h1>
<Navi a="12" b="12" c="11" d={this.state.d} add={(this.add.bind(this))} />
5 然后我们在子组件接收这个函数,然后通过传参的方法把值传到父组件,从而改变父组件的值。
//子组件
class Navi extends Component{
constructor(props){
super();
this.state = {
d:props.d
}
this.add=props.add
}
render() {
return (
<div>
<hr/>
<p>{this.props.a}</p>
<p>{this.state.d}</p>
<input type="button" value="点我改变d的值" onClick={()=>{this.add(8)}} />
</div>
)
}
}
context 上下文传递 (爷爷传递给孙子)
可以跨级传递数据,但是会降低组件的复用性,因为这些组件依赖“上下文”,。所有尽量只使用context传递登录状态、颜色主题等全局数据。
1 定义 引入 childContextTypes 。
2 接收 在孙子 使用 contextTypes 接收。
3 调用 在构造函数里面 constructor(props,context){ //第一个是props,第二个就是context。然后state 定义就可以调用。
}
// 爷爷. childContextTypes
Yeye.childContextTypes = { //定义
a: ProTypes.string.isRequired;
}
Sunzi.contextTypes = {
a: ProTypes.string.isRequired; // 接收
}
4如果要使用子孙元素改变爷爷元素,就可以使用上面 props一样在context 里面定义一个函数 然后逻辑一样了。