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

資訊專欄INFORMATION COLUMN

Redux專題:中間件

ybak / 2454人閱讀

摘要:好處就是不再需要能夠處理異步的中間件了。不過(guò),它是一個(gè)研究中間件很好的范本。執(zhí)行它,返回的是由第二層函數(shù)組成的中間件數(shù)組。也就是說(shuō)呀同學(xué)們,除了最后一個(gè)中間件的是原始的之外,倒數(shù)往前的中間件傳入的都是上一個(gè)中間件的邏輯函數(shù)。

本文是『horseshoe·Redux專題』系列文章之一,后續(xù)會(huì)有更多專題推出
來(lái)我的 GitHub repo 閱讀完整的專題文章
來(lái)我的 個(gè)人博客 獲得無(wú)與倫比的閱讀體驗(yàn)

Redux暴露非常少的API,優(yōu)雅的將單向數(shù)據(jù)流落地。但有這些,Redux的作者Dan Abramov仍然覺(jué)得遠(yuǎn)遠(yuǎn)不夠。一個(gè)工具的強(qiáng)大之處體現(xiàn)在它的擴(kuò)展能力上。Redux的中間件機(jī)制讓這種擴(kuò)展能力同樣變的異常優(yōu)雅。

中間件在前端的意思是插入某兩個(gè)流程之間的一段邏輯。具體到Redux,就是在dispatch一個(gè)動(dòng)作前后插入第三方的處理函數(shù)。

使用

還記得嗎?Store構(gòu)造器createStore有三個(gè)參數(shù),第三個(gè)參數(shù)叫做enhancer,翻譯過(guò)來(lái)就是增強(qiáng)器。我們先將enhancer按下不表,并且告訴你其實(shí)Redux的另一個(gè)APIapplyMiddleware就是一個(gè)enhancer。

import { createStore, combineReducers, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import logger from "redux-logger";
import { userReducer } from "./user/reducer";
import { todoReducer } from "./todo/reducer";

const reducers = combineReducers({
    userStore: userReducer,
    todoStore: todoReducer,
});

const enhancer = applyMiddleware(thunk, logger);
const store = createStore(reducers, null, enhancer);

export default store;

只需要把所有中間件依次傳入applyMiddleware,就生成了一個(gè)增強(qiáng)器,它們就可以發(fā)揮作用了。

如果preloadedState為空,enhancer可以作為第二個(gè)參數(shù)傳入。看源代碼:

if (typeof preloadedState === "function" && typeof enhancer === "undefined") {
    enhancer = preloadedState;
    preloadedState = undefined;
}

if (typeof enhancer !== "undefined") {
    if (typeof enhancer !== "function") {
        throw new Error("Expected the enhancer to be a function.");
    }
    return enhancer(createStore)(reducer, preloadedState);
}

if (typeof reducer !== "function") {
    throw new Error("Expected the reducer to be a function.");
}
服務(wù)器請(qǐng)求

一個(gè)組件免不了向服務(wù)器請(qǐng)求數(shù)據(jù),然而開(kāi)發(fā)者不希望組件內(nèi)部有過(guò)多的邏輯,請(qǐng)求應(yīng)該封裝成函數(shù)給組件調(diào)用,同時(shí)組件需要實(shí)時(shí)獲取請(qǐng)求的狀態(tài)以便展示不同的界面。最好的辦法就是將請(qǐng)求也納入Redux的管理中。

import api from "./api";

export const fetchMovieAction = () => {
    dispatch({ type: "FETCH_MOVIE_START" });
    api.fetchMovie().then(res => {
        dispatch({ type: "FETCH_MOVIE_END", payload: { movies: res.data } });
    }).catch(err => {
        dispatch({ type: "FETCH_MOVIE_ERROR", error: true, payload: { msg: err } });
    });
};
import React, { Component } from "react";
import { connect } from "react-redux";

import { fetchMovieAction } from "./actions";
import Card from "./Card";

class App extends Component {
    render() {
        const { movies } = this.props;
        return (
            
{movies.map(movie => )}
); } componentDidMount() { this.props.fetchMovie(); } } const mapState = (state) => { return { movies: state.payload.movies, }; }; const mapDispatch = (dispatch) => { return { fetchMovie: () => dispatch(fetchMovieAction()), }; }; export default connect(mapState, mapDispatch)(App);

大功告成了。

只需要將請(qǐng)求封裝成一個(gè)函數(shù),然后偽裝成Action被發(fā)射出去,請(qǐng)求調(diào)用前后,真正的Action會(huì)被發(fā)射,在Store中存儲(chǔ)請(qǐng)求的狀態(tài),并且能夠被組件訂閱到。

異步Action

你是不是發(fā)現(xiàn)了什么?對(duì)咯,這里的Action不是一個(gè)純對(duì)象。

因?yàn)檎?qǐng)求一定是一個(gè)函數(shù),為了讓請(qǐng)求入會(huì),只能反過(guò)頭來(lái)修改大會(huì)章程。但是大會(huì)章程豈能隨便推翻,這時(shí)意見(jiàn)領(lǐng)袖出來(lái)說(shuō)話了:

