最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文詳解React Redux設(shè)計(jì)思想與工作原理

 更新時(shí)間:2023年09月24日 17:26:14   作者:左耳咚  
最近看項(xiàng)目中使用了?Redux,?便嘗試了解一波?Redux?的設(shè)計(jì)思想與工作原理,所以本文詳細(xì)的給大家介紹了Redux設(shè)計(jì)思想與工作原理,需要的朋友可以參考下

設(shè)計(jì)思想

在開始了解之前,我們需要先了解 Redux 解決了什么問題?

Redux 解決了什么問題

在沒有 Redux 之前, 如果組件之間存在大量通信,甚至有些通信跨越多個(gè)組件,或者多個(gè)組件之間共享一套數(shù)據(jù),簡單的父子組件間傳值不能滿足我們的需求,自然而然地,我們需要有一個(gè)地方存取和操作這些公共狀態(tài)。而 redux 就為我們提供了一種管理公共狀態(tài)的方案,便于管理比較復(fù)雜的通信場景。

Redux 的設(shè)計(jì)理念

Redux 的設(shè)計(jì)采用了 Facebook 提出的 Flux 數(shù)據(jù)處理理念

在 Flux 中通過建立一個(gè)公共集中數(shù)據(jù)倉庫 Store 進(jìn)行管理,整體分成四個(gè)部分即: View (視圖層)、Action (動(dòng)作)、Dispatcher (派發(fā)器)、Store (數(shù)據(jù)層)

如下圖所示,當(dāng)我們想要修改倉庫的數(shù)據(jù)時(shí),需要從 View 中觸發(fā) Action,由 Dispatcher 派發(fā)到 Store 修改數(shù)據(jù),從而驅(qū)動(dòng)視圖更新

這種設(shè)計(jì)的好處在于其數(shù)據(jù)流向是單一的,數(shù)據(jù)的修改一定是會經(jīng)過 Action、Dispatcher 等動(dòng)作才能實(shí)現(xiàn),方便預(yù)測、維護(hù)狀態(tài)的流向。

當(dāng)我們了解了 Flux 的設(shè)計(jì)理念后,便可以照葫蘆畫瓢了。

如下圖所示,在 Redux 中同樣需要維護(hù)一個(gè)公共數(shù)據(jù)倉庫 Store, 而數(shù)據(jù)流向只能通過 View 觸發(fā) Action、 Reducer更新派發(fā), Store 改變從而驅(qū)動(dòng)視圖更新

工作原理

當(dāng)我們了解了 Redux 的設(shè)計(jì)理念后,趁熱打鐵炫一波 Redux 的工作原理,我們知道使用 Redux 進(jìn)行狀態(tài)管理的第一步就是需要先創(chuàng)建數(shù)據(jù)倉庫 Store, 也就會需要調(diào)用 createStore 方法。那我們就先拿 createStore 開炫。

createStore

從 Redux 源碼中我們不難看出,createStore 接收 reducer、初始化state中間件三個(gè)參數(shù),當(dāng)執(zhí)行 createStore 時(shí)會記錄當(dāng)前的 state 狀態(tài),并返回 store 對象,包含 dispatch、subscribe、getState 等屬性。

其中

  • dispatch: 用來觸發(fā) Action
  • subscribe: 當(dāng) store 值的改變將觸發(fā) subscribe 的回調(diào)
  • getState: 用來獲取當(dāng)前的 state 狀態(tài)。

getState 比較簡單,直接返回當(dāng)前的 state 狀態(tài),接下來我們將著重了解 dispatch 與 subscribe 的實(shí)現(xiàn)。

function createStore(reducer, preloadedState, enhancer) {
   let currentReducer = reducer // 記錄當(dāng)前的 reducer
   let currentState = preloadedState // 記錄當(dāng)前的 state
   let isDispatching = false // 是否正在進(jìn)行 dispatch
   function getState() {
      return currentState // 通過 getState 獲取當(dāng)前的 state
   }
   // 觸發(fā) action
   function dispatch(action: A) {}
   function subscribe(listener: () => void) {}
   // 初始化 state
   dispatch({ type: ActionTypes.INIT } as A)
   // 返回一個(gè) sttore
   const store = {
    dispatch: dispatch as Dispatch<A>,
    subscribe,
    getState
   }
   return store
}

