欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

next-redux-wrapper使用細(xì)節(jié)及源碼分析

 更新時間:2023年02月12日 14:40:12   作者:拾光者  
這篇文章主要為大家介紹了next-redux-wrapper使用細(xì)節(jié)及源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

前幾天寫了一篇文章講解了 wrapper 概念,本篇文章主要從源碼分析它的實(shí)現(xiàn)過程,去更好的理解服務(wù)端使用 redux 的注意事項。

先附上一份主要代碼結(jié)構(gòu)圖:

目錄結(jié)構(gòu)

.
├── lerna.json
├── package.json
├── packages
│   ├── configs
│   ├── demo
│   ├── demo-page
│   ├── demo-redux-toolkit
│   ├── demo-saga
│   ├── demo-saga-page
│   └── wrapper
└── yarn.lock

可以明顯的看出來這是一個用 lerna 管理的 monorepo 倉庫

demo-* 開頭的是案例庫,而configs 庫也是為案例庫服務(wù)的,那么只用管 wrapper 庫即可。

wrapper 結(jié)構(gòu):

packages/wrapper
├── jest.config.js jest 配置
├── next-env.d.ts
├── package.json
├── src
│   └── index.tsx 核心實(shí)現(xiàn)代碼
├── tests 測試代碼
│   ├── client.spec.tsx
│   ├── server.spec.tsx
│   └── testlib.tsx
├── tsconfig.es6.json
└── tsconfig.json

核心代碼都在 packages/wrapper/src/index.tsx文件,下面開始分析。

代碼結(jié)構(gòu)

把大部分代碼的具體實(shí)現(xiàn)去掉,然后留下整體代碼的頂層聲明:

// 用于客戶端 hydrate 的時發(fā)送初始化指令用的 action key
export const HYDRATE = '__NEXT_REDUX_WRAPPER_HYDRATE__';
// 用于判斷是否是服務(wù)器
const getIsServer = () => typeof window === 'undefined';
// 用于反序列化 State,類似解密函數(shù)
const getDeserializedState = <S extends Store>(initialState: any, {deserializeState}: Config<S> = {}) =>
    deserializeState ? deserializeState(initialState) : initialState;
// 用于序列化 State,類似加密函數(shù)
const getSerializedState = <S extends Store>(state: any, {serializeState}: Config<S> = {}) =>
    serializeState ? serializeState(state) : state;
// 客戶端存儲 store 用的變量
let sharedClientStore: any;
// 初始化 redux store
const initStore = <S extends Store>({makeStore, context = {}}: InitStoreOptions<S>): S => {
// ...
};
// 創(chuàng)建 wrapper
export const createWrapper = <S extends Store>(makeStore: MakeStore<S>, config: Config<S> = {}) => {
    // ...
    return {
        getServerSideProps,
        getStaticProps,
        getInitialAppProps,
        getInitialPageProps,
        // 以前的函數(shù),忽略掉,不建議使用了
        withRedux,
        useWrappedStore,
    };
};
// 以前的函數(shù),忽略掉,不建議使用了
export default <S extends Store>(makeStore: MakeStore<S>, config: Config<S> = {}) => {
    // ...
    return createWrapper(makeStore, config).withRedux;
};

代碼分析:

  • HYDRATE,常量,用于客戶端 react 執(zhí)行 hydrate 的時發(fā)送初始化指令用的 action key。
  • getIsServer 用于判斷是否是服務(wù)器.
  • getDeserializedState 用于反序列化 State ,類似解密函數(shù),依賴外部使用方傳入。
  • getSerializedState 用于序列化 State ,類似加密函數(shù),依賴外部使用方傳入。
  • sharedClientStore 變量,用于客戶端存儲 redux store 用的,用在 initStore 中。
  • initStore 初始化 redux store ,主要是處理 服務(wù)端 和 客戶端 在創(chuàng)建時緩存的位置問題。
  • createWrapper 創(chuàng)建 wrapper 核心
  • default 默認(rèn)導(dǎo)出函數(shù),以前的函數(shù),忽略掉,不建議使用了,主要使用 createWrapper 函數(shù)返回的 withRedux 函數(shù),因此本篇文章不進(jìn)行講解 withRedux 函數(shù)。

