问题:当一个子组件修改了全局变量,并没有通知其他组件时,其他组件不知道这个值改变了
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) return
for(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(){
// 先把事件名和函数插入fnLists
eventHub.on('我要花钱', function(data){
money.amount -= data
render()
})
}
}
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
// action
eventHub.trigger('我要花钱' /*action type*/, 100 /*payload*/)
eventHub.on是subscribe
on里数据操作是reducer
eventHub.on('我要花钱', function(data){ // subscribe
money.amount -= data // reducer
render()
})
看官方实例学习
使用Redux创建store
let createStore = Redux.createStore
let 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)