<pre> 當有以下須要能夠考慮使用redux: 當組件的狀態,須要共享 某個狀態須要在任何地方均可以拿到 一個組件須要改變全局狀態 一個組件須要改變另外一個組件的狀態 vue中是 store(state,mutation,action) |----------------------- | | action --->mutation | |-- ↑------- ↑ | dispatch | | | | | | | | | ↓ | component<-----|-----state | |-------------- | state能夠由組件直接獲取獲得 組件diapatch action 或commit mutation 來實現數據state的修改 react沒有vuex那麼清晰,在store裏定義state(狀態),action等 主要定義reducer和action react中reduce至關於mutation,store不須要定義聲明,有reducer自動完成 組件經過store.getState()得到狀態 組件怎麼改狀態?經過容器dispatch去改-->也就是store.dispatch(Action) 這個Action至關於從新觸發掉了reducer 從新產生State,State一變化就觸發組件變化。流向和vuex是同樣的 component--->Action--->reducer--->state--->component 可是不把store,reducer,action所有叫store 這每個東西都是普通的 </pre>
02vue
<script type="text/babel"> //count數據 用redux存 //VUEX的使用:1)建立容器 定義state,action,mutation 2)容器掛載到Vue實例上 3)組件獲取狀態或修改狀態 //Redux: //reducer:用於產生state的函數 定義reducer才能知道count是什麼數據 // reducer根據對應的action產生state //action 是個普通對象,用於記錄用戶的行爲 裏面屬性其實能夠隨便定,但規範上通常是給{type:''} // store 根據reducer函數建立 //六步驟 //1.定義Reducer:是個函數 怎麼定義隨意 名字隨便取,可是裏面參數的含義是固定的 //第一個參數,上一次的狀態 state是由reducer建立的,因此一次都沒調用的時候可能沒有定義,能夠給個初始化 //第二個參數是用戶提交的action對象 //返回值爲新狀態 function myCount(state=0,action){ //這個state其實就表明count //reducer就是根據action產生state //傳遞給個人action究竟是個什麼行爲,全部要根據action.type判斷 //reducer最終返回的是一個新狀態 switch(action.type){ case 'ADD': return state+1 case 'SUB': return state-1 //必定要定義默認狀況 default:return state //返回舊狀態 } } //2.reduce作好後建立容器 // 建立store:用Redux.createStore 這個方法接受一個參數,就收Reducer做參數 根據這個Reducer就能產生容器(store) const store=Redux.createStore(myCount) //3.有時候可寫可不寫,簡單的話能夠不寫 建立Action函數,Action Creator 是個函數,做用是建立action(一個對象) return一個對象 //能夠由參數也能夠沒有 function setCount(type){ //返回Action return{ type } } //4 建立組件 獲取狀態 修改狀態 class App extends React.Component{ add=()=>{ //讓狀態+1 reducer已將幫你作了 只要去執行一遍就行 //只要去調用reducer 這時候用store.dispatch store是全局變量 //dispatch參數爲action //addCount就是幫咱們生成action對象的 因此這裏得dispatch的參數就位action函數 不然簡單的話能夠不用這個addCount函數 直接store.dispatch({type:"ADD"}) store.dispatch(setCount('ADD')) //一dispatch 立刻就會去調用reducer函數(也就是myCount),action傳給myCount的第二個參數 這時候state就變了 state+1了 //但這時候是不會更新視圖的 } sub=()=>{ //讓狀態-1 store.dispatch(setCount('SUB')) } render(){ return( <div> {/*獲取狀態 store.getState() 拿到了state(就是count數字)*/} <p>{store.getState()}</p> <button onClick={this.add}>+</button> <button onClick={this.sub}>-</button> </div> ) } } //5.渲染組件 ReactDOM.render(<App/>,document.getElementById('root')) //6.監聽狀態變化,從新渲染頁面 store.subscribe會自動監聽state的更新 store.subscribe(function(){ ReactDOM.render(<App/>,document.getElementById('root')) }) </script>
03react
<div id='root'></div> <script src="./react.js"></script> <script src="./react-dom.js"></script> <script src="./react-router-dom.js"></script> <script src="./redux.js"></script> <script src="./babel.min.js"></script> <script type="text/babel"> //需求:共享數據count,行爲有:加某個值,減某個值 //1.定義Reducer:Reducer是函數,用於根據就狀態和Action產生新狀態 //myCount這個函數由你去定義但不是否是由你直接去調用 而是由你去dispatch的時候由內部的Redux經過store自動的去調用 //因此裏面的形參不能換順序,調用者根據規則去調用的,因此要按規則去定義,第一個就要定義state,第二個是action //redux的action個vuex不一樣 vuex的action是方法(函數), redux的是對象 且有不成文的規則,要有一個type屬性 不叫type也能夠 不過都用type {type} //state=0這個初始值能夠在建立recuder的時候在形參裏設置,也能夠在第二步建立容器的時候指定 function myCount(state=0,action){ debugger switch (action.type) { //action:{type:表示行爲名稱,payload:行爲所攜帶的數據(推薦用payload)} case 'ADD': return state+action.payload case 'SUB': return default: return state-action.payload } } //2.建立容器 第一個參數就是recuder,第二個參數就是狀態初始值(可選,但這裏不寫那麼reducer(myCount)就要寫,不然會顯示NAN) const store = Redux.createStore(myCount,0) //3.定義建立Action的方法,Action Creator function myActionCreator(type,payload=1) { return { type, payload } } //4.設計組件 class App extends React.Component{ render(){ console.log(store.getState()) debugger return( <div> <p>{store.getState()}</p> <button>+</button> <button>-</button> </div> ) } } function myRender(){ ReactDOM.render(<App/>,document.getElementById('root')) } myRender() //這裏只是講的redux redux自己是不能自動更新組件的(state變化的話) 後面有一個react-redux 這個作的是自動監聽state變化 會直接引發視圖變化 只用redux纔有第五步 //5.監聽狀態改變 store.subscribe(myCount)是有返回值的 執行這個返回值就會解除監聽 var unSubScribe=store.subscribe(myCount) // setTimeout(()=>unSubScribe(),20000)//解除監聽 </script>
04vuex
<style> .del{ text-decoration: line-through } </style> </head> <body> <div id='root'></div> <script src="./react.js"></script> <script src="./react-dom.js"></script> <script src="./react-router-dom.js"></script> <script src="./redux.js"></script> <script src="./babel.min.js"></script> <script type="text/babel"> //1.設置reducer function todoList(state=[],action){ switch (action.type) { case 'ADD_LIST': return [ ...state, action.payload ] case 'DELETE_ITEM': return [ ...state.slice(0,action.index), ...state.slice(action.index+1) ] case 'TOGO_TODO': return [ ...state.slice(0,action.index), Object.assign(state[action.index],{isCompleted:!state[action.index].isCompleted}), ...state.slice(action.index+1) ] case 'CLEAR_LIST': return [] default: return state } } //多個reducer能夠合併 const totalCount=function(state=0,action){ switch(action.type) { case 'CHANGE_TOTAL': //修改總數量 return action.payload case 'ADD_TOTAL': return state+1 case 'SUB_TOTAL': return state-1 default: return state } } //combineReducers的參數,爲一個對象,該對象key是state中的屬性,value是產生對應state的reducer函數 const allReducer=Redux.combineReducers({ todoList, totalCount }) //2.建立容器 const store=Redux.createStore(allReducer) //3.設置action Creator function addlist(payload){ return { type:'ADD_LIST', payload } } function deleteItem(index){ return { type:'DELETE_ITEM', index } } function check(index){ return { type:'TOGO_TODO', index } } //定義totalChange的Action Creator function changeTotalCount(){ return } //4 建立UI class App extends React.Component{ render(){ return(<div> 標籤內容 <TodoList/> <AddItem/> </div>) } } class TodoList extends React.Component{ del=(index)=>{ store.dispatch(deleteItem(index)) } check=(index)=>{ store.dispatch(check(index)) } render(){ return(<ul> {store.getState().todoList.map((val,index)=>{ return(<li> <input type="checkbox" checked={val.isCompleted} onChange={e=>this.check(index)} /> <span className={val.isCompleted?'del':''}>{val.content}</span> <button onClick={e=>this.del(index)}>刪除</button> </li>) }) } </ul>) } } class AddItem extends React.Component{ add=()=>{ this.inputItem.value!==''?store.dispatch(addlist({content:this.inputItem.value,isCompleted:false})):alert('請輸入事件') } render(){ return(<div> <input ref={(el)=>this.inputItem=el}/> <button onClick={this.add}>保存</button> </div>) } } function render(){ ReactDOM.render(<App/>,document.getElementById('root')) } render() store.subscribe(render) </script>
05redux
<div id='root'></div> <script src="./react.js"></script> <script src="./react-dom.js"></script> <script src="./react-router-dom.js"></script> <script src="./redux.js"></script> <script src="./babel.min.js"></script> <script type="text/babel"> class App extends React.Component{ constructor(props){ super(props) } add=()=>{ //讓狀態+1 reducer已將幫你作了 只要去執行一遍就行 //只要去調用reducer 這時候用store.dispatch store是全局變量 //dispatch參數爲action //addCount就是幫咱們生成action對象的 因此這裏得dispatch的參數就位action函數 不然簡單的話能夠不用這個addCount函數 直接store.dispatch({type:"ADD"}) // store.dispatch(setCount('ADD')) //一dispatch 立刻就會去調用reducer函數(也就是myCount),action傳給myCount的第二個參數 這時候state就變了 state+1了 //但這時候是不會更新視圖的 } sub=()=>{ //讓狀態-1 store.dispatch(setCount('SUB')) } render(){ return( <div> </div> ) } } const a1=new App() debugger //5.渲染組件 ReactDOM.render(<App/>,document.getElementById('root')) //6.監聽狀態變化,從新渲染頁面 store.subscribe會自動監聽state的更新 store.subscribe(function(){ ReactDOM.render(<App/>,document.getElementById('root')) }) </script>
06babel
<div id='root'></div> <script src="./react.js"></script> <script src="./react-dom.js"></script> <script src="./react-router-dom.js"></script> <script src="./redux.js"></script> <script src="./babel.min.js"></script> <script type="text/babel"> //1.定義reducer 是個函數 function reducer1(state = 0 ,action){ switch (action.type){ default:return state ;break; } } //2.reducer作好後建立容器 const store = Redux.createStore(reducer1) //3.建立action函數,做用是return一個對象 function action(type){ return type } //創個組件 class App extends React.Component{ render(){ return <div>11</div> } } ReactDOM.render(<App/>,document.getElementById('root')) </script>