一共就 8 個聲明,其中只暴露了 HYDRATEcreateWrapper 和默認(rèn)導(dǎo)出函數(shù),忽略掉默認(rèn)導(dǎo)出函數(shù)。

下面進(jìn)行對 createWrapper 函數(shù)的分析。

核心實(shí)現(xiàn)

createWrapper 整體實(shí)現(xiàn)概覽

// 創(chuàng)建 wrapper
export const createWrapper = <S extends Store>(makeStore: MakeStore<S>, config: Config<S> = {}) => {
    // 幾個 wrapper 函數(shù)的實(shí)際核心實(shí)現(xiàn)函數(shù)
    const makeProps = async (): Promise<WrapperProps> => {/** ... */};
    // 頁面級 getInitialProps 函數(shù)的包裹函數(shù)
    const getInitialPageProps = (callback) => async (context) => {/** ... */};
    // 應(yīng)用級 getInitialProps 函數(shù)的包裹函數(shù)
    const getInitialAppProps = (callback) => async (context) => {/** ... */};
    // getStaticProps 函數(shù)的包裹函數(shù)
    const getStaticProps = (callback) => async (context) => {/** ... */};
    // getServerSideProps 函數(shù)的包裹函數(shù)
    const getServerSideProps = (callback) => async (context) => await getStaticProps(callback)(context);
    // hydrate 處理函數(shù),調(diào)用 store.dispatch 發(fā)起初始化 
    const hydrate = (store: S, state: any) => {
        if (!state) {
            return;
        }
        store.dispatch({
            type: HYDRATE,
            payload: getDeserializedState<S>(state, config),
        } as any);
    };
    // hydrate 處理中間數(shù)據(jù)的函數(shù)(用于分析處理各種情況)
    const hydrateOrchestrator = (store: S, giapState: any, gspState: any, gsspState: any, gippState: any) => {
        //...
    };
    // redux hydrate 執(zhí)行 hook
    const useHybridHydrate = (store: S, giapState: any, gspState: any, gsspState: any, gippState: any) => {
        // ...
    };
    // 用于在應(yīng)用中關(guān)聯(lián) store 的 hook。一般用在 App 組件
    // giapState stands for getInitialAppProps state
    const useWrappedStore = <P extends AppProps>(incomingProps: P, displayName = 'useWrappedStore'): {store: S; props: P} => {
        // ...
        return {store, props: {...initialProps, ...resultProps}};
    };
    return {
        getServerSideProps,
        getStaticProps,
        getInitialAppProps,
        getInitialPageProps,
        useWrappedStore,
    };
};

可以把 createWrapper 函數(shù)的內(nèi)容分兩類:

  • Next.js 數(shù)據(jù)獲取函數(shù)的包裹函數(shù)實(shí)現(xiàn)。
  • Next.js 渲染頁面內(nèi)容 時的處理實(shí)現(xiàn)。

從 數(shù)據(jù)獲取 到 渲染頁面內(nèi)容 本身就有一個前后順序,這里也按照這個順序來分析。

createWrapper 中 數(shù)據(jù)獲取函數(shù) 的包裹函數(shù)實(shí)現(xiàn)分析

callback 函數(shù)說明,就是我們調(diào)用 wrapper.[wrapperFunctionName] 函數(shù)時傳遞的參數(shù)。

比如:

App.getInitialProps = wrapper.getInitialAppProps(({ store }) => async (ctx) => {
  // ...
});

callback 就是 ({ store }) => async (ctx) => {} 這部分代碼.

我們來看幾個 數(shù)據(jù)獲取函數(shù) 的代碼:

// 頁面級 getInitialProps 函數(shù)的包裹函數(shù)
const getInitialPageProps =
    <P extends {} = any>(callback: PageCallback<S, P>): GetInitialPageProps<P> =>
    async (
        context: NextPageContext | any, // legacy
    ) => {
        // context 中會存儲 store — 避免雙重包裝,因?yàn)橛锌赡苌蠈咏M件也調(diào)用了 `getInitialPageProps` 或者 `getInitialAppProps` 函數(shù)。
        if ('getState' in context) {
            // 有緩存的 store ,直接給 callback 傳入的 store
            return callback && callback(context as any);
        }
        // 調(diào)用 makeProps 執(zhí)行開發(fā)者傳入要執(zhí)行的函數(shù)
        return await makeProps({callback, context, addStoreToContext: true});
    };
