最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Vue3实践总结-状态管理

    正文概述 掘金(吴文周)   2021-03-21   1097

    状态管理

    简述

    • 多个组件,多个模块之间共享状态是最常见的开发述求,场景之多不胜枚举,例如全局用户状态,修改用户信息全局响应变化等等。

    常见的解决方案

    • 简单方案基于事件监听机制利用回调传参,多处订阅实现数据的流转。例如官方推荐的mitt事件库。优势简单的数据事件通信是能满足的,劣势随着数据复杂性变动,回调写法的代码阅读性,整体使用体验下降,使用方式也非常简单,具体实现如下:
    //定义组合api事件流
    const $emitter = mitt()
    /**
     * @name: useOnChange
     * @msg: 监听事件emit
     */
    export function useOnChange<T extends Function>(fun: T) {
      $emitter.on(EventsEnum.CHANGE, itemMessage => {
        fun(itemMessage)
      })
    }
    /**
     * @name: useChange
     * @msg: 触发事件emit
     * @param {*}
     */
    export function useChange(itemMessage: number) {
      $emitter.emit(EventsEnum.CHANGE, itemMessage)
    }
    
    // A组件中触发事件发送数据
    export default defineComponent({
      name: 'A',
      setup() {
       //组件A中发送数据
       const handlerClick = (item)=>{
         //使用组合api发送数据
         useChange(1)
       }
      }
     })
    
    // B组件中监听事件获取数据
    export default defineComponent({
      name: 'B',
      setup() {
        //回调中获取数据
       useOnChange((mes)=>{
        console.log(mes)
       })
      }
     })
     
    // C 组件中监听事件获取数据
    export default defineComponent({
      name: 'C',
      setup() {
       //回调中获取数据
       useOnChange((mes)=>{
         console.log(mes)
       })
      }
     })
    
    • 基于vue3的响应式官方一些简单的实践
    const store = {
      debug: true,
    
      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')
    
    • 知名状态管理库Redux,Flux,Vuex,这些都是非常优秀的第三方库

    为什么明明有vuex你还在折腾啥?

    • 先抛出一个问题大家用了element那么久,请问知道this.$message是怎么实现的吗?如果什么都不管,项目来了上去就是一套全家桶,做一个项目和做十个项目有什么区别?既然新的机会来了为什么自己写一下vue3的组件,vue3的状态管理?
    • 业务与场景在项目初期比较简单,没有记录变更、保存状态快照、历史回滚/时光旅行的诉求,那为什么不自己做一个状态管理呢?
    • 核心实现功能:状态修改单项数据流,状态改变全局数据响应,代码约定,思考一下怎么解决这三个问题?

    实现思路

    • 单项数据流,Readonly
    • 状态改变数据响应,组合api和响应式
    • 代码约束 使用ts 进行接口约定

    其他大神的一些实现

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

    站在巨人的肩膀上

    • 基于一些大神是vue3封装reduer思路自己也去做了实现
    1. 基础实现
    /*
     * @Description:Reducer
     * @version: 1.0.0
     * @Author: 吴文周
     * @Date: 2021-02-26 13:45:46
     * @LastEditors: 吴文周
     * @LastEditTime: 2021-03-02 14:52:33
     */
    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.实现小型reduer

     /*
     * @Description:xxx全局状态
     * @version: 1.0.0
     * @Author: 吴文周
     * @Date: 2021-02-26 13:53:09
     * @LastEditors: 吴文周
     * @LastEditTime: 2021-03-20 16:10:59
     */
    import { Ref } from 'vue'
    import { useModel, useReducer } from './reducer'
    // 状态接口
    export interface State {
       oo: string,
       xx: string,
       cc: string,
    }
    // 行为接口
    export interface Action {
      type: 'changeOO' | 'changeXX' | 'changeCC'//指定action
      payload: State
    }
    // 组合函数使用是 状态接口
    export type StateType = Readonly<Ref<State>>
    // 使用实例接口
    interface Redux {
      state: StateType
      // 这里不是注释,只是这样的语法mark当不识别,保证优雅性,实际使用时放开注释
      //dispatch: <T extends Action>(action: T) => void
    }
    // 状态变更
    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 }
    }
    // 初始化状态
    function useStore() {
      const initialState = {
        oo: 'oo',
        xx: 'xx',
        cc: 'cc',
      }
      return useReducer(reducer, initialState)
    }
    // 组合api 函数可以被任意组件 在任意地方调用
    export function useXXXRedux() {
      const redux: Redux = useModel(useStore)
      return redux
    }
    

    3.调用实现,在任意组件内,或者任何组合api内部,在哪里调用都行

    
    export default defineComponent({
      name: 'D',
      setup() {
       //回调中获取数据
        const { state:xxState,dispatch } = useXXXRedux()
       //监听state变化
        watch(xxState, state => {
        })
       //触发状态改变
       dispatch({type:"changeOO",{payload:{oo:"iii"}}})
     })
    

    总结

    • 缺点: 记录变更、保存状态快照、历史回滚/时光旅行的诉求 这些是缺失的
    • 优点:整体代码是简单明了的,无侵入式
    • 熟练使用第三方库是一个开发者的基础素养

    起源地下载网 » Vue3实践总结-状态管理

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元