国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

redux 源碼分析,實(shí)現(xiàn)一個(gè)迷你的redux

Ashin / 1778人閱讀

摘要:實(shí)現(xiàn)一個(gè)先不考慮中間件,實(shí)現(xiàn)一個(gè)簡潔的實(shí)現(xiàn)是最主要的一個(gè)了,通過可以創(chuàng)建一個(gè)用來存放應(yīng)用中所有的,一個(gè)應(yīng)用只能有一個(gè)。方法是用來把每一個(gè)用方法包裹一下,因?yàn)榭赡苤皇欠祷匾粋€(gè)具有屬性的對象,只有用執(zhí)行才有意義。正好可以利用的特性實(shí)現(xiàn)這個(gè)效果。

實(shí)現(xiàn)一個(gè)redux 先不考慮中間件,實(shí)現(xiàn)一個(gè)簡潔的redux 實(shí)現(xiàn)createStore

createStore是redux最主要的一個(gè)API了,通過createStore可以創(chuàng)建一個(gè)store用來存放應(yīng)用中所有的state,一個(gè)應(yīng)用只能有一個(gè)store。

// 先創(chuàng)建一個(gè)mini-redux.js文件:
export function createStore(reducer) {
    // 初始化store
    let currentStore = {};
    // 初始化事件列表
    let currentListeners = [];
    
    // 獲取state
    function getState() {
        return currentStore;
    }
    // 訂閱事件
    function subscribe(listener) {
        currentListeners.push(listener);
    }
    // 定義dispatch方法
    function dispatch(action) {
        currentStore = reducer(currentStore, action);
        currentListeners.forEach(v => v());
        // return dispatch;
    }
    // 默認(rèn)執(zhí)行reducer type類型不要命中reducer中自定義的case
    dispatch({type: "@ZQT-REDUX"});
    return {getState, subscribe, dispatch}
}

上面創(chuàng)建了一個(gè)redux.js文件,并暴露了一個(gè)createStore方法,接受reducer作為參數(shù)

// 創(chuàng)建mini-react-redux.js
import React from "react";
import PropTypes from "prop-types";

export const connect = (mapStateToProps = state => state, mapDispatchToProps = {}) => (WrapComponent) => {
    return class connentComponent extends React.Component{
        static contextTypes = {
            store: PropTypes.object
        }
        constructor(props, context) {
            super(props, context);
            this.state = {
                props: {}
            }
        }
        componentDidMount() {
            const {store} = this.context;
            // 為什么非要訂閱  因?yàn)闆]一個(gè)connect實(shí)際上就是一個(gè)訂閱  每當(dāng)dispatch執(zhí)行的時(shí)候  就要重新執(zhí)行以下update方法
            store.subscribe(() => this.update());
            this.update();
        }
        update = () => {
            const {store} = this.context;
            const stateProps = mapStateToProps(store.getState());

            // 每一個(gè)action需要用dispatch包裹一下
            const stateDispatch = bindActionCreators(mapDispatchToProps, store.dispatch);
            this.setState({
                props: {
                    ...this.props,
                    ...stateProps,
                    ...stateDispatch
                }
            })
        }
        render() {
            return 
        }
    }
}

export class Provider extends React.Component{
    static childContextTypes = {
        store: PropTypes.object
    }
    getChildContext() {
        return {
            store: this.store
        }
    }
    constructor(props, context) {
        super(props, context);
        this.store = props.store;
    }
    render() {
        return this.props.children
    }
}

function bindActionCreators(creators, dispatch) {
    const bound = {};
    Object.keys(creators).forEach(v => {
        bound[v] = bindActionCreator(creators[v], dispatch);
    })
    return bound;
}
function bindActionCreator(creator, dispatch) {
    return (...args) => dispatch(creator(...args))
}

上面創(chuàng)建了mini-react-redux.js文件,主要暴露了connect方法和Provider組件。

先看Provider組件。Provider利用的react的context屬性,把store注入到Provider組件,并返回this.props.children(也就是Provider組件里面嵌入的組件,一般是頁面的跟組件App組件),這樣所有的組件都可以共享store。

然后再看connect方法。connect方法是一個(gè)雙重嵌套的方法(專業(yè)名詞叫函數(shù)柯里化)里面的方法接受一個(gè)組件并且返回一個(gè)組件,正式高階組件的用法,外面的函數(shù)接受mapStateToProps和mapDispatchToProps兩個(gè)參數(shù),mapStateToProps是用來把store里面的數(shù)據(jù)映射到組件的props屬性中,mapDispatchToProps是把用戶自己定義的action映射到組件的props屬性中。