dispatch

在 Redux 中, 修改數(shù)據(jù)的唯一方式就是通過 dispatch,而 dispatch 接受一個(gè) action 對象作為參數(shù),執(zhí)行 dispatch 方法,將生成新的 state,并觸發(fā)監(jiān)聽事件。

function dispatch(action) {
    // 如果已經(jīng)在觸發(fā)中,則不允許再次出發(fā) dispatch (禁止套娃)
    // 例如:在 reducer 中觸發(fā) dispatch
    if (isDispatching) {
      throw new Error('Reducers may not dispatch actions.')
    }
    try {
      // 上鎖
      isDispatching = true
      // 調(diào)用 reducer,獲取新的 state
      currentState = currentReducer(currentState, action)
    } finally {
      isDispatching = false
    }
    // 觸發(fā)訂閱事件
    const listeners = (currentListeners = nextListeners)
    listeners.forEach(listener => {
      listener()
    })
    return action
  }

subscribe

在 Redux 中, 可以通過 subscribe 方法來訂閱 store 的變化, 一旦 store 發(fā)生了變化, 就會執(zhí)行訂閱的回調(diào)函數(shù)

可以看到 subscribe 方法接收一個(gè)回調(diào)函數(shù)作為參數(shù), 執(zhí)行 subscribe 方法將會返回一個(gè) unsubscribe 函數(shù), 用于取消訂閱

function subscribe(listener: () => void) {
    if (isDispatching) {
      throw new Error()
    }
    let isSubscribed = true // 防止調(diào)用多次 unsubscribe
    ensureCanMutateNextListeners() // 確保 nextListeners 是 currentListeners 的快照,而不是同一個(gè)引用
    const listenerId = listenerIdCounter++
    nextListeners.set(listenerId, listener) //nextListeners 添加訂閱事件
    // 取消訂閱事件
    return function unsubscribe() {
      if (!isSubscribed) {
        return
      }
      if (isDispatching) {
        throw new Error()
      }
      isSubscribed = false
      ensureCanMutateNextListeners(); // 如果某個(gè)訂閱事件執(zhí)行了 unsubscribe, nextListeners 創(chuàng)建了新的內(nèi)存地址,而原先的listeners 依然保持不變 (dispatch 方法中的312 行)
      nextListeners.delete(listenerId)
      currentListeners = null
    }
  }

ensureCanMutateNextListeners 與 currentListeners 的作用

承接上文,在 subscribe 中不管是注冊監(jiān)聽還是取消監(jiān)聽都會調(diào)用 ensureCanMutateNextListeners 的方法,那么這個(gè)方法是做什么的呢?

從函數(shù)的邏輯上不難得出答案:

ensureCanMutateNextListeners 確保 nextListeners 是 currentListeners 的快照,而不是同一個(gè)引用

function ensureCanMutateNextListeners() {
    if (nextListeners === currentListeners) { // currentListeners 用來確保循環(huán)的穩(wěn)定性
      nextListeners = new Map()
      currentListeners.forEach((listener, key) => {
        nextListeners.set(key, listener)
      })
    }
}

在 dispatch 或者 subscribe 函數(shù)中,都是通過 nextListeners 觸發(fā)監(jiān)聽,那為何還需要使用 currentListeners?

這里就不賣關(guān)子了,這里的 currentListeners 用于確保在 dispatch 中 listener 的數(shù)量不會發(fā)生變化, 確保當(dāng)前循環(huán)的穩(wěn)定性。

請看下面的例子??

const a = store.subscribe(() => {
  /* a */
});
const b = store.subscribe(() => a());
const c = store.subscribe(() => {
  /*/ c */
});
store.dispatch(action);

上面的代碼在 Redux 中是被允許的, 通過 subscribe 注冊監(jiān)聽函數(shù) a、b、c,此時(shí) nextListeners 指向 [a, b, c]

當(dāng)執(zhí)行 dispatch 時(shí), listener、currentListeners、nextListeners 將指向地址 [a, b, c];

