问题:当一个子组件修改了全局变量,并没有通知其他组件时,其他组件不知道这个值改变了
http://js.jirengu.com/lipadokebu/2/edit?html,js,output
声明eventHub
eventHub作为事件中心,实现订阅和发布功能
let fnLists = {}let eventHub = {trigger(eventName, data){let fnList = fnLists[eventName]if(!fnList) returnfor(let i=0; i < fnList.length; i++){fnList[i](data)}},on(eventName, fn){if(!fnLists[eventName]){fnLists[eventName] = []}fnLists[eventName].push(fn)}}
声明一个管家,init初始化,先把”我要花钱”事件名和对应的函数fn插入到fnLists
let x = {init(){// 先把事件名和函数插入fnListseventHub.on('我要花钱', function(data){money.amount -= datarender()})}}x.init()
只有根组件知道money, 并通过props传给其他组件
class App extends React.Component {constructor(){super()this.state = {money: money}}render(){return (<div className="root"><Bigpa money={this.state.money}/><Secpa money={this.state.money}/></div>)}}class Bigpa extends React.Component {constructor(){super()}render(){return (<div className="papa">Bigpa {this.props.money.amount}<Son1 money={this.props.money}/><Son2 money={this.props.money}/></div>)}}class Son2 extends React.Component {constructor(){super()}comsume(){eventHub.trigger('我要花钱', 100) // 触发事件}render(){return (<div className="son">Son2 {this.props.money.amount}<button onClick={()=>this.comsume()}>消费</button></div>)}}
当子组件eventHub.trigger('我要花钱', 100) 时,就会调用fnLists里对应的函数,更新money的值,
调用render()渲染到页面(React只会更新变化了的部分)
http://js.jirengu.com/lipadokebu/3/edit?html,js,output
引入Redux, Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
概念:
用store存储所有数据
let money = {amount: 100000}let user = {id: 123232,nickname: '土豪'}let store = {money: money,user: user}
eventHub.trigger是action
第一个参数是action type, 第二个参数是payload
// actioneventHub.trigger('我要花钱' /*action type*/, 100 /*payload*/)
eventHub.on是subscribe
on里数据操作是reducer
eventHub.on('我要花钱', function(data){ // subscribemoney.amount -= data // reducerrender()})
看官方实例学习
使用Redux创建store
let createStore = Redux.createStorelet reducers = (state, action) => {state = state || {money: {amount: 100000}}switch (action.type) {case '我要花钱':return {money: {amount: state.money.amount - action.payload}}default:return state}}const store = createStore(reducers)console.log(store.getState())
dispatch触发action
comsume(){// eventHub.trigger('我要花钱', 100)store.dispatch({type: '我要花钱', payload: 100})}
subscribe并render
function render(){ReactDOM.render(<App store={store.getState()}/>, document.querySelector("#root"))}render()store.subscribe(()=>render())
注意数据改用props传给App
http://js.jirengu.com/qabefirulo/1/edit?html,js,output
Redux的意义
事件名自定义,在reducers里列好
state是只读的,没办法用App里的state,但也没办法阻止组件修改根数据(JS毛病)
阻止猪队友
1. 使用 eventHub/eventBus 来通信
一个组件监听某个事件,另一个组件触发相同的事件并传参,即可实现两个组件的通信
缺点是事件容易越来越多,不好控制代码的复杂度
2. 使用 Redux
每次操作触发一个 action
action 会触发对应的 reducer
reducer 会用旧的 state 和 action 造出一个新的 state
使用 store.subscribe 监听 state 的变化,一旦 state 变化就重新 render(render 会做 DOM diff,确保只更新该更新的 DOM)
