react+reflux入門教程
為了簡化react的flux帶來的冗余操作,社區的同仁們給我們帶來了很多優秀的輪子,諸如redux,reflux等。今天我們就通過逐行講解代碼實例的方法,感受一番reflux的設計之美。
例子
這個例子是非常簡單的todo例子,學習語言從helloworld開始,學習框架從todo開始,這是我們碼農界的文化傳統!
組件
components/todo.js
import React from 'react'
import Reflux from 'reflux'
import ReactMixin from 'react-mixin'
import store from '../stores/store'
import actions from '../actions/actions'
export default class Todo extends React.Component{
//組件渲染完成后,通過action獲取所有的數組,刷新綁定到this.state上
componentDidMount() {
actions.getAll();
}
add(){
var item =this.refs.item.value;
this.refs.item.value='';
actions.add(item);
}
remove(i){
actions.remove(i);
}
render() {
//items用于乘放li的集合
let items;
if(this.state.list){
items=this.state.list.map( (item,i)=> {
//設置key是因為react的diff算法,是通過key來計算最小變化的
return <li key={i}>
{item.name}
<button onClick={this.remove.bind(this,i)}>remove</button>
</li>
})
}
return (
<div>
<input type="text" ref="item"/>
<button onClick={this.add.bind(this)}>add</button>
<ul>
{items}
</ul>
</div>
)
}
}
// ES6 mixin寫法,通過mixin將store的與組件連接,功能是監聽store帶來的state變化并刷新到this.state
ReactMixin.onClass(Todo, Reflux.connect(store)); 上述代碼,我們干了3件事:
- 渲染了一個組件,這個組件包括一個input,一個add按鈕,一個列表,列表每項包含名稱和remove按鈕
- 給這個組件添加了幾個方法,其中 componentDidMount ()在組件渲染完成后觸發, componentDidMount() 、add()和remove()方法分別調用actions的方法去更新狀態
- 最后一行代碼,使用es6的mixin寫法,使得組件監聽store帶來的state變化,并刷新界面。
看到這里,很多沒有接觸過reflux的同學可能已經暈了,我來圖解下reflux的功能流程吧!
組件就是用戶界面,actions就是組件的動作,store用于執行actions的命令,并返回一個state對象給組件。組件通過state來更新界面。
這里我想說說react和angular的某個相同之處,就是將數據和界面綁定起來,通過操作數據來更新界面(不用苦逼的操作dom了)。我們把數據和界面的規則建好后,更新數據,界面自動就變化了。在這里,數據指的是this.state,界面指的是組件。
那么為何要用actions和store這么多層去更新state呢?為了以后項目業務邏輯變復雜后便于管理。為什么便于管理,因為actions有很多鉤子,鉤子就是“觸發之前,觸發之后的回調什么的”,這些鉤子我們以后會用得上。
actions和store兩個好基友開始更新狀態
actions/actions.js
import Reflux from 'reflux' export default Reflux.createActions(['getAll','add','remove']);
stores/store.js
import Reflux from 'reflux'
import actions from '../actions/actions'
//給數組添加remove方法,用于去除指定下標的元素
Array.prototype.remove=function(dx)
{
if(isNaN(dx)||dx>this.length){return false;}
for(var i=0,n=0;i<this.length;i++)
{
if(this[i]!=this[dx])
{
this[n++]=this[i]
}
}
this.length-=1
};
export default Reflux.createStore({
items:[],
//監聽所有的actions
listenables: [actions],
//on開頭的都是action觸發后的回調函數
onGetAll () {
//更新狀態(就是個對象)
this.trigger({list:this.items});
},
onAdd(item){
this.items.push({name:item});
this.trigger({list:this.items});
},
onRemove(i){
this.items.remove(i);
this.trigger({list:this.items});
}
}); 上述代碼,我們干了3件事:
- 給數組對象的原型添加一個remove的方法,用于刪除指定下標的元素
- 創建一個store,監聽actions的方法
- 在store里,on開頭的都是actions對應的回調函數,this.trigger(),負責更新state(這里指的是{list: this .items}這個對象 )
渲染組件
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Todo from './components/todo';
ReactDOM.render(
<Todo>
</Todo>,
document.querySelector('#app')
); 最后,用webpack編譯
webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: {
app:path.join(__dirname, 'src'),
vendors: ['react','reflux','react-mixin']
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
loaders: [
{
test:/\.js?$/,
exclude:/node_modules/,
loader:'babel',
query:{
presets:['react','es2015']
}
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js')
]
}; 總結
相比較redux而言,
- reflux沒有reducer的概念,取而代之,和action做基友的是store
- reflux沒有把狀態的一部分值綁定在組件的props上,而是將狀態綁定在組件的state上,我們來看react dev tool的截圖
- reflux可以直接調用action的方法,而redux必須將方法綁定在組件的props上,或者使用props的dispatch方法來執行actions的方法
- ……
有此看來,reflux好理解的多,但是redux的單一state是實際項目中是非常好用的,所以,redux在github上的星星比reflux多得多!兩個都是社區同仁智慧的結晶,都是優秀的值得學習的輪子!
源代碼:
https://github.com/lewis617/myReact/tree/master/todo
運行方法:
npm install
npm run build
手動打開index.html