當(dāng)初規(guī)定Action必須是一個(gè)純對(duì)象不是為了搞個(gè)人崇拜,而是出于實(shí)際需要。因?yàn)閞educer必須是一個(gè)純函數(shù),這決定了dispatch的參數(shù)Action必須是一個(gè)帶type字段的純對(duì)象。現(xiàn)如今我們要拉異步請(qǐng)求入會(huì),而中間件又可以中途攔截做一些處理,那Action為什么不能是一個(gè)函數(shù)呢?Action必須是一個(gè)純對(duì)象這種說(shuō)法是完完全全的教條主義!

大家還動(dòng)腦筋想出了一個(gè)異步Action的名頭,這下函數(shù)類型的Action終于名正言順了。

閉包

你是不是還發(fā)現(xiàn)了什么?對(duì)咯,請(qǐng)求函數(shù)中的dispatch哪去了。

不知道,可能會(huì)報(bào)錯(cuò)吧(無(wú)辜臉)。

其實(shí)我們還有一件事沒(méi)干:把dispatch方法偷渡到請(qǐng)求函數(shù)中。

export const fetchMovieAction = () => {
    return (dispatch) => {
        dispatch({ type: "FETCH_MOVIE_START" });
        api.fetchMovie().then(res => {
            dispatch({ type: "FETCH_MOVIE_END", payload: { movies: res.data } });
        }).catch(err => {
            dispatch({ type: "FETCH_MOVIE_ERROR", error: true, payload: { msg: err } });
        });
    };
};

很簡(jiǎn)單哪,加一個(gè)閉包,dispatch從返回函數(shù)的參數(shù)中偷渡進(jìn)來(lái)。

腦洞

我們要的不就是一個(gè)dispatch方法么,我能不能這樣:

export const fetchMovie = (dispatch) => {
    dispatch({ type: "FETCH_MOVIE_START" });
    api.fetchMovie().then(res => {
        dispatch({ type: "FETCH_MOVIE_END", payload: { movies: res.data } });
    }).catch(err => {
        dispatch({ type: "FETCH_MOVIE_ERROR", error: true, payload: { msg: err } });
    });
};
const mapDispatch = (dispatch) => {
    return {
        fetchMovie: () => fetchMovie(dispatch),
    };
};

貌似是能行得通的,只不過(guò)這時(shí)候請(qǐng)求函數(shù)已經(jīng)不能叫Action了。考慮到之前請(qǐng)求函數(shù)偽裝成Action渾水摸魚(yú),還要插入中間件來(lái)幫助特殊處理,我們這樣做也不過(guò)分是吧。

好處就是不再需要能夠處理異步Action的中間件了。

壞處就是這不符合規(guī)范,是我的腦洞,闖了禍不要打我(蔑視)。

redux-thunk

前面多次提到處理異步Action的中間件,到底是何方神圣?

市面上流行的方案有很多種,我們挑最簡(jiǎn)單的一種來(lái)說(shuō)一說(shuō)(都不點(diǎn)贊怪我咯)。

redux-thunk算是Redux官方出品的異步請(qǐng)求中間件,但是它沒(méi)有集成到Redux中,原因還是為了擴(kuò)展性,社區(qū)可以提出各種方案,開(kāi)發(fā)者各取所需。

讓我們來(lái)探討一下redux-thunk的思路:原來(lái)Action只有一種,就是純對(duì)象,現(xiàn)在Action有兩種,純對(duì)象和異步請(qǐng)求函數(shù)。只不過(guò)多了一種情況,不算棘手嘛。如果Action是一個(gè)對(duì)象,不為難它直接放走;如果Action是一個(gè)函數(shù),就地執(zhí)行,調(diào)用異步請(qǐng)求前后,真正的Action自然會(huì)釋放出來(lái),又回到第一步,放它走。

