国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

我們一起聊聊70 行代碼實現(xiàn) Zustand 核心功能

開發(fā) 前端
React 和 Vue 除了自帶的狀態(tài)管理 API,同時還有一些功能強大的狀態(tài)管理庫可供選擇。Vue 常見的狀態(tài)管理庫有 Vuex 和 Pinia,React 狀態(tài)管理相對更多,有 redux、mobox、zustand、jotai 等等。

前端目前主流的開發(fā)技術(shù)棧如 React、Vue 等都是狀態(tài)數(shù)據(jù)驅(qū)動 UI 更新(即 UI = f(state)),所以狀態(tài)管理是項目開發(fā)的重要一環(huán)。

React 和 Vue 除了自帶的狀態(tài)管理 API,同時還有一些功能強大的狀態(tài)管理庫可供選擇。Vue 常見的狀態(tài)管理庫有 Vuex 和 Pinia,React 狀態(tài)管理相對更多,有 redux、mobox、zustand、jotai 等等。

在 React 中,redux 還是最熱門的狀態(tài)管理庫,相信你肯定在 React 開發(fā)中有使用過它。其他的狀態(tài)庫,都有各自的設計理念,在某些場景和開發(fā)規(guī)范,它們可能更適合你的項目。

本文將介紹 zustand 的核心實現(xiàn),zustand 庫和 redux 類似,都參考了 flux 設計理念,它一些特點如下:

  • 易于上手,學習成本低
  • 輕量級設計,gzip 壓縮后僅 1KB
  • TypeScript 友好,有助于提升代碼質(zhì)量和開發(fā)體驗
  • 強大的可擴展性,通過中間件可以實現(xiàn)日志,數(shù)據(jù)持久化等能力
  • zustand 在設計上注重性能,采用高效的更新機制減少不必要的渲染,同時支持狀態(tài)分片。

基于上述特點,zustand 還是比較受歡迎的,你可以看到 zustand 的使用量是排在前頭的。

圖片圖片

Zustand 的使用

zustand 的使用起來很簡單, 使用 create 創(chuàng)建一個 useStore,可以把狀態(tài)值和更新狀態(tài)函數(shù)都保存在 state 中,隨后在組件中調(diào)用即可。

import { create } from 'zustand'

const useStore = create((set) => ({
  count: 1,
  // 通過 set 方法更新狀態(tài)值,set 支持傳入函數(shù)和狀態(tài)對象值
  inc: () => set((state) => ({ count: state.count + 1 })),
}))

function Counter() {
  const count = useStore((state) => state.count)
  const inc = useStore((state) => state.inc)
  return (
    <div>
      <p>{`Count: ${count}`}</p>
      <button onClick={inc}>+1</button>
    </div>
  )
}

代碼體驗地址:https://code.juejin.cn/pen/7396472908036210698

同時 zustand 核心代碼也可以在普通 JS 中調(diào)用,把上述功能用普通 JS 實現(xiàn)就如下:

<div>
  <p>Count: <span id="value"></span></p>
  <button id="btn">+1</button>
</div>
import { createStore } from 'zustand@4.5.4/vanilla'

const store = createStore((set) => ({
  count: 1,
  inc: () => set((state) => ({ count: state.count + 1 })),
}))

const { getState, setState, subscribe, getInitialState } = store

window.onload = () => {
  const value = document.querySelector('#value')
  value.innerHTML = getInitialState().count // 設置 store 中 count 值
  // 使用 subscribe 訂閱狀態(tài)變化,并更新數(shù)值
  subscribe((state) => {
    value.innerHTML = state.count
  })

  const btn = document.querySelector('#btn')
  btn.onclick = () => {
    // 觸發(fā)更新
    getState().inc()
  }
}

代碼體驗地址:https://code.juejin.cn/pen/7396483548833644581

Zustand 的實現(xiàn)

Vanilla 版本

zustand 的核心實現(xiàn)非常簡潔,我們先實現(xiàn)一個普通版本的 zustand,因為 react hook 版本也需要使用到它。從上面zustand 使用案例代碼可以看出,state 狀態(tài)值不能直接修改,要通過 setState 來觸發(fā)修改,這個和 redux 一致,對于通知狀態(tài)變化則使用了發(fā)布訂閱模式。

核心實現(xiàn)大概如下:

圖片圖片