在componentDidMount方法里面執(zhí)行了store.subscribe(() => this.update())這句代碼,是因?yàn)槊看问褂胐ispatch觸發(fā)一個(gè)action的時(shí)候都要執(zhí)行一下update方法,即重新獲取store數(shù)據(jù)并映射到組件中去,這樣才能保證store數(shù)據(jù)發(fā)生變化,組件props能同時(shí)跟著變化。

bindActionCreators方法是用來把每一個(gè)action用dispatch方法包裹一下,因?yàn)閍ction可能只是返回一個(gè)具有type屬性的對象,只有用dispatch執(zhí)行action才有意義。

到此為止,一個(gè)沒有中間件的不支持異步dispatch的簡潔版的redux已經(jīng)實(shí)現(xiàn)了,創(chuàng)建一個(gè)demo,就可以看到效果了
// 創(chuàng)建index.js 作為項(xiàng)目入口文件,大家可以自己添加action和reducer,就可以查看效果
import React from "react";
import ReactDOM from "react-dom";
import { createStore, applyMiddleware } from "./mini-redux";
import { counter } from "./index.redux"
import { Provider } from "./mini-react-redux";
import App from "./App"

const store = createStore(counter);
ReactDOM.render(
  (
    
      
    
  ),
  document.getElementById("root"))
支持中間件和異步action的redux實(shí)現(xiàn)

上面實(shí)現(xiàn)了簡潔版的redux,再此基礎(chǔ)上添加支持中間件的代碼

// 修改mini-redux.js為
export function createStore(reducer, enhancer) {
    if(enhancer) {
        return enhancer(createStore)(reducer)
    }
    let currentStore = {};
    let currentListeners = [];

    function getState() {
        return currentStore;
    }

    function subscribe(listener) {
        currentListeners.push(listener);
    }

    function dispatch(action) {
        currentStore = reducer(currentStore, action);
        currentListeners.forEach(v => v());
        // return dispatch;
    }

    dispatch({type: "@ZQT-REDUX"});
    return {getState, subscribe, dispatch}
}

export function applyMiddleware(...middlewares) {
    return createStore=>(...args)=> {
        // 這里args 就是上面createStore 傳過來的reducers
        const store = createStore(...args)
        let dispatch = store.dispatch
        // 暴漏 getState 和 dispatch 給 第三方中間價(jià)使用
        const midApi = {
            getState: store.getState,
            dispatch: (...args) => dispatch(...args)
        }
        // 創(chuàng)造第三方中間件使用 middlewareAPI 后返回的函數(shù)組成的數(shù)組
        const middlewareChain = middlewares.map(middleware => middleware(midApi))
        // 結(jié)合這一組函數(shù) 和 dispatch 組成的新的 dispatch,然后這個(gè)暴漏給用戶使用,而原有的 store.dispatch 是不變的,但是不暴漏
        dispatch = compose(...middlewareChain)(store.dispatch);
        return{
            ...store,
            dispatch
        }
    }
}

export function compose(...funcs) {
    if(funcs.length === 0){
        return arg => arg
    }
    if(funcs.length === 1) {
        return funcs[0]
    }
    return funcs.reduce((ret, item) => (...args) => item(ret(...args)));
}

createStore方法修改了一下,多接受了一個(gè)enhancer方法,enhancer就是在index.js創(chuàng)建store的時(shí)候傳過來的applyMiddleware方法。判斷是否傳了enhancer參數(shù),如果有就return enhancer(createStore)(reducer)

applyMiddleware方法接受多個(gè)中間件作為參數(shù),這個(gè)方法的最終目的就是創(chuàng)建一個(gè)新的dispatch屬性,新的dispatch屬性是經(jīng)過中間件修飾過的,并且暴露這個(gè)新的dispatch屬性,原來的dispatch屬性不變。

compose方法是一個(gè)可以吧compose(fn1,fn2,fn3)(arg)轉(zhuǎn)為fn3(fn2(fn1(arg)))的方法,也就是fn1的執(zhí)行結(jié)果作為fn2的參數(shù),fn2的執(zhí)行結(jié)果作為fn1的參數(shù),依次類推。正好可以利用reduce的特性實(shí)現(xiàn)這個(gè)效果。

const thunk = ({getState, dispatch}) => next => action => {
    // 如果是函數(shù)  就執(zhí)行action
    if(typeof action === "function") {
        return action(dispatch, getState)
    }
    return next(action)
}
export default thunk