這是redux-thunk簡(jiǎn)化后的代碼,其實(shí)源代碼也跟這差不多。是不是很恐慌?

const thunk = ({ dispatch, getState }) => next => action => {
    if (typeof action === "function") {
        return action(dispatch, getState);
    }
    return next(action);
};

上面的函數(shù)就部署在我的個(gè)人博客中用來(lái)處理異步請(qǐng)求,完全沒(méi)有問(wèn)題。既然它這么簡(jiǎn)單,而且可以預(yù)計(jì)它萬(wàn)年不會(huì)變,那我為什么要憑空多一個(gè)依賴包。就將它放在我的眼皮底下不是挺好的嘛。

不過(guò),它是一個(gè)研究中間件很好的范本。

我們先將thunk先生降級(jí)成普通函數(shù)的寫法:

const thunk = function({ dispatch, getState }) {
    return function(next) {
        return function(action) {
            if (typeof action === "function") {
                return action(dispatch, getState);
            }
            return next(action);
        }
    }
};
compose

我知道compose是Redux的五大護(hù)法之一,可為什么挑在這個(gè)時(shí)候講它呢?

先不告訴你。

compose在函數(shù)式編程中的含義是組合。假如你有一堆函數(shù)要依次執(zhí)行,而且上一個(gè)函數(shù)的返回結(jié)果是下一個(gè)函數(shù)的參數(shù),我們?cè)鯓訉懣雌饋?lái)最裝逼?

const result = a(b(c(d(e("redux")))));

這種寫法讓人一眼就看穿了調(diào)用細(xì)節(jié),裝逼明顯是不夠的。

我們來(lái)看Redux是怎么實(shí)現(xiàn)compose的:

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

誒,我看見(jiàn)reduce了,然后...就沒(méi)有然后了。

假設(shè)我們現(xiàn)在有三個(gè)函數(shù):

const funcA = arg => console.log("funcA", arg);
const funcB = arg => console.log("funcB", arg);
const funcC = arg => console.log("funcC", arg);

執(zhí)行reduce的第一步返回的accumulator(accumulator是reduce中的概念),結(jié)果顯而易見(jiàn):

(...args) => funcA(funcB(...args));

執(zhí)行reduce的第二步返回的accumulator,注意到,這時(shí)reduce已經(jīng)執(zhí)行完了,返回的是一個(gè)函數(shù)。

(...args) => funcA(funcB(funcC(...args)));

特別提醒:執(zhí)行compose最終返回的是一個(gè)函數(shù)。也就是說(shuō)開(kāi)發(fā)者得這么干compose(a, b, c)()才能讓傳入的函數(shù)依次執(zhí)行。

另外需要注意的是:傳入的函數(shù)是從右到左依次執(zhí)行的。

applyMiddleware

廢話少說(shuō),先上源代碼:

export default function applyMiddleware(...middlewares) {
    return createStore => (...args) => {
        const store = createStore(...args);
        let dispatch = () => {
            throw new Error(
                `Dispatching while constructing your middleware is not allowed. ` +
                `Other middleware would not be applied to this dispatch.`
            );
        };
        const middlewareAPI = {
            getState: store.getState,
            dispatch: (...args) => dispatch(...args),
        };
        const chain = middlewares.map(middleware => middleware(middlewareAPI));
        dispatch = compose(...chain)(store.dispatch);
        return { ...store, dispatch };
    }
}

還記得中間件閉包好幾層的寫法嗎?現(xiàn)在我們就來(lái)一層一層的剝開(kāi)它。

middlewareAPI是一個(gè)對(duì)象,正好是傳給第一層中間件函數(shù)的參數(shù)。執(zhí)行它,返回的chain是由第二層函數(shù)組成的中間件數(shù)組。貼一下redux-thunk第二層轉(zhuǎn)正后的樣子:

function(next) {
    return function(action) {
        if (typeof action === "function") {
            return action(dispatch, getState);
        }
        return next(action);
    }
}

中間件第二層函數(shù)接收一個(gè)next參數(shù),那這個(gè)next具體指什么呢?我先透露一下,next是整個(gè)Redux中間件機(jī)制的題眼,理解了next就可以對(duì)Redux中間件的理解達(dá)到大徹大悟的化境。