// dispatch 觸發(fā)監(jiān)聽事件的邏輯
// 觸發(fā)訂閱事件 
const listeners = (currentListeners = nextListeners)
listeners.forEach(listener => { listener() })

當(dāng)執(zhí)行到 b 監(jiān)聽函數(shù)時(shí),將解綁 a 函數(shù)的監(jiān)聽事件,如果直接修改 nextListeners, 在循環(huán)中操作數(shù)組是非常危險(xiǎn)的事情, 因此借助 ensureCanMutateNextListeners、currentListeners 為 nextListeners 開辟了新的內(nèi)存地址,對 nextListeners 的操作將不影響 listener。

實(shí)現(xiàn)一個(gè) mini react-redux

上文我們說到,一個(gè)組件如果想從 store 存取公用狀態(tài),需要進(jìn)行四步操作:

  • import引入store
  • getState獲取狀態(tài)
  • dispatch修改狀態(tài)
  • subscribe訂閱更新

代碼相對冗余,我們想要合并一些重復(fù)的操作,而 react-redux 就提供了一種合并操作的方案:react-redux提供 Providerconnect 兩個(gè)API, Provider 將 store 放進(jìn) this.context 里,省去了 import 這一步, connect將 getState、dispatch 合并進(jìn)了this.props,并自動(dòng)訂閱更新,簡化了另外三步,下面我們來看一下如何實(shí)現(xiàn)這兩個(gè)API:

Provider

Provider 組件比較簡單,接收 store 并放進(jìn)全局的 context 對象,使 store 可用于任何需要訪問 Redux store 的嵌套組件

import React, { createContext } from 'react';
let StoreContext;
const Provider = (props) => {
  StoreContext = createContext(props.store);
  return <StoreContext.Provider value={props.store}>{ props.children }</StoreContext.Provider>
}

connect

下面我們來思考一下如何實(shí)現(xiàn) connect ,我們先回顧一下connect的使用方法

connect(mapStateToProps, mapDispatchToProps)(App)

connect 接收 mapStateToProps、mapDispatchToProps 兩個(gè)函數(shù),然后返回一個(gè)高階函數(shù), 最終將 mapStateToProps、mapDispatchToProps 函數(shù)的返回值通過 props 形式傳遞給 App 組件

我們直接放出connect的實(shí)現(xiàn)代碼,并不復(fù)雜:

import React, { createContext, useContext, useEffect } from 'react';
export function connect(mapStateToProps, mapDispatchToProps) {
    return function (Component) {
      const connectComponent: React.FC = (props) => {
        const store = useContext(StoreContext);
        const [, updateState] = useState();
        const forceUpdate = useCallback(() => updateState({}), []);
        const handleStoreChange = () => {
            // 強(qiáng)制刷新
            forceUpdate();
        }
        useEffect(() => {
          store.subscribe(handleStoreChange)
        }, [])
        return (
          <Component
              // 傳入該組件的props,需要由connect這個(gè)高階組件原樣傳回原組件  
              { ...(props) }
              // 根據(jù) mapStateToProps 把 state 掛到 this.props 上 
              { ...(mapStateToProps(store.getState())) }
              // 根據(jù)mapDispatchToProps把dispatch(action)掛到this.props上
              { ...(mapDispatchToProps(store.dispatch)) }
          />
        )
      }
      return connectComponent;
    }
}

可以看出 connect 通過 useContext 實(shí)現(xiàn)和 store 的鏈接,將 state 作為第一個(gè)參數(shù)傳給 mapStateToProps、將 dispatch 作為第一個(gè)參數(shù)傳遞給 mapDispatchToProps,最終將結(jié)果通過 props 形式傳遞給子組件。

其實(shí) connect 這種設(shè)計(jì),是裝飾器模式的實(shí)現(xiàn),所謂裝飾器模式,簡單地說就是對類的一個(gè)包裝,動(dòng)態(tài)地拓展類的功能。這里的 connect 以及 React 中的高階組件(HoC)都是這一模式的實(shí)現(xiàn)。

