摘要:基于的管理框架,提供簡(jiǎn)單快捷的開發(fā)范式。這里的更改會(huì)對(duì)請(qǐng)求參數(shù)生效只針對(duì)名字是的進(jìn)行下面鉤子函數(shù)的執(zhí)行用于在執(zhí)行之后觸發(fā)。
vanex
基于mobx & mobx-react的React store管理框架,提供簡(jiǎn)單快捷的開發(fā)范式。使用模式類似dva,但用起來(lái)比dva更簡(jiǎn)單,開發(fā)效率更高!
github地址: https://github.com/alibaba/vanex
example地址: https://github.com/alibaba/va...
三個(gè)API搞定問題!簡(jiǎn)單易上手,開發(fā)效率高。
如何使用vanex提供了一鍵初始化的start方法,入口文件可以像下面這樣開始:
import React from "react"; import App from "./App"; import { start, } from "vanex"; // model import user from "./models/User"; import todos from "./models/Todos"; start({ component: App, container: "#root", models: { user, todos } });
所以,只需要把你的model(類似于tarot的module)、React Container Component、Middleware(可選)、Relation傳遞進(jìn)來(lái),應(yīng)用就能跑起來(lái)了。
介紹下幾個(gè)概念:
model: 數(shù)據(jù)管理,區(qū)別于tarot,其只有:name命名空間以及data、action兩個(gè)核心部分,action部分可以同時(shí)存放類似于Reducers以及Effects兩個(gè)部分的操作(作為優(yōu)化,后續(xù)這里可以做拆分);
middleware:中間件,用于輔助異步處理。model重定義的一個(gè)action最終被執(zhí)行的流程是這樣的:首先其會(huì)被mobx的action函數(shù)包一層,以避免掉每次更改數(shù)據(jù)都會(huì)觸發(fā)一次UI的重新渲染,然后其會(huì)被各個(gè)中間件依次執(zhí)行,而每個(gè)中間件都有before/after/error三個(gè)操作,可以在不同的操作中對(duì)每一種操作做統(tǒng)一的處理;
relation:用于不同model之間的通信,基于監(jiān)聽訂閱模式。
基于vanex的開發(fā)范式的container Component也是UI Component,UI Component像下面這樣:
import React, {Component, PropTypes} from "react"; // components import UserLogin from "./components/UserLogin"; import UserDetail from "./components/UserDetail"; import Todos from "./components/Todos"; import { inject, observer, } from "vanex"; // 注意先observer,后inject @inject("user") @observer export default class App extends Component { render() { // const user = this.props.user.toJSON(); console.log(this.props.user.toJSON()); const {user} = this.props; console.log("user.isLogin:", user.isLogin); if (user.isLogin !== true) { return; } return ( ); } }
這里的oberser來(lái)自于mobx的observer,inject則來(lái)自于mobx-react。如果想給一個(gè)Component同時(shí)注入多個(gè)model,則可以像下面這樣:
// start import React from "react"; import App from "./App"; import { start, } from "vanex"; // model import user from "./models/User"; import todos from "./models/Todos"; start({ component: App, container: "#root", models: { user, todos } });
import { inject, observer, } from "vanex"; @inject( stores => ({ user: stores.user, todos: stores.todos, }) ) @oberser class MyComponent extends Component{ constructor(props, context) { super(props, context); } render() { const { user, todos, } = this.props; return ({user.name}); } }
mobx的observer API,用于將React Component變成observable的(動(dòng)態(tài)收集依賴),在對(duì)model中的某些數(shù)據(jù)做了操作之后,如果被修改的數(shù)據(jù)剛好被該React組件使用到了,就會(huì)觸發(fā)該組件的重新渲染,這也就是mobx能細(xì)粒度控制數(shù)據(jù)的原因所在。
mobx-react的inject API,用于指定將哪些model注入進(jìn)React Component(this.props.modelName),也就指定了該組件基于哪些數(shù)據(jù)做Observeable。
model代碼類似于下面這樣:
import TodoItem from "./TodoItem"; import * as api from "../api"; export default { name: "Todos", data: { list: [], }, syncs: { add(text, userId) { // 類似于Vue,對(duì)數(shù)組的操作會(huì)觸發(fā)UI的重新渲染 this.list.push(new TodoItem({ text, userId })); }, }, effects: { async getByUserId(userId) { let todos = await api.getTodosByUserId(userId); todos = todos.map(todo => new TodoItem(todo)); // 類似于Vue,對(duì)數(shù)組的操作會(huì)觸發(fā)UI的重新渲染 this.list = this.list.concat(todos); }, } };
model由以下幾個(gè)部分組成:
1、name: 當(dāng)前model的命名空間;
2、constants: 不可變常量;
3、data: 可操作數(shù)據(jù)部分;
4、syncs: 同步操作數(shù)據(jù)部分;
5、effects: 異步處理部分;
6、init: 初始化model后的回調(diào)方法;
7、autorun: 每次對(duì)數(shù)據(jù)進(jìn)行操作后都會(huì)自動(dòng)執(zhí)行的方法。
觸發(fā)action model內(nèi)部觸發(fā)model內(nèi)部定義的Data數(shù)據(jù),會(huì)被賦值到model實(shí)例上,所以任何在Data中定義的數(shù)據(jù)都可以通過(guò)this.xxx的方式來(lái)引用,如下:
import fetch from "whatwg-fetch"; const pageSize = 20; export default { name: "Applications", data: { dataSource: [ ], // 列表顯示的數(shù)據(jù) detailPageVisible: false, campaignDetail: {}, }, syncs: { validate(value) { value = value ||""; // xxxx return { code: 200 }; }, }, effects:{ async getList(payload = {}) { const { currentPage = 1, } = payload; const url = `/applications/list/${currentPage}?pageSize=${pageSize}`; let res = await fetch(url); res = res.body; const validateRes = this.validate(res); if(validateRes.code == 200) { this.dataSource = res.data; // 這樣就會(huì)觸發(fā)對(duì)應(yīng)Component的重新渲染 this.currentPage = res.currentPage; this.totalItem = res.totalItem; this.totalPage = res.totalPage; } return res; }, } };
可以看到,更改數(shù)據(jù)則是直接給model實(shí)例賦值即可,簡(jiǎn)單直接高效,而且多次賦值只會(huì)觸發(fā)一次的重新渲染。你能想象如果一個(gè)頁(yè)面是一個(gè)list列表,用戶對(duì)列表中某一個(gè)進(jìn)行操作后,需要修改這一項(xiàng)的數(shù)據(jù)及顯示,只需要執(zhí)行類似于:
this.props.home.list[2].name = "New Name";
的代碼就能完成name的數(shù)據(jù)處理及頁(yè)面展示更改嗎?想想就激動(dòng)是不是。
有的同學(xué)會(huì)有:syncs和effects里面多次對(duì)model直接賦值會(huì)觸發(fā)UI的多次渲染的擔(dān)心,其實(shí)不會(huì)的,我們隊(duì)syncs以及effects里面的每一個(gè)方法都用會(huì)使用mobx的action做了一層包裝,從而來(lái)避免這個(gè)問題。
另外,我們也提供this.set()的輔助方法來(lái)方便的為model改值,所以你還可以這樣做:
this.set({ dataSource: res.data, currentPage: res.currentPage, totalItem: res.totalItem, totalPage: res.totalPage, });
這里會(huì)使用mobx的runInAction來(lái)統(tǒng)一執(zhí)行,從而保證UI渲染只執(zhí)行一次。
組件內(nèi)觸發(fā)如下,簡(jiǎn)單直接:
import { inject, observer } from "vanex"; @inject("applications") @observer class Applications extends Component { constructor(props, context) { super(props, context); } clickHandler() { this.props.applications.getList(); // 直接執(zhí)行 } render() { return ( ); } }Vanex插件機(jī)制
Vanex支持插件機(jī)制,使用的方式如下:
import { start, use } from "vanex"; import effectPlugin from "./effect-plugin"; use(effectPlugin); // start代碼
目前已經(jīng)提供的插件列表如下:
onStateChange用于監(jiān)聽數(shù)據(jù)發(fā)生改變的時(shí)候的觸發(fā)回調(diào)。格式如下:
export default { onStateChange: [event => { console.log(event); }] };onEffect
用于處理異步執(zhí)行執(zhí)行前(before)、后(after)、錯(cuò)誤(error)以及過(guò)濾哪些effects執(zhí)行該回調(diào),它在執(zhí)行的時(shí)候其實(shí)是以中間件的形式來(lái)執(zhí)行的。如果有類似于每次請(qǐng)求都自帶csrfToken的需求,則可以在before鉤子函數(shù)中組裝。
具體使用如下:
// Before exec action function preLogger({ type, payload }) { console.log(`[${type}] params: `, payload); payload。csrfToken = "xxx"; // 這里的更改會(huì)對(duì)請(qǐng)求參數(shù)生效 return payload; } // Action exec fail function errorLogger({ type, payload }) { console.log(`[${type}] error: `, payload.message); return payload; } // After exec action function afterLogger({ type, payload }) { console.log(`[${type}] result: `, payload); return payload; } export default { filter({ type }) { return /^User/.test(type); // 只針對(duì)Model名字是User的進(jìn)行下面鉤子函數(shù)的執(zhí)行 }, before: preLogger, after: afterLogger, error: errorLogger, };onAction
用于在執(zhí)行syncs Action之后觸發(fā)。格式如下:
export default { onAction: [( actionName, actionArgs, result) => { console.log(`當(dāng)前執(zhí)行Action的名字:${actionName}`); console.log(`當(dāng)前執(zhí)行Action的參數(shù):${actionArgs}`); console.log(`當(dāng)前執(zhí)行Action的結(jié)果:${result}`); }] };getActionState
這個(gè)并不是Vanex插件,但是用于解決在組件中獲取當(dāng)前model中某個(gè)effect是否正在發(fā)送請(qǐng)求的問題,而這個(gè)狀態(tài)可以用于方便的控制Loading組件是否可見。因?yàn)檫@種需求非常普遍,所以Vanex直接內(nèi)置到內(nèi)部實(shí)現(xiàn)中。使用示例如下:
const { user } = this.props; const { loading: loginLoading, error: loginError } = user.getActionState("user/login");用于開發(fā)組件
有時(shí)候,我們并不想執(zhí)行頁(yè)面渲染,而是用Vanex來(lái)開發(fā)一個(gè)組件,這時(shí),還是可以使用start API,只要不傳如container值,就會(huì)返回一個(gè)React Component。
import React from "react"; import { render } from "react-dom"; import App from "./App"; // load middlewares import middlewares from "./middlewares"; import { start, use, } from "vanex"; use({ onEffect: middlewares }); // model import user from "./models/User"; import todos from "./models/Todos"; // relation import relation from "./relations"; // 驗(yàn)證start返回一個(gè)組件 const MyComponent = start({ component: App, models: { user, todos }, relation }); render(特點(diǎn), document.querySelector("#root"));
簡(jiǎn)單易上手,開發(fā)效率高;
MVVM:Vanex實(shí)現(xiàn)了基于React的MVVM開發(fā)范式,簡(jiǎn)單直接,開發(fā)效率高;
更改store數(shù)據(jù):直接賦值;
觸發(fā)action:直接執(zhí)行store的action;
性能優(yōu)化:自動(dòng)做掉。
為什么基于mobx的開發(fā)范式更簡(jiǎn)單高效?Mobx的實(shí)現(xiàn)思想和Vue幾乎一樣,所以其優(yōu)點(diǎn)跟Vue也差不多:通過(guò)監(jiān)聽數(shù)據(jù)(對(duì)象、數(shù)組)的屬性變化,可以通過(guò)直接在數(shù)據(jù)上更改就能觸發(fā)UI的渲染,從而做到MVVM、響應(yīng)式、上手成本低、開發(fā)效率高,在數(shù)據(jù)管理上需要再詳細(xì)闡述下其區(qū)別。
Redux是建議全局唯一Store的,多個(gè)Reducers也會(huì)在傳遞給react-redux之前被合并成一個(gè)root reducer,任何數(shù)據(jù)的更改(通過(guò)Reducer)都會(huì)通過(guò)這一個(gè)store來(lái)觸發(fā)整個(gè)UI樹的重新渲染,如果不做任何的性能優(yōu)化(pureRender等),就算VD(Virtual Dom)有了再高的效率提升,當(dāng)頁(yè)面數(shù)據(jù)量、DOM數(shù)量大了,性能消耗也是非常大的。另外一點(diǎn),Redux實(shí)現(xiàn)的對(duì)數(shù)據(jù)的管理是pull方式的,就是說(shuō)其只能等待應(yīng)用派發(fā)某個(gè)行為(Action),然后重新觸發(fā)UI的渲染,而做不到對(duì)行為的可預(yù)期;Mobx則不一樣,他是基于監(jiān)聽數(shù)據(jù)的屬性變化來(lái)實(shí)現(xiàn)的,而且是多store的,對(duì)于任何的數(shù)據(jù)變更都是第一時(shí)間知道的,所以其實(shí)現(xiàn)方式是基于push的監(jiān)聽訂閱模式而實(shí)現(xiàn),這樣,他就可以做到對(duì)數(shù)據(jù)的可預(yù)測(cè)以及細(xì)粒度的控制,甚至可以通過(guò)修改React組件生命周期的方式來(lái)減少性能的消耗,而無(wú)需使用者對(duì)這些細(xì)節(jié)關(guān)心。當(dāng)然這一切肯定是有了mobx對(duì)組件做observe操作才能實(shí)現(xiàn)的,所以也就有了observer用的越多,應(yīng)用性能越高的說(shuō)法。
感謝Vanex的部分實(shí)現(xiàn)參考自MVVM框架:mobx-roof。
落地1、內(nèi)容創(chuàng)作投放平臺(tái)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/87347.html
摘要:前言作為官方的腳手架是相當(dāng)好用的。注意就是腳手架的核心配置代碼。另一個(gè)是使用,用戶通過(guò)增加修改配置。所以才有了今天的主題基于的腳手架,確切說(shuō)應(yīng)該是基于的腳手架。其中一定要填寫。前言 create-react-app作為facebook官方的react腳手架是相當(dāng)好用的。主要設(shè)計(jì)原理是將配置好的如Webpack,Babel,ESLint,合并到react-scripts這npm包中,用戶就可以...
摘要:平臺(tái)上的微服務(wù)架構(gòu)應(yīng)用再來(lái)看一下我眼中的基于當(dāng)前最流行的微服務(wù)架構(gòu)的設(shè)計(jì)是什么樣的,即我們平臺(tái)上要運(yùn)行的典型應(yīng)用是什么樣的。 showImg(https://segmentfault.com/img/remote/1460000010900878); 8月19日的數(shù)人云Container Meetup上,張龍老師做了《基于Kubernetes的PaaS平臺(tái)的設(shè)計(jì)和思考》的精彩分享,分別...
摘要:由進(jìn)行開發(fā)和維護(hù),代發(fā)布于年月,現(xiàn)在主要是。狀態(tài)是只讀的,只能通過(guò)來(lái)改變,以避免競(jìng)爭(zhēng)條件這也有助于調(diào)試。文件大小為,而為,為。請(qǐng)記住,性能基準(zhǔn)只能作為考慮的附注,而不是作為判斷標(biāo)準(zhǔn)。使用的人員報(bào)告說(shuō),他們永遠(yuǎn)不必閱讀庫(kù)的源代碼。 本文當(dāng)時(shí)寫在本地,發(fā)現(xiàn)換電腦很不是方便,在這里記錄下。 angular,react & vue 2018/07/23 2016年,對(duì)于JavaScript來(lái)說(shuō)...
摘要:感謝大神的免費(fèi)的計(jì)算機(jī)編程類中文書籍收錄并推薦地址,以后在倉(cāng)庫(kù)里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡(jiǎn)介現(xiàn)在,越來(lái)越多的科技公司和開發(fā)者開始使用開發(fā)各種應(yīng)用。 說(shuō)明 2017-12-14 我發(fā)了一篇文章《沒用過(guò)Node.js,就別瞎逼逼》是因?yàn)橛腥嗽谥跎虾贜ode.js。那篇文章的反響還是相當(dāng)不錯(cuò)的,甚至連著名的hax賀老都很認(rèn)同,下班時(shí)讀那篇文章,竟然坐車的還坐過(guò)站了。大家可以很...
閱讀 3098·2023-04-26 01:58
閱讀 951·2021-11-24 09:38
閱讀 3285·2021-09-03 10:29
閱讀 713·2021-08-21 14:10
閱讀 1488·2019-08-30 15:44
閱讀 3085·2019-08-30 14:10
閱讀 3211·2019-08-29 16:32
閱讀 1476·2019-08-29 12:48