const create = (createState) => {
  let state
  let initialState
  const listeners = new Set()

  const setState = (partial, replace) => {
    // 判斷是否為函數(shù),為函數(shù)就調(diào)用,并傳入當前狀態(tài)值
    const nextState = typeof partial === 'function'
      ? partial(state)
      : state
    
    // 對比狀態(tài)值是否有變化
    if (!Object.is(nextState, state)) {
      const previousState = state
      // 如果是替換整個狀態(tài)值,或者狀態(tài)值為基礎值或 null,則直接賦值,不然使用 Object.aasign 合并狀態(tài)值
      state = replace ?? (typeof nextState !== 'object' || nextState === null)
        ? nextState
        : Object.assign({}, state, nextState)
      
      // 觸發(fā)訂閱函數(shù)
      listeners.forEach((listener) => listener(state, previousState))
    }
  }

  const getState = () => state
  
  const getInitialState = () => initialState

  const subscribe = (listener) => {
    listeners.add(listener)
    // 返回一個取消訂閱的方法
    return () => {
      listeners.delete(listener)
    }
  }

  // 清空訂閱
  const destory = () => listeners.clear()

  const api = {
    setState,
    getState,
    getInitialState,
    subscribe,
    destory
  }

  // 調(diào)用 createState,createState 參數(shù)為 set、get 和 api 對象,函數(shù)返回狀態(tài)初始值
  initialState = (state = createState(setState, getState, api))

  return api
}

export default create

代碼體驗地址:https://code.juejin.cn/pen/7396500100421255204

React Hook

接著基于普通版本實現(xiàn) React Hook 版本。在實現(xiàn)前,我們先了解一個 React 自帶的 Hook - useSyncExternalStore[1]。

useSyncExternalStore 的作用是讓你可以訂閱外部的狀態(tài)源,當外部狀態(tài)源發(fā)生變化時,React 會觸發(fā)重選渲染。

const snapshot = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?)

useSyncExternalStore 調(diào)用第一個參數(shù) subscribe 訂閱數(shù)據(jù)源變化,當數(shù)據(jù)源變化了,就觸發(fā)重新渲染,并調(diào)用 getSnapshot 返回最新的狀態(tài)值。

有了這個 Hook 的支持,我們就可以輕松實現(xiàn) React Hook 版本 zustand。

import createImpl from './vanilla'
import useSyncExternalStoreExports from 'use-sync-external-store/shim/with-selector'

const { useSyncExternalStoreWithSelector } = useSyncExternalStoreExports

const create = (createState) => {
  // 使用普通版本 zustand 創(chuàng)建一個支持發(fā)布訂閱的數(shù)據(jù)源
  const api = createImpl(createState)

  // zustand 版本 Hook,參數(shù)為狀態(tài)值選擇器和判斷狀態(tài)是否變化函數(shù)
  const useBearStore = (selector, equiltyFn?) => 
    // 和 useSyncExternalStore 類似,不過支持傳入 selector,獲取部分數(shù)據(jù)
    useSyncExternalStoreWithSelector(
      api.subcribe,
      api.getState,
      api.getInitialState,
      selector,
      equiltyFn,
    )

  // 把 api 合并到 Hook 對象上
  Object.assign(useBearStore, api)

  return useBearStore
}

export default create

至此我們已經(jīng)完成了 zustand 核心功能的代碼編寫。

代碼體驗:https://code.juejin.cn/pen/7396503370447781951

拓展

useSyncExternalStoreWithSelector

React Hook 版本的 zustand 中使用到了 useSyncExternalStoreWithSelector[2],這個 Hook 是基于 useSyncExternalStore 實現(xiàn)的,可以簡單了解下它的實現(xiàn),簡化版源碼如下(去除了服務端渲染等內(nèi)容):

// 相比于 useSyncExternalStore ,多了 selector 和 isEqual 參數(shù)
function useSyncExternalStoreWithSelector(
  subscribe,
  getSnapshot,
  getServerSnapshot,
  selector,
  isEqual?,
) {
  const [getSelection, getServerSelection] = useMemo(() => {
    let memoizedSnapshot; // 緩存的整個狀態(tài)值
    let memoizedSelection: Selection; // 緩存的使用 selector 選中的部分狀態(tài)值
  
    const memoizedSelector = (nextSnapshot: Snapshot) => {
      const prevSnapshot = memoizedSnapshot
      const prevSelection = memoizedSelection

      // 如果整體狀態(tài)值相等,直接返回緩存的 selector 選中的狀態(tài)值。
      if (is(prevSnapshot, nextSnapshot)) {
        return prevSelection;
      }

      // 使用 selector 函數(shù)獲取最新的狀態(tài)值
      const nextSelection = selector(nextSnapshot);

      // 有傳入判斷狀態(tài)是否相等函數(shù),相等的話就返回上次的 selector 選中值。
      if (isEqual !== undefined && isEqual(prevSelection, nextSelection)) {
        // 記錄最新的整體狀態(tài)值
        memoizedSnapshot = nextSnapshot;
        return prevSelection;
      }

      // 記錄最新一次的更新值
      memoizedSnapshot = nextSnapshot;
      memoizedSelection = nextSelection;
      // 返回 selector 函數(shù)獲取最新的狀態(tài)值
      return nextSelection;
    };
      
    const getSnapshotWithSelector = () => memoizedSelector(getSnapshot());
    return [getSnapshotWithSelector, () => {}];
  }, [getSnapshot, getServerSnapshot, selector, isEqual]);
  
  // 調(diào)用 useSyncExternalStore 方法,第二參數(shù)不是整體獲取整個狀態(tài)值,而是 selector 的狀態(tài)值
  const value = useSyncExternalStore(
    subscribe,
    getSelection,
    getServerSelection,
  );
  return value
}

