Redux 一个还好的redux 实践吧
剛開(kāi)始用redux 感覺(jué)它有點(diǎn)笨笨的;
因?yàn)橹貜?fù)代碼非常多啊;
以官方例子說(shuō)吧:(并不是說(shuō)官網(wǎng)例子不好,對(duì)剛起步用它的人來(lái)說(shuō),封裝太多反而難以理解)
1.對(duì)于store中的一個(gè)值的改變需要寫(xiě)兩個(gè)方法也是有點(diǎn)啰嗦;
2.算上action中的type 和 和reducer中的switch,加起來(lái)每寫(xiě)一個(gè)action都要寫(xiě)3,4次相同或者類(lèi)似的名字也是很煩的;
3.每次更新?tīng)顟B(tài)都要 dispatch(action(xxx))或者手動(dòng)封裝...
然后自己動(dòng)手?jǐn)]了一點(diǎn)小方法,改善了一下
這個(gè)實(shí)踐最后在組件中的使用如下:
假設(shè)有一個(gè)store模塊結(jié)構(gòu)如下:
{ songSheet: {name: "推薦歌單", list: [], active: false, isFetching: false,...}, ...placeConf:{personal: {name: "私人FM", show: false,...},...} }復(fù)制代碼然后再reducer的分支處理函數(shù)中如下設(shè)置:
setPlaceConfPersonalVis(state, action){return copy(state,{placeConf:{personal:{show: state.data}} })}復(fù)制代碼然后mapDispatchToProps方法中這么寫(xiě) :
const mapDispatchToProps = dispatch => {const $actions = makeActions(dispatch);$action.setPlaceConfPersonalVis(true); return {...actions ,// ... 其他方法} }復(fù)制代碼是的,簡(jiǎn)化后使用就是這么簡(jiǎn)單。
然后如下是各文件代碼:
reducers/index.js // 合并 各reducer模塊
import { combineReducers } from 'redux'; import cmusichome from './cmusichome'; export default combineReducers({cmusichome,// 這里可以放其他模塊的 reducer });復(fù)制代碼reducers/cmusichome.js // 被 reducers/index.js引用 // 核心之一, 將reducer的分支方法拆分出去;
// 這個(gè)是分支處理函數(shù) import cmusichomeFn from "./cmusichomeFn.js"; // 這里是reducer // 生成并更新store 的入口函數(shù) const cmusichome = (state, action) => {// 初始化時(shí), 沒(méi)有state 所以可以在這里設(shè)置 初始值state || (state= {songSheet: {name: "推薦歌單", list: [], active: false, isFetching: false,},songList: {name: "最新音樂(lè)", list: [], active: false, isFetching: false,},djprogramList: {name: "主播電臺(tái)", list: [], active: false, isFetching: false,},playList:{name: "歌曲列表", list: [], show: false, isFetching: false,},recmendList:{show: false, list:[]},placeConf:{personal: {name: "私人FM", show: false},recmend: {name: "每日推薦", show: false},songList: {name: "歌單", show: false},rankingList: {name: "排行榜", show: false},}});const curFn = cmusichomeFn[action.type];// 根據(jù)action 查找分支函數(shù)return curFn && curFn(state, action) || state;// 沒(méi)找到處理函數(shù) 則返回上一次的 state }; export default cmusichome;復(fù)制代碼reducers/cmusichomeFn.js,// 節(jié)選,可以自己添加一些處理分支 被cmusichome.js引用
import tools from "../components/tools.js"; const {copy} = tools; export default {// 歌單updateSongSheet(state, action) {return copy(state, {songSheet: {list: action.data,}});},toggleSongSheetState(state, action){return copy(state, {songSheet: {active: !state.songSheet.active,}});},fetchSongSheet(state,action){return copy(state, {songSheet: {isFetching: action.data,}});}, };復(fù)制代碼actions/index.js // 被views/Discover.js容器組件引用 // 核心之一,根據(jù)reducerFn的鍵名,創(chuàng)建同名action方法;
// 所有在 reducer 中使用的分支函數(shù); import cmusichomeFns from "../reducers/cmusichomeFn"; // ...這里可以繼續(xù)引入其他模塊的分值函數(shù)// 根據(jù)reducer 分支函數(shù)名, 創(chuàng)建對(duì)應(yīng)的 action 函數(shù) // 這些action函數(shù)會(huì)接受一個(gè)值, 然后生成 返回{type: action名, data: 參數(shù)值}的方法; function makeReducerFnsIntoActions(reducerFns){const actions = {};Object.keys(reducerFns).forEach(item => actions[item] = data => ({type: item, data}));return actions; }; // 組合所有actions 作為 makeActions 內(nèi)部需要轉(zhuǎn)化的actions const actions = {...makeReducerFnsIntoActions(cmusichomeFns),// ...這里可以繼續(xù)添加 分支函數(shù) }; // 導(dǎo)出將 dispatch(action(val)) 轉(zhuǎn)化為 xxx.action(val) 模式的函數(shù); // 可以在外界用 ...xxx 解構(gòu)成 action(val); 接受 dispatch 作為參數(shù); // 然后在 mapDispatchToProps 方法中 return { ...makeActions(dispatch), ... } // 就可以在 子組件中使用xxx.action(val) 真是極方便的; export default function makeActions(dispatch){function _(str,val){dispatch(actions[str](val));};const actionFn = {};Object.keys(actions).forEach(item=> actionFn[item] = val => _(item,val));return actionFn; }復(fù)制代碼App.js // 含react-router / react-redux
import React from 'react'; import logo from '../images/logo.svg'; import './App.css'; import {HashRouter,Route} from 'react-router-dom'; import Discover from './Discover.js'; const App = () => (<HashRouter basename="/"><div className="App"><img src={logo} className="App-logo" alt="logo" /><audio src="" id="audio"></audio><Route path="/discover" component={Discover}/></div></HashRouter> ); export default App;復(fù)制代碼views/Discover.js // 容器組件 // 被App.js 引用
import makeActions from '../actions'; import $http from "./../http/http.js"; import React, from 'react'; import { connect } from 'react-redux'; import Home from "./Home/Home.js"; const mapStateToProps = state => ({...state.cmusichome}); const mapDispatchToProps = dispatch => {const $actions = makeActions(dispatch);$http.personalized()(res => {$actions.updateSongSheet(res.result.map(item => ({name: item.name, img: item.picUrl, id: item.id,})))});return{...$actions,// 貌似到子組件 const {$action} = props;會(huì)好一些getPlayList: function (id) {$actions.fetchPlayList(true);$http.playlistDetail({id})(res=>{$actions.updatePlayList(res.playlist.tracks);$actions.togglePlayList(true);$actions.fetchPlayList(true);});},playASong(id){$http.songUrl({id})(res=>{const audio = document.querySelector("#audio");audio.src = res.data[0].url;audio.play();})},}}; export default connect(mapStateToProps, mapDispatchToProps)(Home);復(fù)制代碼copy.js // 被 reducers/cmusichomeFn.js 引用 // 核心之一 // 深拷貝數(shù)組外的屬性 // 對(duì)于數(shù)組的操作是: 通過(guò)數(shù)組map返回新數(shù)組替換之前的數(shù)組,并不會(huì)直接引用傳入的數(shù)組或者原store中的值(為什么這么做我也不知道);
import type from "./type.js"; function _copy() {if(arguments.length) {const list = Array.prototype.map.call(arguments, item => item);const curObj = list.shift();Object.keys(curObj).forEach(item=>{const val = curObj[item];if(val !== undefined)this[item] = (type.isObject(val) && copy(this[item]||{},val)) ||(type.isArray(val) && val.map(item => item)) ||val;});return _copy.apply(this, list);} else return this; } function copy(){return _copy.apply({},arguments);} export default copy;復(fù)制代碼type.js // 被 copy.js 引用
const getType = item => (Object.prototype.toString.call(item).slice(8, -1));getType.isNumber = item => getType(item) === 'Number'; getType.isString = item => getType(item) === 'String'; getType.isArray = item => getType(item) === 'Array'; getType.isObject = item => getType(item) === 'Object'; getType.isBoolean = item => getType(item) === 'Boolean'; getType.isNull = item => getType(item) === 'Null'; getType.isUndefined = item => getType(item) === 'Undefined'; getType.isFunction = item => getType(item) === 'Function'; getType.isDate = item => getType(item) === 'Date'; export default getType;復(fù)制代碼demo 請(qǐng)移架?https://github.com/DeyaoCai/cmusic?
轉(zhuǎn)載于:https://juejin.im/post/5be3124951882516d1553181
總結(jié)
以上是生活随笔為你收集整理的Redux 一个还好的redux 实践吧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python opencv SIFT,获
- 下一篇: 常用的时间字符串转换