對類的裝飾常用于拓展類的功能,對類中函數(shù)的裝飾常用于 AOP 切面

@decorator
class A {}
// 等同于
class A {}
A = decorator(A) || A;

裝飾器只能用于類和類的方法,不能用于函數(shù),因?yàn)榇嬖诤瘮?shù)提升。 如果一定要裝飾函數(shù),可以使用高階函數(shù)

mini react-redux

通過上文,我們了解了 Provider 與 connect 的實(shí)現(xiàn),我們可以寫個(gè) mini react-redux 來測試一下

1 創(chuàng)建如下目錄結(jié)構(gòu)

2 實(shí)現(xiàn) createStore 函數(shù) 創(chuàng)建一個(gè) createStore.ts 文件,createStore 最終將返回 store 對象,包含 getState、dispatch、subscribe

export const createStore = (reducer: Function) => {
    let currentState: undefined = undefined;
    const obervers: Array<Function> = [];
    function getState() {
        return currentState;
    }
    function dispatch(action: { type: string}) {
        currentState = reducer(currentState, action);
        obervers.forEach(fn => fn());
    }
    function subscribe(fn: Function) {
        obervers.push(fn);
    }
    dispatch({ type: '@@REDUX/INIT' }); // 初始化 state
    return {
        getState,
        dispatch,
        subscribe
    }
}

3 實(shí)現(xiàn) reducer

createStore 函數(shù)接收一個(gè) reducer 方法,reducer 常用來分發(fā) action, 并返回新的 state

// reducer.ts
const initialState = {
    count: 0
}
export function reducer(state = initialState, action: { type: string}) {
    switch (action.type) {
        case 'add': 
            return {
                ...state,
                count: state.count + 1
            }
        case 'reduce':
            return {
                ...state,
                count: state.count - 1
            }
        default:
            return initialState;
    }
}

4 實(shí)現(xiàn) Provider 與 connect

/* eslint-disable react-hooks/rules-of-hooks */
//@ts-nocheck 
import React, { createContext, useContext, useEffect } from 'react';
let StoreContext;
const Provider = (props) => {
  StoreContext = createContext(props.store);
  return <StoreContext.Provider value={props.store}>{ props.children }</StoreContext.Provider>
}
export default Provider;
export function connect(mapStateToProps, mapDispatchToProps) {
    return function (Component) {
      const connectComponent: React.FC = (props) => {
        const store = useContext(StoreContext);
        const [, updateState] = React.useState();
        const forceUpdate = React.useCallback(() => updateState({}), []);
        const handleStoreChange = () => {
            // 強(qiáng)制刷新
            forceUpdate();
        }
        useEffect(() => {
          store.subscribe(handleStoreChange)
        }, [])
        return (
          <Component
              // 傳入該組件的props,需要由connect這個(gè)高階組件原樣傳回原組件   
              { ...(props) }
              // 根據(jù) mapStateToProps 把 state 掛到 this.props 上       
              { ...(mapStateToProps(store.getState())) }
              // 根據(jù)mapDispatchToProps把dispatch(action)掛到this.props上              
              { ...(mapDispatchToProps(store.dispatch)) }
          />
        )
      }
      return connectComponent;
    }
}

5 修改 main.tsx

// main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
import  Provider from './react-redux/index.tsx';
import { createStore } from './react-redux/createStore.ts';
import { reducer } from './react-redux/reducer.ts';
ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
      <Provider store={createStore(reducer)}>
        <App />
      </Provider>
  </React.StrictMode>,
)

6 修改 App.tsx

// App.tsx
import { useState } from 'react';
import { connect } from './react-redux';
const addAction = {
  type: 'add'
}
const mapStateToProps = (state: { count: number }) => {
  return {
    count: state.count
  }
}
const mapDispatchToProps = (dispatch: any) => {
  return {
    addCount: () => {
      dispatch(addAction)
    }
  }
}
interface Props {
  count: number;
  addCount: () => void;
}
function App(props: Props): JSX.Element {
  const { count, addCount } = props;
  return (
    <div className="App">        
      { count }        
      <button onClick={ () => addCount() }>增加</button>      
    </div>
  );
}
export default connect(mapStateToProps, mapDispatchToProps)(App);