總結(jié)

可以看到 zustand 核心代碼還是很簡潔的。通過實現(xiàn)核心代碼,我們可以更好地理解和使用 zustand。有興趣的同學可以繼續(xù)了解下 zustand 插件相關的內(nèi)容。

參考資料

[1]useSyncExternalStore: https://react.dev/reference/react/useSyncExternalStore

[2]useSyncExternalStoreWithSelector: https://github.com/facebook/react/blob/d17e9d1ce566276fc54a8ea27f4e9ea1fa434e62/packages/use-sync-external-store/src/useSyncExternalStoreWithSelector.js

責任編輯:武曉燕 來源: 栗子前端
相關推薦

2022-10-28 07:27:17

Netty異步Future

2021-08-27 07:06:10

IOJava抽象

2024-02-20 21:34:16

循環(huán)GolangGo

2024-11-27 16:07:45

2023-07-18 07:56:20

2023-08-10 08:28:46

網(wǎng)絡編程通信

2023-08-04 08:20:56

DockerfileDocker工具

2022-05-24 08:21:16

數(shù)據(jù)安全API

2023-06-30 08:18:51

敏捷開發(fā)模式

2023-09-10 21:42:31

2023-03-29 08:26:06

2023-06-07 14:07:00

架構(gòu)

2024-02-26 00:00:00

Go性能工具

2022-06-26 09:40:55

Django框架服務

2022-11-12 12:33:38

CSS預處理器Sass

2023-04-26 07:30:00

promptUI非結(jié)構(gòu)化

2022-12-07 13:12:15

2023-07-27 07:46:51

SAFe團隊測試

2022-07-29 08:17:46

Java對象內(nèi)存

2023-12-28 09:55:08

隊列數(shù)據(jù)結(jié)構(gòu)存儲
點贊
收藏

51CTO技術(shù)棧公眾號

