前提:DvaJS快速上手(2)
簡單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);