之前我們已經(jīng)拆解了compose的內(nèi)部機(jī)制,從右到左執(zhí)行,最右邊的中間件的參數(shù)就是store.dispatch,它返回的值就是倒數(shù)第二個(gè)中間件的next。它返回什么呢?我們?cè)賱円粚樱?/p>

function(action) {
    if (typeof action === "function") {
        return action(dispatch, getState);
    }
    return next(action);
}

別看redux-thunk麻雀雖小,大家發(fā)現(xiàn)沒(méi)有,第三層函數(shù)才是它的邏輯,前面兩層都是配合redux的演出。也就是說(shuō)呀同學(xué)們,除了最后一個(gè)中間件的next是原始的dispatch之外,倒數(shù)往前的中間件傳入的next都是上一個(gè)中間件的邏輯函數(shù)。

Redux中間件本質(zhì)上是將dispatch套上一層自己的邏輯。

最終applyMiddleware里得到的這個(gè)dispatch是經(jīng)過(guò)無(wú)數(shù)中間件精心包裝,植入了自己的邏輯的dispatch。然后用這個(gè)臃腫的dispatch覆蓋原有的dispatch,將Store的API返回。

每一個(gè)Action就是這樣穿過(guò)重重的邏輯代碼才能最后被發(fā)射成功。只不過(guò)處理異步請(qǐng)求的中間件不再往下走,直到異步請(qǐng)求發(fā)生,真正的Action被發(fā)射出來(lái),才會(huì)走到下一個(gè)中間件的邏輯。

構(gòu)建dispatch過(guò)程中禁止執(zhí)行dispatch

middlewareAPI中的dispatch為什么是一個(gè)拋出錯(cuò)誤的函數(shù)?

我們現(xiàn)在已經(jīng)知道,applyMiddleware的目的只有一個(gè):用所有中間件組裝成一個(gè)超級(jí)dispatch,并將它覆蓋原生的dispatch。但是如果超級(jí)dispatch還沒(méi)組裝完成,就被中間件調(diào)用了原生的dispatch,那這游戲別玩了。

所以Redux來(lái)了一手掉包。

middlewareAPI初始傳入的dispatch是一個(gè)炸彈,中間件的開(kāi)發(fā)者膽敢在頭兩層閉包函數(shù)的外層作用域調(diào)用dispatch,炸彈就會(huì)引爆。而一旦超級(jí)dispatch構(gòu)建完成,這個(gè)超級(jí)dispatch就會(huì)替換掉炸彈。

怎么替換呢?

函數(shù)也是引用類型對(duì)吧,炸彈dispatch之所以用let定義,就是為了將來(lái)修改它的引用地址:

let dispatch = () => {
    throw new Error(
        `Dispatching while constructing your middleware is not allowed. ` +
        `Other middleware would not be applied to this dispatch.`
    );
};
// ...
dispatch = compose(...chain)(store.dispatch);

當(dāng)然,這是對(duì)中間件開(kāi)發(fā)者的約束,如果你只是一個(gè)中間件的使用者,這無(wú)關(guān)緊要。

applyMiddleware的花式調(diào)用

我們注意到,執(zhí)行applyMiddleware返回的是一個(gè)函數(shù),這個(gè)函數(shù)有唯一的參數(shù)createStore。

WTF?

applyMiddleware不是createStore的參數(shù)之一么:

const store = createStore(reducer, applyMiddleware(middleware1, middleware2, middleware3));

怎么createStore也成了applyMiddleware的參數(shù)了?

貴圈真亂。

首先我們明確一點(diǎn),applyMiddleware是一個(gè)增強(qiáng)器,增強(qiáng)器是需要改造Store的API的,這樣才能達(dá)到增強(qiáng)Store的目的。所以applyMiddleware必須傳入createStore以生成初始的Store。

所以生成一個(gè)最終的Store其實(shí)可以這樣寫:

const enhancedCreateStore = applyMiddleware(middleware1, middleware2, middleware3)(createStore);
const store = enhancedCreateStore(reducer);

那通常的那種寫法,Redux內(nèi)部是怎么處理的呢?

if (typeof enhancer !== "undefined") {
    if (typeof enhancer !== "function") {
        throw new Error("Expected the enhancer to be a function.")
    }
    return enhancer(createStore)(reducer, preloadedState)
}

上面是createStore源代碼中的一段。

如果enhancer存在并且是一個(gè)函數(shù),那么直接傳入createStore執(zhí)行,再傳入reducer和preloadedState執(zhí)行(這時(shí)候再傳入enhancer就沒(méi)完沒(méi)了了),然后直接返回。