国产青春久久久国产毛片| 美女做暖暖视频免费在线观看全部网址91 | 成人不卡视频| 久久久久99精品久久久久| 国产精品3区| 97人洗澡人人免费公开视频碰碰碰| 一区二区三区四区在线看| 欧美精品日韩www.p站| 国产精品亚洲人成在99www| 成人黄色生活片| 日韩av二区在线播放| 奇米影视亚洲色图| 一区二区三区在线观看国产| 久久国产精品高清一区二区三区| 91麻豆精品国产91久久久久久| 日韩少妇视频| 久久久久久久电影一区| 五月天久久网站| 亚洲一二区在线| 国产精品婷婷午夜在线观看| 污视频网站在线观看| 亚洲成av人乱码色午夜| 色悠久久久久综合先锋影音下载| 亚洲影院在线看| 国产成人综合亚洲网站| hbad中文字幕| 欧美α欧美αv大片| 在线精品视频一区| 成人免费观看网站| 国产成人av电影在线| 91破解版在线看| 日韩av影片在线观看| 色橹橹欧美在线观看视频高清| 懂色av一区二区三区在线播放| 日韩写真在线| 日韩一级欧美一级| 久久男人av| 四虎影院一区二区三区 | 日本成人一区二区| www日韩av| 国产亚洲一区字幕| 久草中文在线| 91精品国产91久久久久久久久| 精品91在线| 欧美大尺度做爰床戏| 欧美一二三在线| 怕怕欧美视频免费大全| 中国成人亚色综合网站| 午夜精品成人在线视频| 日本欧美韩国| 久久精品日产第一区二区三区精品版| 久久久午夜电影| 日本动漫同人动漫在线观看| 国产www精品| 成人av午夜影院| 成人动漫在线免费观看| 久久久久久中文| 国产精品亚洲一区二区三区在线| 日夜干在线视频| 欧美亚洲在线播放| 99综合电影在线视频| 黄色成年人视频在线观看| 国产99久久精品一区二区| 成人91在线观看| 国产在线美女| caoporn国产精品免费公开| 国产精品私人影院| 欧美激情三区| 黄色一级视频播放| 欧美一区二区三区在线| 亚洲色图国产| 久草在线官网| 秋霞成人午夜鲁丝一区二区三区| www.在线欧美| 午夜欧美巨大性欧美巨大| 日本精品一区二区三区不卡无字幕| 亚洲va天堂va国产va久| 欧美顶级毛片在线播放| 欧美黄色免费影院| 亚洲人av在线影院| 久久av一区| 日韩精品成人av| 9a蜜桃久久久久久免费| 亚洲国产视频直播| 伊人成综合网yiren22| 国产九九在线视频| 久久艳片www.17c.com | 国产精品v欧美精品v日本精品动漫| 亚色视频在线观看| 久久免费视频这里只有精品| 2014亚洲片线观看视频免费| 成人交换视频| 免费一级特黄毛片| 中文字幕亚洲一区| www.日韩av| 日韩av懂色| 热久久精品国产| 久久久久久久香蕉网| 中文字幕免费一区| 性欧美lx╳lx╳| 女人被爽到呻吟gif动态图下载| 欧美在线一区二区三区四| 国产精品欧美久久久久一区二区| 国产亚洲字幕| 亚洲黄色小视频在线观看| 久久久久久久久久久免费精品| 国产欧美一区二区精品秋霞影院| 国产95亚洲| 99aiav| 国产成人在线亚洲欧美| 亚洲一区二区三区爽爽爽爽爽| 国模精品一区| 精品久久久久一区二区三区 | 亚洲日本国产| 欧美另类tv| 成人午夜视频在线观看免费| 欧美人成在线视频| 亚洲桃色在线一区| 日韩欧美大片| 黄色网址免费在线观看| 欧美h视频在线观看| 最近的2019中文字幕免费一页| 99久久免费精品高清特色大片| 国产情侣一区在线| 初尝黑人巨炮波多野结衣电影| 91免费在线视频网站| 欧美精品一二三四| 九九**精品视频免费播放| 日产精品一区| 国产成人午夜电影| 精品国产_亚洲人成在线| 亚洲欧美精品伊人久久| 久久综合色天天久久综合图片| 青青久久av| √新版天堂资源在线资源| 亚洲最大免费| 97人人做人人爱| 欧美日韩国产综合一区二区三区| 精品一区二区三区不卡| 欧美一区二区三区婷婷| 黄色春季福利在线看| 免费在线成人av电影| 日韩视频欧美视频| 91美女片黄在线观看游戏| 日韩欧美ww| 老司机成人在线| 男女视频在线观看| 成人黄网大全在线观看| 在线观看的毛片| 999香蕉视频| 国产精品一区二区免费福利视频| 精久久久久久| 婷婷久久综合九色国产成人| 欧美成人午夜视频| 丁香婷婷久久久综合精品国产| 国产又大又黄又猛| 国产福利免费在线观看| 春暖花开成人亚洲区| 僵尸世界大战2 在线播放| 全部孕妇毛片丰满孕妇孕| 天天操天天爱天天爽| xxxxx日韩| 日本免费在线观看| 亚洲人性生活视频| 免费看国产一级片| 国产日本韩国在线播放| 97在线视频国产| 国产精品久久久久久亚洲调教| 欧美第一黄网| 一本色道久久亚洲综合精品蜜桃 | 亚洲热线99精品视频| 成人免费福利视频| 精品视频一区二区| wwwwww欧美| 久草在线新视觉| av毛片在线| 欧美男男gaytwinkfreevideos| 香蕉视频官网在线观看日本一区二区| 草草草在线视频| 欧美激情成人动漫| 欧美永久精品| av电影在线观看一区| 97精品国产97久久久久久久久久久久 | 99re在线视频免费观看| 成年人看的毛片| 天堂аⅴ在线最新版在线| 毛片免费看不卡网站| 亚洲国产一区二区三区在线播放| 精品国产户外野外| 久久国产精品久久久久久| 久久精品日产第一区二区三区乱码 | 日本电影一区二区三区| 黄页网站在线观看| 国户精品久久久久久久久久久不卡| 日本欧美韩国一区三区| 日韩av在线天堂网| 青青青在线视频播放| av女优在线| 国产95亚洲| 日本sm残虐另类|