// 應(yīng)用級 getInitialProps 函數(shù)的包裹函數(shù)
const getInitialAppProps =
    <P extends {} = any>(callback: AppCallback<S, P>): GetInitialAppProps<P> =>
    async (context: AppContext) => {
        // 調(diào)用 makeProps 執(zhí)行開發(fā)者傳入要執(zhí)行的函數(shù)
        const {initialProps, initialState} = await makeProps({callback, context, addStoreToContext: true});
        // 每個 `數(shù)據(jù)獲取函數(shù)` 最后需要的返回函數(shù)類型不一樣,因此需要處理成 Next.js 需要的類型
        return {
            ...initialProps,
            initialState,
        };
    };
// getStaticProps 函數(shù)的包裹函數(shù)
const getStaticProps =
    <P extends {} = any>(callback: GetStaticPropsCallback<S, P>): GetStaticProps<P> =>
    async context => {
        // 調(diào)用 makeProps 函數(shù)時,相比 getInitialPageProps 和 getInitialAppProps 缺少了 addStoreToContext 參數(shù)
        const {initialProps, initialState} = await makeProps({callback, context});
        return {
            ...initialProps,
            props: {
                ...initialProps.props,
                initialState,
            },
        } as any;
    };
// getServerSideProps 函數(shù)的包裹函數(shù)
const getServerSideProps =
    <P extends {} = any>(callback: GetServerSidePropsCallback<S, P>): GetServerSideProps<P> =>
    async context =>
        await getStaticProps(callback as any)(context); // 返回參數(shù)和static一樣,因此直接調(diào)用 getStaticProps 函數(shù)即可

我們可以看出幾個函數(shù)的主要區(qū)別點(diǎn)在于 參數(shù)類型(也就是context 類型) 和 返回值類型 不一致,這也是 Next.js 不同數(shù)據(jù)獲取函數(shù) 的區(qū)別之一。

getInitialPageProps 需要注意有可能上層組件也調(diào)用了 getInitialPageProps 或者 getInitialAppProps 函數(shù)。 因此需要判斷是否把 store 存儲到了 context 中,是的話,需要直接從 context 中獲取。(注釋是這樣的,這里有點(diǎn)問題,待驗(yàn)證)

getInitialAppPropsgetInitialPageProps 實(shí)現(xiàn)類似,只是只需要執(zhí)行一次,不用考慮緩存,還有就是 返回值類型 不一樣

getStaticProps 調(diào)用 makeProps 函數(shù)時,相比 getInitialPagePropsgetInitialAppProps 缺少了 addStoreToContext 參數(shù),返回值也不一樣。

getServerSideProps 返回參數(shù)和 getStaticProps 一樣,因此直接調(diào)用 getStaticProps 函數(shù)即可。

接下來就是幾個數(shù)據(jù)獲取的 wrapper 函數(shù) 的實(shí)際核心實(shí)現(xiàn),也就是 makeProps 函數(shù):

// 數(shù)據(jù)獲取的 `wrapper 函數(shù)` 的實(shí)際核心
const makeProps = async ({
    callback,
    context,
    addStoreToContext = false,
}: {
    callback: Callback<S, any>;
    context: any;
    addStoreToContext?: boolean;
}): Promise<WrapperProps> => {
    // 服務(wù)端初始化 store
    const store = initStore({context, makeStore});
    if (config.debug) {
        console.log(`1. getProps created store with state`, store.getState());
    }
    // Legacy stuff - 把 store 放入 context 中
    if (addStoreToContext) {
        if (context.ctx) {
            context.ctx.store = store;
        } else {
            context.store = store;
        }
    }
    // 這里實(shí)現(xiàn)了 callback 雙層函數(shù)執(zhí)行,先傳遞 store 給 callback 生成新的函數(shù)
    const nextCallback = callback && callback(store);
    // 再用新的函數(shù)傳遞 context 參數(shù),獲取 initialProps
    const initialProps = (nextCallback && (await nextCallback(context))) || {};
    if (config.debug) {
        console.log(`3. getProps after dispatches has store state`, store.getState());
    }
    const state = store.getState();
    return {
        initialProps,
        // 在服務(wù)端可以對 state 數(shù)據(jù)加密,防止被輕易解析
        initialState: getIsServer() ? getSerializedState<S>(state, config) : state,
    };
};