喵,后面還有好多代碼呢,怎么就返回了?

不,就這么任性。

這么看下來(lái),以下寫法才是正宗的Redux:

const store = applyMiddleware(middleware1, middleware2, middleware3)(createStore)(reducer);

以下寫法只是Redux為開(kāi)發(fā)者準(zhǔn)備的語(yǔ)法糖:

const store = createStore(reducer, applyMiddleware(middleware1, middleware2, middleware3));
洋蔥圈模型

想必大家都聽(tīng)說(shuō)過(guò)中間件的洋蔥圈模型,這個(gè)比喻非常形象,乍聽(tīng)上去,啊,好像明白了。但是大家真的對(duì)洋蔥圈模型有一個(gè)具象化的理解嗎?

假設(shè)現(xiàn)在有三個(gè)中間件:

const middleware1 = ({ dispatch, getState }) => next => action => {
    console.log("middleware1 start");
    next(action);
    console.log("middleware1 end");
}

const middleware2 = ({ dispatch, getState }) => next => action => {
    console.log("middleware2 start");
    next(action);
    console.log("middleware2 end");
}

const middleware3 = ({ dispatch, getState }) => next => action => {
    console.log("middleware3 start");
    next(action);
    console.log("middleware3 end");
}

現(xiàn)在將它傳入applyMiddleware:

function reducer(state = {}, action) {
    console.log("reducer return state");
    return state;
}

const middlewares = [middleware1, middleware2, middleware3];
const store = createStore(reducer, applyMiddleware(...middlewares));

我們看一下打印的結(jié)果:

middleware1 start
middleware2 start
middleware3 start
reducer return state
middleware3 end
middleware2 end
middleware1 end

對(duì)結(jié)果感到驚訝嗎?其實(shí)理解函數(shù)調(diào)用棧的同學(xué)就能明白為什么是這樣的結(jié)果。reducer執(zhí)行之前也就是dispatch真正執(zhí)行之前的日志好理解,dispatch被一層一層包裝,一層一層的深入調(diào)用。但是dispatch執(zhí)行完以后呢?這時(shí)候的執(zhí)行權(quán)在調(diào)用棧最深的那一層邏輯那里,也就是最接近原始dispatch的邏輯函數(shù)那里,所以之后的執(zhí)行順序是從最深處往上調(diào)用。

總的看下來(lái),一個(gè)Action的更新Store之旅就像穿過(guò)一個(gè)洋蔥圈的旅行。一堆中間件簇?fù)碇鳤ction鉆到洋蔥的中心,Action執(zhí)行自己的使命更新Store后就地圓寂,然后中間件帶著它的遺志再?gòu)难笫[的中心鉆出來(lái)。

回看compose

其實(shí)我解釋上面的打印日志,還有一個(gè)關(guān)節(jié)沒(méi)有打通。

記得applyMiddleware的源代碼嗎??jī)?nèi)部調(diào)用了compose來(lái)執(zhí)行chain。

我們強(qiáng)調(diào)過(guò),compose的函數(shù)類型參數(shù)的執(zhí)行順序是從右到左的,我相信大家在不少的地方都見(jiàn)到過(guò)這樣的表述。但是大家想過(guò)沒(méi)有,為什么要從右到左執(zhí)行?原生JavaScript除了實(shí)現(xiàn)reduce之外還有一個(gè)reduceRight,從左到右執(zhí)行并沒(méi)有什么技術(shù)障礙,那么為什么要讓執(zhí)行順序這么別扭呢?

答案就在上面的打印日志里。

打印日志很好哇,根據(jù)傳入的順序執(zhí)行。對(duì),執(zhí)行compose是從右到左,但是compose返回的終極dispatch是一層一層從外面包裹的呀,最后一個(gè)中間件也就是最左邊的中間件的邏輯,包裹在最外面一層,自然它的日志最先被打印出來(lái)。

所以compose被設(shè)計(jì)成參數(shù)從右到左執(zhí)行,不是有技術(shù)障礙,也不是Redux特立獨(dú)行,而是其中本來(lái)就要經(jīng)歷一次反轉(zhuǎn),compose只有再反轉(zhuǎn)一次才能將它扭轉(zhuǎn)過(guò)來(lái)。

Redux專題一覽

考古
實(shí)用
中間件
時(shí)間旅行

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

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