運(yùn)行項(xiàng)目,點(diǎn)擊增加按鈕,如能正確計(jì)數(shù),我們整個(gè)redux、react-redux的流程就走通了。

中間件

在大部分場景下, 我們需要自定義 dispatch 的行為, 在 Redux 中, 我們可以使用 中間件來拓展 dispatch 的功能

類似于 Express 或者 Koa, 在這些框架中,我們可以使用中間件來拓展 請求 和 響應(yīng) 之間的功能

而 Redux 中間件的作用是在 action 發(fā)出之后, 到達(dá) reducer 之前, 執(zhí)行一系列的任務(wù)

在 Redux 中我們可以通過 applyMiddleware 生成一個(gè)強(qiáng)化器 enhancer 作為 createStore 的第二個(gè)參數(shù)傳遞。

import { createStore, applyMiddleware } from 'redux'  
import rootReducer from './reducer'  
import { print1, print2, print3 } from './exampleAddons/middleware'  
const middlewareEnhancer = applyMiddleware(print1, print2, print3)  
// Pass enhancer as the second arg, since there's no preloadedState  
const store = createStore(rootReducer, middlewareEnhancer)  
export default store

正如它們的名稱所示,每個(gè)中間件在調(diào)度操作時(shí)都會打印一個(gè)數(shù)字

import store from './store'  
store.dispatch({ type: 'todos/todoAdded', payload: 'Learn about actions' })  
// log: '1'  
// log: '2'  
// log: '3'

在這個(gè)例子中,當(dāng)觸發(fā) dispatch 的內(nèi)部執(zhí)行順序如下:

  • The print1 middleware (which we see as store.dispatch)
  • The print2 middleware
  • The print3 middleware
  • The original store.dispatch
  • The root reducer inside store

實(shí)現(xiàn)一個(gè)中間件

從上文得知, 我們了解了如何使用中間件, 接下來我們將實(shí)現(xiàn)一個(gè)中間件。

在 Redux 中,中間件其實(shí)是由三個(gè)嵌套函數(shù)組成

function exampleMiddleware(storeAPI) {  
   return function wrapDispatch(next) {  
       return function handleAction(action) {  
         // Do anything here: pass the action onwards with next(action),  
         // or restart the pipeline with storeAPI.dispatch(action)  
         // Can also use storeAPI.getState() here  
         return next(action)  
      }  
   }  
}

最外層函數(shù) exampleMiddleware 將會被 applyMiddleware 調(diào)用,并傳入 storeAPI 對象( 形如 {dispatch, getState} ),

中間層函數(shù) wrapDispatch 接收一個(gè) next 參數(shù),next 實(shí)際上就是中間管道的下一個(gè)中間件函數(shù),如果是最后一個(gè) next,那么他的下一個(gè)中間件函數(shù)就是 dispatch

最內(nèi)層函數(shù) handleAction 接收一個(gè) Action 對象

此時(shí),我們知道了如何編寫一個(gè)中間件,接下來我們將實(shí)現(xiàn)一個(gè) logger 中間件

const loggerMiddleware = storeAPI => next => action => {  
    console.log('dispatching', action)  
    let result = next(action)  
    console.log('next state', storeAPI.getState())  
    return result  
}

寫完 logger 中間件后,我們嘗試在 Redux 中使用,如下

import { createStore, applyMiddleware } from "redux";
const initialState = {
  count: 0
}
function reducer(state = initialState, action: { type: string}) {
  switch (action.type) {
      case 'add': 
          return {
              ...state,
              count: state.count + 1
          }
      case 'reduce':
          return {
              ...state,
              count: state.count - 1
          }
      default:
          return initialState;
  }
}
const logger1 = storeAPI => next => action => {  
  console.log('logger1 開始');
  const result = next(action)  
  console.log('logger1 結(jié)束');
  return result  
}
const logger2 = storeAPI => next => action => {  
  console.log('logger2 開始');
  const result = next(action)  
  console.log('logger2 結(jié)束');
  return result  
}
const logger3 = storeAPI => next => action => {  
  console.log('logger3 開始');
  const result = next(action)  
  console.log('logger3 結(jié)束');
  return result  
}
const middlewares = applyMiddleware(logger1, logger2, logger3);
const store = createStore(reducer, middlewares);
store.dispatch({ type: 'add' });

