摘要:介紹首先是一個(gè)基于和的數(shù)據(jù)流方案,然后為了簡(jiǎn)化開發(fā)體驗(yàn),還額外內(nèi)置了和,所以也可以理解為一個(gè)輕量級(jí)的應(yīng)用框架。
介紹(dva.js)
dva 首先是一個(gè)基于 redux 和 redux-saga 的數(shù)據(jù)流方案,然后為了簡(jiǎn)化開發(fā)體驗(yàn),dva 還額外內(nèi)置了 react-router 和 fetch,所以也可以理解為一個(gè)輕量級(jí)的應(yīng)用框架。
特性易學(xué)易用,僅有 6 個(gè) api,對(duì) redux 用戶尤其友好,配合 umi 使用后更是降低為 0 API
elm 概念,通過 reducers, effects 和 subscriptions 組織 model
插件機(jī)制,比如 dva-loading 可以自動(dòng)處理 loading 狀態(tài),不用一遍遍地寫 showLoading 和 hideLoading
支持 HMR,基于 babel-plugin-dva-hmr 實(shí)現(xiàn) components、routes 和 models 的 HMR
前言我的個(gè)人理解:dva的核心其實(shí)是 saga的封裝,將action,reducer等等全部引入到model中。
過多的廢話也就不再闡述了,欲知詳情,請(qǐng)看官網(wǎng),本文的目的就是快速開始,讓一個(gè)擁有react+redux基礎(chǔ)的人可以快速使用dva.js
"深入"配置環(huán)境安裝依賴之類的就不多說了,請(qǐng)看官方文檔
dva new dva-quickstart
我們得到初始項(xiàng)目,目錄結(jié)構(gòu)如下:
接下里將會(huì)逐個(gè)目錄解釋,請(qǐng)注意看注釋
import dva from "dva"; //引入依賴 import "./index.css"; // 1. Initialize const app = dva(); //初始化 dva應(yīng)用 // 2. Plugins // app.use({}); //使用中間件 // 3. Model // app.model(require("./models/example").default); // 加載model層 (后面詳細(xì)解釋model) // 4. Router app.router(require("./router").default); // 引入router // 5. Start app.start("#root"); // 掛載dva應(yīng)用
基本上就是這樣,多余的沒什么好說的
路由匹配 router.jsimport React from "react"; import { Router, Route, Switch } from "dva/router"; // 引入 router,用的就是 react-router import IndexPage from "./routes/IndexPage"; // 引入路由綁定的高階組件 // 按照從上到下的順序開始匹配url規(guī)則,匹配到了就是展示對(duì)應(yīng)的組件view function RouterConfig({ history }) { return (路由頁面 routes/IndexPage.js); } export default RouterConfig;
在routes目錄下,是路由頁面,由多個(gè)高階組件渲染而成,當(dāng)然,剛初始化的項(xiàng)目自然沒有寫高階組件,在后面的實(shí)戰(zhàn)操作中,我們將以 路由頁面 => 高階組件 => 基礎(chǔ)組件 路由綁定model層,高階組件綁定路由的action事件,基礎(chǔ)組件綁定原生事件,在路由中觸發(fā)action更新數(shù)據(jù)流 的邏輯 完成一個(gè)簡(jiǎn)單標(biāo)準(zhǔn)的dva過程
import React from "react"; import { connect } from "dva"; import styles from "./IndexPage.css"; // 在這個(gè)方法中,我們返回一個(gè)dom結(jié)構(gòu) // 并且 在圓括號(hào)中 可以接受一個(gè)大對(duì)象(包含很多東西),也可以解構(gòu) 只取其中的state和dispatch,具體可以在后面看 function IndexPage() { return (); } IndexPage.propTypes = { }; // 這里 connect方法就是redux的connect,后面的IndexPage表示綁定的高階組件 // 在connect的第一個(gè)括號(hào)中,是可以拿到所有的model對(duì)象,這樣就可以把對(duì)應(yīng)的model對(duì)象綁定到我們的高階組件上 export default connect()(IndexPage);Yay! Welcome to dva!
- To get started, edit
src/index.js
and save to reload.- Getting Started
看了上面的注釋很蒙也沒關(guān)系,因?yàn)榧埳险劚踔粒冶紱]有出來,你只需要知道,connect的作用及過程就好了
數(shù)據(jù)模型 model/emample.jsexport default { namespace: "example", // 命名空間 作為 connect方法 中獲取model對(duì)象state的 id state: {}, // 初始化state subscriptions: { // 訂閱 setup({ dispatch, history }) { // eslint-disable-line }, }, effects: { // 異步action的handler *fetch({ payload }, { call, put }) { // eslint-disable-line yield put({ type: "save" }); }, }, reducers: { //react-redux的reducers 用來接收action并且處理數(shù)據(jù)更新 save(state, action) { return { ...state, ...action.payload }; }, }, };
當(dāng)我們?cè)诟唠A組件中通過connect綁定了高階組件和model,并且在index.js中引入這個(gè)model,就可以使用標(biāo)準(zhǔn)流程:
在subscriptions方法中訂閱路由變化,當(dāng)路由與高階組件相對(duì)應(yīng),調(diào)用effects請(qǐng)求數(shù)據(jù),拿到數(shù)據(jù)reducer更新數(shù)據(jù)
代碼就不貼了,大家應(yīng)該都知道這里面做什么
公共服務(wù) services/example.js這里封裝了一些公共使用的方法
"淺出"項(xiàng)目地址:https://github.com/zhaowanhua...
接下來,我們將quick-start項(xiàng)目改造成一個(gè)按照dva標(biāo)準(zhǔn)流程的小項(xiàng)目(如上圖),幫助大家理解和使用
首先我們把上面那些文件夾下面的文件全部刪干凈
import dva from "dva"; import "./index.css"; import createHistory from "history/createBrowserHistory"; // 這個(gè)方法里面 可以配置router的 路由模式,比如hash或者H5 histroy, // 具體區(qū)別可以參考我的文章 vue-router,單頁應(yīng)用原理一致的 const app = dva({ history: createHistory() }); // 2. Plugins // app.use({}); // 3. Model app.model(require("./models/List").default); // 引入model // 4. Router app.router(require("./router").default); // 5. Start app.start("#root");創(chuàng)建基礎(chǔ)組件 components/Item.js
import React from "react"; const Item = ({ num, id, OnDelete }) => { return (
export default { namespace: "list", // 這個(gè)namespace 是model的唯一識(shí)別id,在connect中需要使用這個(gè)綁定 state: {}, subscriptions: { setup({ dispatch, history }) { // eslint-disable-line return history.listen(({ pathname }) => { if (pathname === "/") { dispatch({ type: "fetch", payload: {} }); } }); }, }, effects: { * fetch({ payload }, { call, put }) { // eslint-disable-line // 這里假裝 獲取到了服務(wù)器的數(shù)據(jù) const fetchData = [0, 1, 2, 3] yield put({ type: "save", list: fetchData }); }, }, reducers: { // 保存 save(state, action) { return {...state, list: action.list }; }, // 新增 add(state, action) { const [..._arr] = {...state }.list; _arr.push(_arr.length) return { ...state, list: _arr } }, // 刪除 del(state, action) { return { ...state, list: state.list.filter((item, index) => { return index !== action.id }) } }, }, };
寫好model 是要在index.js中引入的,不然沒有效果
創(chuàng)建高階組件 components/List.jsimport React from "react"; import Item from "./Item" // 通過prop 把路由頁面的action觸發(fā)方法綁定過來,傳遞給子組件(OnDelete),也可以在當(dāng)前組件觸發(fā),如OnAdd function List({ OnAdd, OnDelete, list }) { const List = list.map((num, index) =>創(chuàng)建路由頁面 routes/IndexPage.js- ); return (
{List}); } List.propTypes = {}; export default List;
import React from "react"; import { connect } from "dva"; import List from "../components/List" //我們?cè)诼酚身撁胬锩驿秩靖唠A組件,寫好action,通過prop傳遞給基礎(chǔ)組件 // 這里引入的list 對(duì)應(yīng) model中的namespace function IndexPage({ dispatch, list }) { function handleAdd() { dispatch({ type: "list/add" }); } function handleDelete(id) { dispatch({ type: "list/del", id: id, }); } return (總結(jié)); } IndexPage.propTypes = {}; // 通過connect方法綁定路由頁面和model,你可以把connect方法的第一個(gè)參數(shù)(方法里的) 打印出來看看都有什么東西,不要讓解構(gòu)擾亂了你的眼睛,connect((obj)=>{console.log(obj)})() export default connect(({ list }) => { return list; // 這里是state中的list,通過connect,在每次數(shù)據(jù)更新的時(shí)候,流向我們的view,更新視圖,你可以在這里"打樁",看看具體的數(shù)據(jù)流動(dòng) })(IndexPage);
以上是我最近學(xué)習(xí)的想法和思考后得到的內(nèi)容,希望對(duì)大家有所幫助,寫的比較隨意,在內(nèi)容中如果有問題或者想法不對(duì),請(qǐng)予指正,也可以提出新的問題,我們共同探究.
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/96684.html
摘要:多端統(tǒng)一開發(fā)框架優(yōu)秀學(xué)習(xí)資源匯總官方資源項(xiàng)目倉庫官方文檔項(xiàng)目倉庫官方文檔微信小程序官方文檔百度智能小程序官方文檔支付寶小程序官方文檔字節(jié)跳動(dòng)小程序官方文檔文章教程不敢閱讀包源碼帶你揭秘背后的哲學(xué)從到構(gòu)建適配不同端微信小程序等的應(yīng)用小程序最 Awesome Taro 多端統(tǒng)一開發(fā)框架 Taro 優(yōu)秀學(xué)習(xí)資源匯總 showImg(https://segmentfault.com/img/r...
摘要:哈哈,我理解,架構(gòu)就是骨架,如下圖所示譯年月個(gè)有趣的和庫前端掘金我們創(chuàng)辦的使命是讓你及時(shí)的了解開發(fā)中最新最酷的趨勢(shì)。 翻譯 | 上手 Webpack ? 這篇就夠了! - 掘金譯者:小 boy (滬江前端開發(fā)工程師) 本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明作者及出處。 原文地址:https://www.smashingmagazine.... JavaSrip... 讀 Zepto 源碼之代碼結(jié)構(gòu) - ...
摘要:在符號(hào)位中,表示正,表示負(fù)。我們知道對(duì)于整型來說,內(nèi)存中存放的是該數(shù)的補(bǔ)碼。在計(jì)算機(jī)系統(tǒng)中,數(shù)值一律用補(bǔ)碼來表示和存儲(chǔ)。表示有效數(shù)字,。規(guī)定對(duì)于位的浮點(diǎn)數(shù),最高的位是 ...
摘要:進(jìn)入當(dāng)前程序的學(xué)習(xí)系統(tǒng)的所有樣本稱作輸入,并組成輸入空間。結(jié)束語注意這篇文章僅僅是我接下來的機(jī)器學(xué)習(xí)系列的第一篇,后續(xù)還會(huì)有更多的內(nèi)容。 往期回顧:統(tǒng)計(jì)學(xué)習(xí)方法第...
閱讀 3712·2021-10-12 10:11
閱讀 1980·2019-08-30 15:53
閱讀 1589·2019-08-30 13:15
閱讀 2302·2019-08-30 11:25
閱讀 1797·2019-08-29 11:24
閱讀 1648·2019-08-26 13:53
閱讀 3522·2019-08-26 13:22
閱讀 1747·2019-08-26 10:24