異步action在定義的時(shí)候返回的就是一個(gè)接受一個(gè)dispatch的方法,所以如果action是一個(gè)函數(shù),就吧dispatch和getState方法傳給該action,并且執(zhí)行該action。如果不是一個(gè)函數(shù),就直接返回action。

到此為止一個(gè)支持中間件的redux就實(shí)現(xiàn)了,該demo只是為了學(xué)習(xí)redux的思想,不能作為真正的redux來使用,有很多類型檢查代碼都省略了

從實(shí)現(xiàn)迷你版的redux可以體會(huì)到redux精巧的設(shè)計(jì)和函數(shù)式編程的魅力,有隊(duì)函數(shù)式編程感興趣的可以看一下這篇文章https://llh911001.gitbooks.io...

github源碼地址:https://github.com/zhuqitao/z...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/109188.html

相關(guān)文章

  • 去哪兒網(wǎng)迷你React研發(fā)心得

    摘要:市面上竟然擁有多個(gè)虛擬庫。虛擬庫,就是出來后的一種新式庫,以虛擬與算法為核心,屏蔽操作,操作數(shù)據(jù)即操作視圖。及其他虛擬庫已經(jīng)將虛擬的生成交由與處理了,因此不同點(diǎn)是,虛擬的結(jié)構(gòu)與算法。因此虛擬庫是分為兩大派系算法派與擬態(tài)派。 去哪兒網(wǎng)迷你React是年初立項(xiàng)的新作品,在這前,去哪兒網(wǎng)已經(jīng)深耕多年,擁有QRN(react-native的公司制定版),HY(基于React的hybird方案)...

    pekonchan 評論0 收藏0
  • express分析和對比

    摘要:前言目前最新版本是所以本文分析也基于這個(gè)版本。源碼分析直接切入主題由于目前是一個(gè)獨(dú)立的路由和中間件框架。所以分析的方向也以這兩個(gè)為主。源碼去年的時(shí)候有分析過現(xiàn)在對比分析思考下。 前言 目前express最新版本是4.16.2,所以本文分析也基于這個(gè)版本。目前從npm倉庫上來看express使用量挺高的,express月下載量約為koa的40倍。所以目前研究下express還是有一定意義...

    mmy123456 評論0 收藏0
  • 高性能迷你React框架anujs1.1.4發(fā)布

    摘要:本周在支持機(jī)票的項(xiàng)目中對做了大量改進(jìn),包括性能上與結(jié)構(gòu)上的改進(jìn)。但通過一些簡化改改良,代碼的可靠性大大提高了。此外,還有周邊的優(yōu)化在目錄下提供一個(gè),用于在舊式中替換。改善,里面內(nèi)置了一個(gè)補(bǔ)丁,也是用于改善性能,或中的性能好差。 本周在支持機(jī)票的項(xiàng)目中對anujs做了大量改進(jìn),包括性能上與結(jié)構(gòu)上的改進(jìn)。與1.1.3一樣,還是差一個(gè)組件就完全兼容阿里的antd UI庫。 框架本身的改進(jìn)有:...

    elva 評論0 收藏0
  • 動(dòng)手實(shí)現(xiàn)一個(gè)最簡單redux

    摘要:原文地址的主要集中在函數(shù)返回值中,以下這個(gè)迷你的只簡單實(shí)現(xiàn)方法,如下測試代碼運(yùn)行結(jié)果 原文地址:https://github.com/huruji/blog/issues/1 redux的主要API集中在createStore函數(shù)返回值中,以下這個(gè)迷你的redux只簡單實(shí)現(xiàn)createStore、dispatch、subscribe、getState方法,如下: const creat...

    xiguadada 評論0 收藏0
  • redux源碼解讀--applyMiddleware源碼解析

    摘要:的中間件主要是通過模塊實(shí)現(xiàn)的。返回的也是一個(gè)對象這個(gè)其實(shí)就是,各個(gè)中間件的最底層第三層的哪個(gè)函數(shù)組成的圓環(huán)函數(shù)構(gòu)成的這就是對源碼的一個(gè)整體解讀,水平有限,歡迎拍磚。后續(xù)的源碼解讀和測試?yán)涌梢躁P(guān)注源碼解讀倉庫 applyMiddleware源碼解析 中間件機(jī)制在redux中是強(qiáng)大且便捷的,利用redux的中間件我們能夠?qū)崿F(xiàn)日志記錄,異步調(diào)用等多種十分實(shí)用的功能。redux的中間件主要是...

    Atom 評論0 收藏0

發(fā)表評論

0條評論

Ashin

|高級講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<