最終將打印

從打印的記過來看,如果之前有接觸過 Express 或者 Koa 的同學(xué),應(yīng)該可以很快發(fā)現(xiàn),這個(gè)是一個(gè)洋蔥模型

applyMiddleware 的實(shí)現(xiàn)原理

從上可知,Redux 提供了一個(gè) applyMiddleware 方法用于將中間件拓展到 dispatch 上

具體是如何拓展的呢?

從源碼我們不難看出,最終是通過 compose 也就是利用 reduce 方法,將下一個(gè)的中間件函數(shù)作為參數(shù),在上一個(gè)中間件的函數(shù)體內(nèi)執(zhí)行。

注意這里傳入 compose 內(nèi)的每一個(gè)函數(shù)都是一個(gè)雙層嵌套函數(shù)。

// applyMiddleware 源碼
export default function applyMiddleware(
  ...middlewares
) {
  // 返回一個(gè)接收 createStore為入?yún)⒌暮瘮?shù)
  return createStore => (reducer, preloadedState) => {
    // 創(chuàng)建 store
    const store = createStore(reducer, preloadedState)
    let dispatch: Dispatch = () => {
      throw new Error(
        'Dispatching while constructing your middleware is not allowed. ' +
          'Other middleware would not be applied to this dispatch.'
      )
    }
    /**
     * middleware 形如:
     * ({dispatch, getState}) => next => action => { ... return next(action) }
     */
    const middlewareAPI: MiddlewareAPI = {
      getState: store.getState,
      dispatch: (action, ...args) => dispatch(action, ...args)
    }
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)
    return {
      ...store,
      dispatch
    }
  }
}
function compose(...funcs) {
  if (funcs.length === 0) {
    // infer the argument type so it is usable in inference down the line
    return (arg:) => arg
  }
  if (funcs.length === 1) {
    return funcs[0]
  }
  return funcs.reduce(
    (a, b) =>
      (...args) =>
        a(b(...args))
  )
}

模擬洋蔥模型

承接上文,我們大概了解了什么是洋蔥模型,接下來我們將模擬一波洋蔥模型的實(shí)現(xiàn)。

const func1 = (fn) => () => {
    console.log('進(jìn)入func1', fn);
    const res = fn();
    console.log('離開func1');
    return res;
}
const func2 = (fn) => () => {
    console.log('進(jìn)入func2', fn);
    const res = fn();
    console.log('離開func2');
    return res;
}
const func3 = (fn) => () => {
    console.log('進(jìn)入func3', fn);
    const res = fn();
    console.log('離開func3');
    return res;
}
const composeB = (...fns) => {
    if (fns.length === 0) return arg => arg    
    if (fns.length === 1) return fns[0]  
    return fns.reduce((res, cur) => {
        return (...args) => res(cur(...args))
    });
}
// (...args) => func1((...args) => func2((...args) => func3(...args))) // 從左到右入棧
const dispatch = () => void 0;
const c = composeB(func1, func2, func3)(dispatch);
c();

總結(jié)

書寫至此,突然有一絲煽情,之前在下對于 redux 充滿了未知與恐懼,剛開始特別害怕學(xué)不懂,便遲遲不敢嘗試,不斷地?cái)[爛,破罐子破摔??僧?dāng)靜下心來,接納自己的愚蠢,慢慢地一遍又一遍地讀每一行代碼與一些很 nice 的文章時(shí),似乎恐懼是自己事前設(shè)定好的。而生活里也并不是只有成功 or 失敗,失敗也不應(yīng)該判定一個(gè)人的價(jià)值,所以不需要懼怕失敗。