makeProps 函數(shù)主要初始化 store ,然后把 store 傳遞給 callback 函數(shù)并執(zhí)行獲取到一個函數(shù),這個函數(shù)傳入 context 再次執(zhí)行,就可以獲取到對應(yīng) 數(shù)據(jù)獲取函數(shù) 的返回值,處理后進(jìn)行返回即可。

其中需要注意下面幾點(diǎn):

  • callback 函數(shù)必須返回一個函數(shù),否則其返回的 initialProps 會被是空對象
  • 調(diào)用 createWrapper 時傳遞參數(shù)中的 debug 參數(shù)在這里會起作用
  • store 放入 context 是一個遺留的處理方式,后續(xù)可能會去掉。但并沒說明后續(xù)處理方式。
  • 返回的 initialState 在服務(wù)端可能自定義加密方法。

createWrapper 中 渲染頁面內(nèi)容 時的處理實(shí)現(xiàn)分析

服務(wù)端把數(shù)據(jù)獲取后,下面就要進(jìn)行的步驟是:渲染頁面內(nèi)容。

有幾個概念需要先理清楚,不然會直接看前面幾個函數(shù)的實(shí)現(xiàn)會很懵逼。

  • giapState:對應(yīng) getInitialAppProps 處理后的 state
  • gspState:對應(yīng) getStaticProps 處理后的 state
  • gsspState:對應(yīng) getServerSideProps 處理后的 state
  • gippState:對應(yīng) getInitialPageProps 處理后的 state

useWrappedStore hook

// 用于在應(yīng)用中關(guān)聯(lián) store 的hook。
const useWrappedStore = <P extends AppProps>(incomingProps: P, displayName = 'useWrappedStore'): {store: S; props: P} => {
    // createWrapper 給 incomingProps 添加了 WrapperProps 類型,因?yàn)樗鼈儾皇菑?P 類型獲取,因此在這里進(jìn)行強(qiáng)制賦予類型
    const {initialState: giapState, initialProps, ...props} = incomingProps as P & WrapperProps;
    // getStaticProps state
    const gspState = props?.__N_SSG ? props?.pageProps?.initialState : null;
    // getServerSideProps state
    const gsspState = props?.__N_SSP ? props?.pageProps?.initialState : null;
    // getInitialPageProps state
    const gippState = !gspState && !gsspState ? props?.pageProps?.initialState ?? null : null;
    // debug 打印代碼,刪除掉了
    if (config.debug) {}
    // 獲取store,initStore 會緩存 store ,有則直接緩存,沒有則進(jìn)行初始化。
    const store = useMemo<S>(() => initStore<S>({makeStore}), []);
    // state 初始化
    useHybridHydrate(store, giapState, gspState, gsspState, gippState);
    // 后續(xù)余state 無關(guān),主要是去掉
    let resultProps: any = props;
    // 順序很重要! Next.js 中 page 的 getStaticProps 應(yīng)該覆蓋 pages/_app 中的 props
    // @see https://github.com/zeit/next.js/issues/11648
    if (initialProps && initialProps.pageProps) {
        resultProps.pageProps = {
            ...initialProps.pageProps, // this comes from wrapper in _app mode
            ...props.pageProps, // this comes from gssp/gsp in _app mode
        };
    }
    // 防止props中的 initialState被到處傳遞,為了數(shù)據(jù)安全,清除掉 initialState
    if (props?.pageProps?.initialState) {
        resultProps = {...props, pageProps: {...props.pageProps}};
        delete resultProps.pageProps.initialState;
    }
    // 處理 getInitialPageProps 的數(shù)據(jù), 清除掉 initialProps
    if (resultProps?.pageProps?.initialProps) {
        resultProps.pageProps = {...resultProps.pageProps, ...resultProps.pageProps.initialProps};
        delete resultProps.pageProps.initialProps;
    }
    return {store, props: {...initialProps, ...resultProps}};
};

