<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Vue3狀態(tài)管理【實(shí)踐總結(jié)】

          共 7261字,需瀏覽 15分鐘

           ·

          2021-03-22 12:49

          原文地址:juejin.cn/post/6941918738320982023


          關(guān)注公眾號(hào) 前端人,回復(fù)“加群

          添加無(wú)廣告優(yōu)質(zhì)學(xué)習(xí)群

          狀態(tài)管理

          簡(jiǎn)述

          • 多個(gè)組件,多個(gè)模塊之間共享狀態(tài)是最常見(jiàn)的開(kāi)發(fā)述求,場(chǎng)景之多不勝枚舉,例如全局用戶狀態(tài),修改用戶信息全局響應(yīng)變化等等。

          常見(jiàn)的解決方案

          • 簡(jiǎn)單方案基于事件監(jiān)聽(tīng)機(jī)制利用回調(diào)傳參,多處訂閱實(shí)現(xiàn)數(shù)據(jù)的流轉(zhuǎn)。例如官方推薦的mitt事件庫(kù)。優(yōu)勢(shì)簡(jiǎn)單的數(shù)據(jù)事件通信是能滿足的,劣勢(shì)隨著數(shù)據(jù)復(fù)雜性變動(dòng),回調(diào)寫法的代碼閱讀性,整體使用體驗(yàn)下降,使用方式也非常簡(jiǎn)單,具體實(shí)現(xiàn)如下:
          //定義組合api事件流
          const $emitter = mitt()
          /**
           * @name: useOnChange
           * @msg: 監(jiān)聽(tīng)事件emit
           */

          export function useOnChange<T extends Function>(fun: T{
            $emitter.on(EventsEnum.CHANGE, itemMessage => {
              fun(itemMessage)
            })
          }
          /**
           * @name: useChange
           * @msg: 觸發(fā)事件emit
           * @param {*}
           */

          export function useChange(itemMessage: number{
            $emitter.emit(EventsEnum.CHANGE, itemMessage)

          // A組件中觸發(fā)事件發(fā)送數(shù)據(jù)
          export default defineComponent({
            name'A',
            setup() {
             //組件A中發(fā)送數(shù)據(jù)
             const handlerClick = (item)=>{
               //使用組合api發(fā)送數(shù)據(jù)
               useChange(1)
             }
            }
           })

          // B組件中監(jiān)聽(tīng)事件獲取數(shù)據(jù)
          export default defineComponent({
            name'B',
            setup() {
              //回調(diào)中獲取數(shù)據(jù)
             useOnChange((mes)=>{
              console.log(mes)
             })
            }
           })
           
          // C 組件中監(jiān)聽(tīng)事件獲取數(shù)據(jù)
          export default defineComponent({
            name'C',
            setup() {
             //回調(diào)中獲取數(shù)據(jù)
             useOnChange((mes)=>{
               console.log(mes)
             })
            }
           }) 
          • 基于vue3的響應(yīng)式官方一些簡(jiǎn)單的實(shí)踐
          const store = {
            debugtrue,

            state: Vue.reactive({
              message'Hello!'
            }),

            setMessageAction(newValue) {
              if (this.debug) {
                console.log('setMessageAction triggered with', newValue)
              }

              this.state.message = newValue
            },

            clearMessageAction() {
              if (this.debug) {
                console.log('clearMessageAction triggered')
              }

              this.state.message = ''
            }

          const appA = Vue.createApp({
            data() {
              return {
                privateState: {},
                sharedState: store.state
              }
            },
            mounted() {
              store.setMessageAction('Goodbye!')
            }
          }).mount('#app-a')

          const appB = Vue.createApp({
            data() {
              return {
                privateState: {},
                sharedState: store.state
              }
            }
          }).mount('#app-b'
          • 知名狀態(tài)管理庫(kù)Redux,Flux,Vuex,這些都是非常優(yōu)秀的第三方庫(kù)

          為什么明明有vuex你還在折騰啥?

          • 先拋出一個(gè)問(wèn)題大家用了element那么久,請(qǐng)問(wèn)知道this.$message是怎么實(shí)現(xiàn)的嗎?如果什么都不管,項(xiàng)目來(lái)了上去就是一套全家桶,做一個(gè)項(xiàng)目和做十個(gè)項(xiàng)目有什么區(qū)別?既然新的機(jī)會(huì)來(lái)了為什么自己寫一下vue3的組件,vue3的狀態(tài)管理?
          • 業(yè)務(wù)與場(chǎng)景在項(xiàng)目初期比較簡(jiǎn)單,沒(méi)有記錄變更、保存狀態(tài)快照、歷史回滾/時(shí)光旅行的訴求,那為什么不自己做一個(gè)狀態(tài)管理呢?
          • 核心實(shí)現(xiàn)功能:狀態(tài)修改單項(xiàng)數(shù)據(jù)流,狀態(tài)改變?nèi)謹(jǐn)?shù)據(jù)響應(yīng),代碼約定,思考一下怎么解決這三個(gè)問(wèn)題?

          實(shí)現(xiàn)思路

          • 單項(xiàng)數(shù)據(jù)流,Readonly
          • 狀態(tài)改變數(shù)據(jù)響應(yīng),組合api和響應(yīng)式
          • 代碼約束 使用ts 進(jìn)行接口約定

          其他大神的一些實(shí)現(xiàn)

          • 利用provide
          • 還有一些基于reactive等等一些想法

          站在巨人的肩膀上

          • 基于一些大神是vue3封裝reduer思路自己也去做了實(shí)現(xiàn)
          1. 基礎(chǔ)實(shí)現(xiàn)
          import { readonly, ref } from 'vue'
          // 全局緩存
          const map = new WeakMap()
          export function useModel(hook: Function{
            if (!map.get(hook)) {
              const ans = hook()
              map.set(hook, ans)
            }
            return map.get(hook)
          }
          export function useReducer(reducer: Function, initialState = {}{
            const state = ref(initialState)
            const dispatch = <T>(action: T) => {
              state.value = reducer(action, state.value)
            }
            return {
              state: readonly(state),
              dispatch,
            }
          }
          export function useStore(reducer: Function, initialState?: any) {
            return useReducer(reducer, initialState)

          2.實(shí)現(xiàn)小型reduer

          import { Ref } from 'vue'
          import { useModel, useReducer } from './reducer'
          // 狀態(tài)接口
          export interface State {
             oo: string,
             xx: string,
             cc: string,
          }
          // 行為接口
          export interface Action {
            type'changeOO' | 'changeXX' | 'changeCC'//指定action
            payload: State
          }
          // 組合函數(shù)使用是 狀態(tài)接口
          export type StateType = Readonly<Ref<State>>
          // 使用實(shí)例接口
          interface Redux {
            state: StateType
            // 這里不是注釋,只是這樣的語(yǔ)法mark當(dāng)不識(shí)別,保證優(yōu)雅性,實(shí)際使用時(shí)放開(kāi)注釋
            //dispatch: <T extends Action>(action: T) => void
          }
          // 狀態(tài)變更
          function reducer(action: Action, state: State{
            switch (action.type) {
              case 'changeOO':
               state.oo = action.payload.oo
               break
              case 'changeXX':
               state.xx = action.payload.xx
               break
              case 'changeCC':
              state.cc = action.payload.cc
               break
            }
            return { ...state }
          }
          // 初始化狀態(tài)
          function useStore({
            const initialState = {
              oo'oo',
              xx'xx',
              cc'cc',
            }
            return useReducer(reducer, initialState)
          }
          // 組合api 函數(shù)可以被任意組件 在任意地方調(diào)用
          export function useXXXRedux({
            const redux: Redux = useModel(useStore)
            return redux

          3.調(diào)用實(shí)現(xiàn),在任意組件內(nèi),或者任何組合api內(nèi)部,在哪里調(diào)用都行

           export default defineComponent({
            name'D',
            setup() {
             //回調(diào)中獲取數(shù)據(jù)
              const { state:xxState,dispatch } = useXXXRedux()
             //監(jiān)聽(tīng)state變化
              watch(xxState, state => {
              })
             //觸發(fā)狀態(tài)改變
             dispatch({type:"changeOO",{payload:{oo:"iii"}}})
           }) 

          總結(jié)

          • 缺點(diǎn): 記錄變更、保存狀態(tài)快照、歷史回滾/時(shí)光旅行的訴求 這些是缺失的
          • 優(yōu)點(diǎn):整體代碼是簡(jiǎn)單明了的,無(wú)侵入式
          • 熟練使用第三方庫(kù)是一個(gè)開(kāi)發(fā)者的基礎(chǔ)素養(yǎng)

          安排

          • 回復(fù)資料包領(lǐng)取我整理的進(jìn)階資料包
          • 回復(fù)加群,加入前端進(jìn)階群
          • console.log("點(diǎn)贊===點(diǎn)看===你我都快樂(lè)")
          • Bug離我更遠(yuǎn)了,下班離我更近了

          瀏覽 51
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲一级无码精品 | 日本成人大香蕉视频在线观看 | 国产精品内射婷婷 | 大香蕉现现伊人 | 天天干夜夜操 |