以上就是一文詳解Redux設(shè)計(jì)思想與工作原理的詳細(xì)內(nèi)容,更多關(guān)于Redux設(shè)計(jì)思想與工作原理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React組件的創(chuàng)建與state同步異步詳解

    React組件的創(chuàng)建與state同步異步詳解

    這篇文章主要介紹了react組件實(shí)例屬性state,有狀態(tài)state的組件稱作復(fù)雜組件,沒有狀態(tài)的組件稱為簡單組件,狀態(tài)里存儲數(shù)據(jù),數(shù)據(jù)的改變驅(qū)動(dòng)頁面的展示,本文結(jié)合實(shí)例代碼給大家詳細(xì)講解,需要的朋友可以參考下
    2023-03-03
  • React生命周期的使用與實(shí)例解讀

    React生命周期的使用與實(shí)例解讀

    這篇文章詳細(xì)介紹了React組件的生命周期,包括掛載、更新、卸載和錯(cuò)誤處理階段,通過代碼示例和詳細(xì)講解,幫助讀者理解每個(gè)生命周期方法的作用和使用場景
    2026-01-01
  • 快速創(chuàng)建React項(xiàng)目并配置webpack

    快速創(chuàng)建React項(xiàng)目并配置webpack

    這篇文章主要介紹了創(chuàng)建React項(xiàng)目并配置webpack,在這里需要注意,Create?React?App?requires?Node?14?or?higher.需要安裝高版本的node,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2022-01-01
  • React Native:react-native-code-push報(bào)錯(cuò)的解決

    React Native:react-native-code-push報(bào)錯(cuò)的解決

    這篇文章主要介紹了React Native:react-native-code-push報(bào)錯(cuò)的解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 基于visual studio code + react 開發(fā)環(huán)境搭建過程

    基于visual studio code + react 開發(fā)環(huán)境搭建過程

    今天通過本文給大家分享基于visual studio code + react 開發(fā)環(huán)境搭建過程,本文給大家介紹的非常詳細(xì),包括react安裝問題及安裝 Debugger for Chrome的方法,需要的朋友跟隨小編一起看看吧
    2021-07-07
  • 一步步設(shè)置你的第一個(gè)Next.js項(xiàng)目(非常詳細(xì)!)

    一步步設(shè)置你的第一個(gè)Next.js項(xiàng)目(非常詳細(xì)!)

    Next.js是一個(gè)基于React的全??蚣?旨在幫助開發(fā)者構(gòu)建高性能、可擴(kuò)展的Web應(yīng)用,這篇文章主要介紹了如何設(shè)置你的第一個(gè)Next.js項(xiàng)目的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-09-09
  • 解決react中l(wèi)abel標(biāo)簽for報(bào)錯(cuò)問題

    解決react中l(wèi)abel標(biāo)簽for報(bào)錯(cuò)問題

    這篇文章主要介紹了react中l(wèi)abel標(biāo)簽for報(bào)錯(cuò)問題,解決辦法就是react中l(wèi)abel標(biāo)簽沒有for屬性,用htmlFor代替for屬性,感興趣的朋友跟隨小編一起看看吧
    2022-02-02
  • react?cropper圖片裁切實(shí)例詳解

    react?cropper圖片裁切實(shí)例詳解

    這篇文章主要為大家介紹了react?cropper圖片裁切實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • React中classnames庫使用示例

    React中classnames庫使用示例

    這篇文章主要為大家介紹了React中classnames庫使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • react-native 封裝選擇彈出框示例(試用ios&android)

    react-native 封裝選擇彈出框示例(試用ios&android)

    本篇文章主要介紹了react-native 封裝選擇彈出框示例(試用ios&android),具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-07-07

最新評論

邛崃市| 溧水县| 乌鲁木齐县| 阿鲁科尔沁旗| 哈密市| 长治县| 余干县| 翁牛特旗| 石台县| 天水市| 绥阳县| 石景山区| 中江县| 皮山县| 东港市| 北海市| 息烽县| 若羌县| 罗平县| 大洼县| 同德县| 英吉沙县| 古浪县| 涡阳县| 永定县| 法库县| 拜泉县| 阜平县| 房山区| 尼勒克县| 体育| 福泉市| 边坝县| 莱州市| 平乡县| 天全县| 土默特左旗| 突泉县| 咸宁市| 中西区| 德州市|