useWrappedStore hook 主要做了以下幾件事:

  • App props 中獲取數(shù)據(jù),并進(jìn)行分類
  • 初始化 store :服務(wù)端不會再初始化,會從緩存獲取,客戶端則會在這里初始化。
  • 處理數(shù)據(jù)覆蓋排序及清除 wrapper 函數(shù)注入的自定義數(shù)據(jù)字段:initialPropsinitialState

initStore

// 初始化 redux store
const initStore = <S extends Store>({makeStore, context = {}}: InitStoreOptions<S>): S => {
    const createStore = () => makeStore(context);
    if (getIsServer()) {
        // 服務(wù)端則存儲到 req.__nextReduxWrapperStore 參數(shù) 中進(jìn)行服用
        const req: any = (context as NextPageContext)?.req || (context as AppContext)?.ctx?.req;
        if (req) {
            // ATTENTION! THIS IS INTERNAL, DO NOT ACCESS DIRECTLY ANYWHERE ELSE
            // @see https://github.com/kirill-konshin/next-redux-wrapper/pull/196#issuecomment-611673546
            if (!req.__nextReduxWrapperStore) {
                req.__nextReduxWrapperStore = createStore(); // Used in GIP/GSSP
            }
            return req.__nextReduxWrapperStore;
        }
        return createStore();
    }
    // Memoize the store if we're on the client
    // 客戶端則存儲到 sharedClientStore 上
    if (!sharedClientStore) {
        sharedClientStore = createStore();
    }
    return sharedClientStore;
};

initStore 函數(shù)中,服務(wù)端利用每次請求都會新生成的對象 req 來緩存服務(wù)端請求上下文的 store,客戶端利用 sharedClientStore 變量來存儲。

useHybridHydrate hook

// hydrate 初始化前置邏輯處理
const useHybridHydrate = (store: S, giapState: any, gspState: any, gsspState: any, gippState: any) => {
    const {events} = useRouter();
    const shouldHydrate = useRef(true);
    // 客戶端路由改變的時候好應(yīng)該重新初始化。
    useEffect(() => {
        const handleStart = () => {
            shouldHydrate.current = true;
        };
        events?.on('routeChangeStart', handleStart);
        return () => {
            events?.off('routeChangeStart', handleStart);
        };
    }, [events]);
    // 這里寫了一大堆注釋,就是表面 useMemo 里面進(jìn)行 hydrate 并不會導(dǎo)致頁面重新不斷渲染,主要是當(dāng)作 constructor 來使用
    useMemo(() => {
        if (shouldHydrate.current) {
            hydrateOrchestrator(store, giapState, gspState, gsspState, gippState);
            shouldHydrate.current = false;
        }
    }, [store, giapState, gspState, gsspState, gippState]);
};

useHybridHydrate 函數(shù)主要用于處理 初始化 state 的前置邏輯,主要使用 useMemo 來盡早調(diào)用 hydrateOrchestrator 函數(shù)初始化 state , 并使用監(jiān)聽路由的方式來處理客戶端路由切換時需要重新初始化的問題。

hydrateOrchestrator

// hydrate 處理中間數(shù)據(jù)的函數(shù)(用于分析處理各種情況)
const hydrateOrchestrator = (store: S, giapState: any, gspState: any, gsspState: any, gippState: any) => {
    if (gspState) {
        // `getStaticProps` 并不能和其他數(shù)據(jù)獲取函數(shù)同時存在在一個頁面,但可能存在 `getInitialAppProps`,這時候只會在構(gòu)建的時候執(zhí)行,因此需要覆蓋 `giapState`
        hydrate(store, giapState);
        hydrate(store, gspState);
    } else if (gsspState || gippState || giapState) {
        // 處理優(yōu)先級問題,getServerSideProps > getInitialPageProps > getInitialAppProps
        hydrate(store, gsspState ?? gippState ?? giapState);
    }
};

