简单demo
完成页面如上,父组件的state通过监听props实现同步,所以父组件的state和props是同步的,加一组件的state也监听props,所以当props发生变化时,加一组件的state也会发生变换化,但是加一按钮的触发事件是改变加一组件的state,而并没有改变props,所以会出现加一state增加而父组件state不增加(没有改变props所以父组件没有监听到);而减一按钮的触发事件为改变props,所以会导致所有通过监听props实现同步的state都发生变化,三个值都监听props。(具体逻辑看下面动图)
页面运行情况
点击加一按钮,只有加一组件的state会发生变化
点击减一按钮,所有数值发生变化
代码解析:
1、model(也就是存放同步props的地方)
export default {
namespace: 'example', //包名
state: {
number: 0, //用于同步的props
},
effects: {
*fetch({ payload }, { call, put }) { // eslint-disable-line
yield put({ type: 'save' });
},
},
reducers: {
add(state, action) {
return { ...state, number: action.payload };
//详情看扩展预算符
//简单理解就是将传入的number赋值给当前props的number变量,实现更新数据
//此处会导致number发生更新,也就是props发生了变化,所以有监听props的组件也会发生变化
},
},
};
2、indexPage(也就是初始页面)
import React, { Component } from 'react';
import { connect } from 'dva';
import styles from './IndexPage.css';
// 导入两个组件
import AddOne from '../components/AddOne';
import MinusOne from '../components/MinusOne';
class IndexPage extends Component {
constructor(props) {
super(props);
this.state = {
number: 0, // 组件的state,这里新建一个number变量
txtAdd: '加一',// 传入子组件的数据,按钮上的文字
txtMinus: '减一',
};
}
// react的生命周期,这个周期的作用是监听props的变化
// 这里监听的是props中的number变量
UNSAFE_componentWillReceiveProps(nextProps) {
// 监听到props发生变化后便将值和当前的state同步
this.setState({
number: nextProps.example.number, // 这里的exmaple是props的包名
});
}
render() {
return (
<div className={styles.normal} >
{/* 当前页面的state */}
<h1>父组件state: {this.state.number}</h1>
{/* props */}
<h1>父组件props: {this.props.example.number}</h1>
<div>
{/* 父组件可以通过下面这种形式将数据传入子组件 */}
<AddOne txtAdd={this.state.txtAdd} />
<MinusOne txtMinus={this.state.txtMinus} />
</div>
</div>
);
}
}
// 连接example Model
export default connect(({ example }) => {
return {
example,
};
},
)(IndexPage);
3、减一组件
import React, { Component } from 'react';
import { connect } from 'dva';
class MinusOne extends Component {
constructor(props) {
super(props);
this.state = {};
//方法需要进行绑定
this.btnMinus = this.btnMinus.bind(this);
}
// 减一方法按钮
btnMinus() {
// 通过dispatch方法可以将数据发送到model中
// type的格式为 ‘包名/reducenr名’
// payload用于传送数据
// 即这个方法的作用是将相关数据传送到相关的reducer里进行数据更新
this.props.dispatch({
type: 'example/add',
payload: this.props.example.number - 1,
});
}
render() {
return (
<div>
<button
style={{
margin: '50px',
}}
onClick={this.btnMinus}
>{this.props.txtMinus}</button>
</div>
);
}
}
export default connect(({ example }) => {
return {
example,
};
},
)(MinusOne);
加一组件
import React, { Component } from 'react';
import { connect } from 'dva';
class AddOne extends Component {
constructor(props) {
super(props);
this.state = {
number: 0, // 组件的state,这里新建一个number变量
};
//方法需要进行绑定
this.btnAdd = this.btnAdd.bind(this);
}
// react的生命周期,这个周期的作用是监听props的变化
// 这里监听的是props中的number变量
// 当减一按钮触发时候props发生了更新,这个方法就会监听到,同时更新页面的state
UNSAFE_componentWillReceiveProps(nextProps) {
this.setState({
number: nextProps.example.number, // 这里的exmaple是props的包名
});
}
// 加一按钮的方法,在这里可以进行逻辑运算
btnAdd() {
// state只能通过setstate进行改变,这里是将state中nunber变量进行+1
// 区别于减一按钮,此处并没有用dipatch方法发送给model
// 所以只有当前组件内的state进行了增加
this.setState({
number: this.state.number + 1,
})
}
render() {
return (
<div>
{/* 加一组件的state */}
<div>加一组件:{this.state.number}</div>
<button
style={{
margin: '50px',
}}
onClick={this.btnAdd}
// 用父组件传入的数据表示按钮上的文字
>{this.props.txtAdd}</button>
</div>
);
}
}
export default connect(({ example }) => {
return {
example,
};
},
)(AddOne);