摘要:背景項(xiàng)目用的是全家桶,之前有同事用改進(jìn)了一波,一直都沒去研究。這次的打算寫一個(gè)輸入框,輸入拼音會(huì)返回對(duì)應(yīng)的城市列表。
背景
項(xiàng)目用的是react全家桶, 之前有同事用redux-saga 改進(jìn)了一波, 一直都沒去研究。 前幾天趁有空,也去學(xué)習(xí)了下, 寫了個(gè)簡(jiǎn)單的demo練練手, 在這里簡(jiǎn)單分享一下。
這次的demo打算寫一個(gè)輸入框,輸入拼音會(huì)返回對(duì)應(yīng)的城市列表。并盡可能多的使用redux-saga的特性
起步首先是使用 create-react-app 創(chuàng)建新的項(xiàng)目,并npm install react-redux redux redux-saga --save
上網(wǎng)隨便搜索了一段城市信息的json,保存為city.js
const cities = [{label:"北京Beijing010",name:"北京",pinyin:"Beijing",zip:"010"}, {label:"重慶Chongqing023",name:"重慶",pinyin:"Chongqing",zip:"023"}, {label:"上海Shanghai021",name:"上海",pinyin:"Shanghai",zip:"021"},...] export default cites;
接著是構(gòu)思state,state有兩個(gè)值,一個(gè)是value代表輸入的值,另一個(gè)是數(shù)組list,代表篩選的結(jié)果
reducers.js // 設(shè)置兩個(gè)action,一個(gè)是設(shè)置value,一個(gè)是設(shè)置list const reducer = (state, action) => { switch (action.type) { case "INPUT": return {...state, value: action.payload} case "SET_LIST": return {...state, list: action.payload} } return {...state} } export default reducer
APP.js
App為純函數(shù)組件,react-redux的connect方法中傳入兩個(gè)參數(shù),mapStateToProps將state傳入App的props,mapActionToProps講handleChange傳入App,當(dāng)調(diào)用handleChange時(shí),會(huì)調(diào)用INPUT這個(gè)action
import React, { Component } from "react"; import "./App.css"; import { connect } from "react-redux" const App = props => () const mapStateToProps = state => ({ value: state.value, list: state.list }) const mapActionToProps = dispatch => ({ handleChange: v => dispatch({ type: "INPUT", payload: v.target.value }) }) // export default App export default connect(mapStateToProps, mapActionToProps)(App);{props.list.map(i =>
- {i.name}
)}
接著是我們的主角saga.js
takeEvery可以監(jiān)聽對(duì)應(yīng)的action,如果為*號(hào)則監(jiān)聽所有的action,如果action.type匹配,調(diào)用對(duì)應(yīng)的回調(diào)函數(shù)。
put可以主動(dòng)去觸發(fā)action,在這里觸發(fā)了獲取的城市結(jié)果
import {takeEvery, put, take} from "redux-saga/effects" import cities from "./city" function* input() { yield takeEvery("INPUT", function* (v) { let filterCities = yield getData(v.payload) yield put({type: "SET_LIST", payload: filterCities.slice(0, 10)}) }); } function getData (v) { return new Promise(function (res, rej) { setTimeout(() => res(cities.filter(i => i.pinyin.toUpperCase().includes(v.toUpperCase()))), 1000) }) } export default input input函數(shù)也可以使用take來替代takeEvery function* input() { while (true) { let v = yield take("INPUT") let filterCities = yield getData(v) yield put({type: "SET_LIST", payload: filterCities.slice(0, 10)}) } }
接下來是最復(fù)雜的index.js部分
import React from "react"; import { render } from "react-dom"; import "./index.css"; import App from "./App"; import registerServiceWorker from "./registerServiceWorker"; import { Provider } from "react-redux" import createSagaMiddleware from "redux-saga" import { createStore, applyMiddleware } from "redux" import reducers from "./reducers" import saga from "./sagas" const sagaMiddleware = createSagaMiddleware() const store = createStore(reducers, {value: "", list: []}, applyMiddleware(sagaMiddleware)) sagaMiddleware.run(saga) render(, document.getElementById("root")); registerServiceWorker();
到這里,城市拼音輸入框就初步完成了
進(jìn)階取消
先加入如果輸入數(shù)字的話,立刻停止查詢并console報(bào)錯(cuò)的功能
修改saga.js
首先,導(dǎo)入fork和cancel兩個(gè)函數(shù),redux-saga的cancel只能取消fork的任務(wù)
import {takeEvery, put, take, cancel, fork} from "redux-saga/effects" // 新加一個(gè)check函數(shù),跟之前的input有點(diǎn)類型,如果監(jiān)測(cè)到有數(shù)字,會(huì)調(diào)用CANCEL function* check () { yield takeEvery("INPUT", function* (v) { if (/d+/.test(v.payload)) { console.log("x ") yield put({type: "CANCEL"}) } }) }
加入函數(shù)main, 首先添加使用fork操作,將input任務(wù)保存為i,在碰到cancel的時(shí)候,取消該任務(wù),并重新開始新的任務(wù)
function* main () { yield fork(check) let i = yield fork(input) while (true) { yield take("CANCEL") console.log("cancel") yield cancel(i) i = yield fork(input) } }
最后導(dǎo)出main
export default main
channel
令函數(shù)是依次查詢,只有之前的查詢完成后,才繼續(xù)查詢后面的
引用actionChannel 的effect,修改函數(shù)input:
function* input () { const inputChan = yield actionChannel("INPUT") while (true) { const v = yield take(inputChan) const filterCities = yield call(getData, v) console.log("done") yield put({type: "SET_LIST", payload: filterCities.slice(0, 10)}) } }
END
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/95896.html
摘要:通過創(chuàng)建將所有的異步操作邏輯收集在一個(gè)地方集中處理,可以用來代替中間件。 redux-saga框架使用詳解及Demo教程 前面我們講解過redux框架和dva框架的基本使用,因?yàn)閐va框架中effects模塊設(shè)計(jì)到了redux-saga中的知識(shí)點(diǎn),可能有的同學(xué)們會(huì)用dva框架,但是對(duì)redux-saga又不是很熟悉,今天我們就來簡(jiǎn)單的講解下saga框架的主要API和如何配合redux框...
摘要:下面會(huì)從淺到深,淡淡在閱讀源碼過程中自己的理解。分拆子頁面后,每一個(gè)子頁面對(duì)應(yīng)一個(gè)文件。總結(jié)上面就是最早版本的源碼,很簡(jiǎn)潔的使用了等其目的也很簡(jiǎn)單簡(jiǎn)化相關(guān)生態(tài)的繁瑣邏輯參考源碼地址 ??dva的思想還是很不錯(cuò)的,大大提升了開發(fā)效率,dva集成了Redux以及Redux的中間件Redux-saga,以及React-router等等。得益于Redux的狀態(tài)管理,以及Redux-saga中...
摘要:下面會(huì)從淺到深,淡淡在閱讀源碼過程中自己的理解。分拆子頁面后,每一個(gè)子頁面對(duì)應(yīng)一個(gè)文件。總結(jié)上面就是最早版本的源碼,很簡(jiǎn)潔的使用了等其目的也很簡(jiǎn)單簡(jiǎn)化相關(guān)生態(tài)的繁瑣邏輯參考源碼地址 ??dva的思想還是很不錯(cuò)的,大大提升了開發(fā)效率,dva集成了Redux以及Redux的中間件Redux-saga,以及React-router等等。得益于Redux的狀態(tài)管理,以及Redux-saga中...
摘要:下面會(huì)從淺到深,淡淡在閱讀源碼過程中自己的理解。分拆子頁面后,每一個(gè)子頁面對(duì)應(yīng)一個(gè)文件。總結(jié)上面就是最早版本的源碼,很簡(jiǎn)潔的使用了等其目的也很簡(jiǎn)單簡(jiǎn)化相關(guān)生態(tài)的繁瑣邏輯參考源碼地址 ??dva的思想還是很不錯(cuò)的,大大提升了開發(fā)效率,dva集成了Redux以及Redux的中間件Redux-saga,以及React-router等等。得益于Redux的狀態(tài)管理,以及Redux-saga中...
閱讀 2322·2021-11-08 13:13
閱讀 1253·2021-10-09 09:41
閱讀 1696·2021-09-02 15:40
閱讀 3194·2021-08-17 10:13
閱讀 2553·2019-08-29 16:33
閱讀 3129·2019-08-29 13:17
閱讀 3141·2019-08-29 11:00
閱讀 3303·2019-08-26 13:40