hydrateOrchestrator 函數(shù)主要用于處理獲取state的覆蓋和優(yōu)先級問題:

  • getStaticProps 并不能和其他數(shù)據(jù)獲取函數(shù)同時存在在一個頁面,但可能存在 getInitialAppProps,這時候只會在構(gòu)建的時候執(zhí)行,因此需要覆蓋 giapState 。
  • SSG 情況,優(yōu)先級 getServerSideProps > getInitialPageProps > getInitialAppProps

hydrate

// hydrate 處理函數(shù),觸發(fā)服務(wù)端渲染過程中的數(shù)據(jù) HYDRATE
const hydrate = (store: S, state: any) => {
    if (!state) {
        return;
    }
    store.dispatch({
        type: HYDRATE,
        payload: getDeserializedState<S>(state, config),
    } as any);
};

hydrate 函數(shù)就是用于發(fā)起 HYDRATE action 的。

總結(jié)

本文主要從 目錄結(jié)構(gòu) 分析,然后再到 代碼結(jié)構(gòu)分析,最好再分析重點(diǎn)代碼實(shí)現(xiàn),這樣一步一步的去讀源碼,可以讓思路更加清晰。

讀源碼之前,有使用經(jīng)驗(yàn)也是一個很重要的點(diǎn),這樣才能帶著疑問和思考去讀,讓閱讀源碼更有意思

以上就是next-redux-wrapper使用細(xì)節(jié)及源碼分析的詳細(xì)內(nèi)容,更多關(guān)于next-redux-wrapper使用的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • react中antd文本框限制輸入中文方式

    react中antd文本框限制輸入中文方式

    這篇文章主要介紹了react中antd文本框限制輸入中文方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • React實(shí)現(xiàn)雙滑塊交叉滑動

    React實(shí)現(xiàn)雙滑塊交叉滑動

    這篇文章主要為大家詳細(xì)介紹了React實(shí)現(xiàn)雙滑塊交叉滑動,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • react中JSX的注意點(diǎn)詳解

    react中JSX的注意點(diǎn)詳解

    這篇文章主要為大家詳細(xì)介紹了react中JSX的注意點(diǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 你知道怎么在 HTML 頁面中使用 React嗎

    你知道怎么在 HTML 頁面中使用 React嗎

    這篇文章主要為大家詳細(xì)介紹了如何在HTML頁面中使用 React,使用使用js模塊化的方式開發(fā),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • react實(shí)現(xiàn)列表滾動組件功能

    react實(shí)現(xiàn)列表滾動組件功能

    在開發(fā)項目的時候,從服務(wù)端獲取到數(shù)據(jù)列表后,展示給用戶看,需要實(shí)現(xiàn)數(shù)據(jù)自動滾動效果,怎么實(shí)現(xiàn)呢,下面小編給大家分享react實(shí)現(xiàn)列表滾動組件功能實(shí)現(xiàn)代碼,感興趣的朋友一起看看吧
    2023-09-09
  • React.js組件實(shí)現(xiàn)拖拽排序組件功能過程解析

    React.js組件實(shí)現(xiàn)拖拽排序組件功能過程解析

    這篇文章主要介紹了React.js組件實(shí)現(xiàn)拖拽排序組件功能過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • react自動化構(gòu)建路由的實(shí)現(xiàn)

    react自動化構(gòu)建路由的實(shí)現(xiàn)

    這篇文章主要介紹了react自動化構(gòu)建路由的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 如何強(qiáng)制刷新react hooks組件

    如何強(qiáng)制刷新react hooks組件

    這篇文章主要介紹了如何強(qiáng)制刷新react hooks組件問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • React中用@符號編寫文件路徑實(shí)現(xiàn)方法介紹

    React中用@符號編寫文件路徑實(shí)現(xiàn)方法介紹

    在Vue中,我們導(dǎo)入文件時,文件路徑中可以使用@符號指代src目錄,極大的簡化了我們對路徑的書寫。但是react中,要想實(shí)現(xiàn)這種方式書寫文件路徑,需要寫配置文件來實(shí)現(xiàn)
    2022-09-09
  • 詳解React setState數(shù)據(jù)更新機(jī)制

    詳解React setState數(shù)據(jù)更新機(jī)制

    這篇文章主要介紹了React setState數(shù)據(jù)更新機(jī)制的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用React框架,感興趣的朋友可以了解下
    2021-04-04

最新評論