相關(guān)文章

  • Redux專題:考古

    摘要:光憑一個(gè)是無(wú)法實(shí)現(xiàn)血緣關(guān)系疏遠(yuǎn)的組件之間的狀態(tài)同步的。就是為解決這個(gè)問(wèn)題而生的。,處理動(dòng)作的派發(fā),相當(dāng)于架構(gòu)的。我們的主角是,它也是目前社區(qū)最受歡迎的狀態(tài)管理框架。專題一覽考古實(shí)用中間件時(shí)間旅行 本文是『horseshoe·Redux專題』系列文章之一,后續(xù)會(huì)有更多專題推出來(lái)我的 GitHub repo 閱讀完整的專題文章來(lái)我的 個(gè)人博客 獲得無(wú)與倫比的閱讀體驗(yàn) React的橫空出世給...

    toddmark 評(píng)論0 收藏0
  • React專題:react,redux以及react-redux常見(jiàn)一些面試題

    摘要:我們可以為元素添加屬性然后在回調(diào)函數(shù)中接受該元素在樹(shù)中的句柄,該值會(huì)作為回調(diào)函數(shù)的第一個(gè)參數(shù)返回。使用最常見(jiàn)的用法就是傳入一個(gè)對(duì)象。單向數(shù)據(jù)流,比較有序,有便于管理,它隨著視圖庫(kù)的開(kāi)發(fā)而被概念化。 面試中問(wèn)框架,經(jīng)常會(huì)問(wèn)到一些原理性的東西,明明一直在用,也知道怎么用, 但面試時(shí)卻答不上來(lái),也是挺尷尬的,就干脆把react相關(guān)的問(wèn)題查了下資料,再按自己的理解整理了下這些答案。 reac...

    darcrand 評(píng)論0 收藏0
  • Redux專題:實(shí)用

    摘要:在英文中的意思是有效載荷。有一個(gè)動(dòng)作被發(fā)射了顧名思義,替換,這主要是方便開(kāi)發(fā)者調(diào)試用的。相同的輸入必須返回相同的輸出,而且不能對(duì)外產(chǎn)生副作用。怎么辦呢開(kāi)發(fā)者得手動(dòng)維護(hù)一個(gè)訂閱器,才能監(jiān)聽(tīng)到狀態(tài)變化,從而觸發(fā)頁(yè)面重新渲染。 本文是『horseshoe·Redux專題』系列文章之一,后續(xù)會(huì)有更多專題推出來(lái)我的 GitHub repo 閱讀完整的專題文章來(lái)我的 個(gè)人博客 獲得無(wú)與倫比的閱讀體...

    Big_fat_cat 評(píng)論0 收藏0
  • React 328道最全面試題(持續(xù)更新)

    摘要:希望大家在這浮夸的前端圈里,保持冷靜,堅(jiān)持每天花分鐘來(lái)學(xué)習(xí)與思考。 今天的React題沒(méi)有太多的故事…… 半個(gè)月前出了248個(gè)Vue的知識(shí)點(diǎn),受到很多朋友的關(guān)注,都強(qiáng)烈要求再出多些React相前的面試題,受到大家的邀請(qǐng),我又找了20多個(gè)React的使用者,他們給出了328道React的面試題,由我整理好發(fā)給大家,同時(shí)發(fā)布在了前端面試每日3+1的React專題,希望對(duì)大家有所幫助,同時(shí)大...

    kumfo 評(píng)論0 收藏0
  • B站Up主-山地人-這位老哥2019年的前端自學(xué)計(jì)劃進(jìn)展如何?——講一個(gè)B站Up主自學(xué)前端85天的故

    摘要:前言自從上次在掘金發(fā)布年山地人的前端完整自學(xué)計(jì)劃講一個(gè)站主山地人的天前端自學(xué)故事以來(lái),一眨眼山地人老哥在站做主已經(jīng)有天了。所以這個(gè)體系里的一些框架包括也是山地人年自學(xué)計(jì)劃的一部分。月底,山地人老哥開(kāi)啟了的兩個(gè)專題。 前言 自從上次在掘金發(fā)布【2019年山地人的前端完整自學(xué)計(jì)劃——講一個(gè)B站UP主山地人的40天前端自學(xué)故事】 以來(lái),一眨眼山地人老哥在B站做Up主已經(jīng)有85天了。 時(shí)隔一個(gè)...

    cocopeak 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

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