zoukankan      html  css  js  c++  java
  • Vue复习五(vuex)

    vuex

    状态管理模块

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export const store = new Vuex.Store({
        state: {
            count: 0,
            num:2
        },
        mutations: {
            increment (state) {
                state.count++
            },
            add(state) {
                state.num++
            }
        }
    })
    

    导入mian.js

    import './components/vuex'
    import {store} from './components/vuex'
    new Vue({
    
        render: h => h(App),
        router,
        store
    }).$mount('#app')
    

    页面上使用

    this.$store.state.count
    

    mapState

    computed: {
      localComputed () { /* ... */ },
      ...mapState({
      	 count: state => state.count,
    
        // 'count' 和 `state => state.count` 结果相同
        countAlias: 'count',
    
        // to access local state with `this`, a normal function must be used
        countPlusLocalState (state) {
          return state.count + this.localCount
        }
      })
    }
    
    如果是数组的话
    [
      // 映射 this.count 为 store.state.count
      'count'
    ]
    

    getter (类似计算属性)

    类似于store 的计算属性

       getters: {
            // 第二个参数传递其他的getters
            doneTodos: ({todos}, {numAdd}) => {
                console.log(numAdd);  //3
                return todos.filter(todo => todo.done)
            },
            numAdd: ({num}) => {
                return num + 1
            }, //方法的形式的访问
            getTodoBy: (state) => id => {
                return state.todos.find(todo => todo.id === id)
            }
        }
    

    使用

    store.getters.getTodoBy(2)
    store.numAdd
    

    mapGetters

     computed: {
        ...mapGetters([
            'numAdd' ,
            'doneTodos',
            'getTodoBy'
        ])
      },
        对象的形式
    ...mapGetters({
      // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
      doneCount: 'doneTodosCount'
    })
    

    Mutation(类似事件)

    Vuex 中的 mutation 非常类似于事件

      mutations: {
            // 第二个是传递的参数,可以是基本数据类型也可以复杂
            increment(state, n) {
                return state.num + n
            }
        },
           
        this.$store.commit('increment',20)        
    

    提交方式

    store.commit({
      type: 'increment', // 方法
      amount: 10  //后面的传递参数
    })
    整个对象都作为载荷传给 mutation 函数
    
    mutations: {
      increment (state, payload) {
        state.count += payload.amount
      }
    }
    

    响应式规则

    1. 最好提前在你的 store 中初始化好所有所需属性。
    2. 当需要在对象上添加新属性时,你应该
    • 使用 Vue.set(obj, 'newProp', 123), 或者

    • 以新对象替换老对象。

      state.obj = { ...state.obj, newProp: 123 }
      

    常量替代Mutation 事件类型

    // mutation-types.js
    export const SOME_MUTATION = 'SOME_MUTATION'
    
      mutations: {
        // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
        [SOME_MUTATION] (state) {
          // mutate state
        }
      }
    

    mutation 是同步函数的

    mapMutations

     methods: {
        ...mapMutations([
          'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
    
          // `mapMutations` 也支持载荷:
          'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
        ]),
        ...mapMutations({
          add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
        })
      }
    

    Action

    • Action 提交的是 mutation,而不是直接变更状态。
    • Action 可以包含任意异步操作。
    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increase(state) {
          state.count++;
        }
      },
      actions: {
        increase(context) {
          context.commit("increase");
        },
        increment ({ commit }) {
        commit('increment')
        }
      }
    });
    

    触发

    store.dispatch('increment')
    传递参数
    // 以载荷形式分发
    store.dispatch('incrementAsync', {
      amount: 10
    })
    
    // 以对象形式分发
    store.dispatch({
      type: 'incrementAsync',
      amount: 10
    })
    

    方法的操作不同

    vuex的处理方式是同步在mutation里面,异步在actions里面

    因为异步操作是成功还是失败不可预测,什么时候进行异步操作也不可预测;当异步操作成功或失败时,如果不 commit(mutation) 或者 dispatch(action),Vuex 和 Redux 就不能捕获到异步的结果从而进行相应的操作

    action

      methods: {
        ...mapActions([
          'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
    
          // `mapActions` 也支持载荷:
          'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
        ]),
        ...mapActions({
          add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
        })
      }
    
    store.dispatch('actionA').then(() => {
      // ...
    })
    

    使用

      methods: {
        ...mapActions([
            "increaseAsync" //   this.increment() 等价 this.$store.commit('increment')
        ])
      },
          
         
    

    Module

    分割成多个模块

    const moduleA = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    
    const moduleB = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        a: moduleA,
        b: moduleB
      }
    })
    
    store.state.a // -> moduleA 的状态
    store.state.b // -> moduleB 的状态
    

    action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState

    const moduleA = {
      // ...
      actions: {
        incrementIfOddOnRootSum ({ state, commit, rootState }) {
          if ((state.count + rootState.count) % 2 === 1) {
            commit('increment')
          }
        }
      }
    }
    

    命名空间

    export const moduleA={
        namespaced: true,
        state:()=>({
            numA:1
        }),
        mutations:{// 方法
            login(state) {
                 state.numA++
            }
        },
        getters: { // 类似计算属性
            doneNum(state) {
                return state.numA + 1
            }
        }
    }
    =========
        <button @click="add">Click</button>
    	{{sex}}
    =========
          
      computed: {
        ...mapState({
            num:state => state.a.numA
        }),
        ...mapGetters({
          sex: 'a/doneNum'
        })    
      }
    	
         methods: {
            ...mapMutations({
              add:'a/login'
            })
          }
    

    传参

     mutations:{
            login(state,str) {
                console.log(str);
                state.numA++
            }
        }
    
        <button @click="add(10)">Click</button>
    

    Actions 同理跟mutaion 类似

    也可以这种形式

    computed: {
      ...mapState('some/nested/module', {
        a: state => state.a,
        b: state => state.b
      })
    },
    methods: {
      ...mapActions('some/nested/module', [
        'foo', // -> this.foo()
        'bar' // -> this.bar()
      ])
    

    使用辅助函数查找命名空间

    import { createNamespacedHelpers } from 'vuex'
    									
    const { mapState, mapActions } = createNamespacedHelpers('a')
    
    export default {
      computed: {
        // 在 `some/nested/module` 中查找
        ...mapState({
          a: state => state.a,
          b: state => state.b
        })
      },
      methods: {
        // 在 `some/nested/module` 中查找
        ...mapActions([
          'foo',
          'bar'
        ])
      }
    }
    

    总结

    state 数据
    getters 计算属性
    mutaions 同步方法
    actions  异步方法
    modules  分模块
    

    表单处理

    双向绑定的计算属性

    <input v-model="message">
        
    computed: {
      message: {
        get () {
          return this.$store.state.obj.message
        },
        set (value) {
          this.$store.commit('updateMessage', value)
        }
      }
    }    
    

    模块重用

    这个状态对象会通过引用被共享,导致状态对象被修改时 store 或模块间数据互相污染的问题。

    实际上这和 Vue 组件内的 data 是同样的问题。因此解决办法也是相同的——使用一个函数来声明模块状态

    const MyReusableModule = {
      state: () => ({
        foo: 'bar'
      }),
      // mutation, action 和 getter 等等...
    }
    

    watch

    页面上
    watch: {
        '$store.state.app.language': function () {
          //你需要执行的代码
        }
    }
    

    监控state,getter的数据的变化

      watch<T>(
          getter: (state: S, getters: any) => T, 
          cb: (value: T, oldValue: T) => void,
              options?: WatchOptions): () => void;
              
     mounted() {
        this.unsub = this.$store.watch(
            // return 返回的监听的值,返回的也可以是数组
            (state,getters)=>{
              return state.a.numA
            },
            //现在的值,之前的值
            (value,oldValue)=>{
              console.log(value,oldValue);
            } ,
            // 是否深度监控
            {
              deep:true
            }
        );
      },
      destroyed() {
        this.unsub();
      },     
    

    subscribe

    发布订阅的统一监控

     created() {
        this.unsubscribe = this.$store.subscribe((mutation, state) => {
          if (mutation.type === 'updateStatus') {
            console.log(`Updating to ${state.status}`);
    
            // Do whatever makes sense now
            if (state.status === 'success') {
              this.complex = {
                deep: 'some deep object',
              };
            }
          }
        });
      },
      beforeDestroy() {
        this.unsubscribe();
      },
    记得离开的时候要取消订阅
    

    vuex-persistedstate

    在页面重新加载之间坚持并重新补充Vuex状态。

    https://github.com/robinvdvleuten/vuex-persistedstate#readme

    其实底层就是默认把state存在localStorage

    import Vuex from "vuex";
    import createPersistedState from "vuex-persistedstate";
    
    const store = new Vuex.Store({
      // ...
      plugins: [createPersistedState()],
    });
    

    在需要的模块里面添加,直接传给后台,如果清理的话直接改state 里面的值就行了

    import createPersistedState from 'vuex-persistedstate';
    import Cookies from 'js-cookie';
    
    Vue.use(Vuex)
    
    const store = new Vuex.Store({
      state: {
        count: 0
      },
      plugins: [createPersistedState({
        storage: {
          getItem: key => Cookies.get(key),
          setItem: (key, value) => Cookies.set(key, value, { expires: 3, secure: true }),
          removeItem: key => Cookies.remove(key)
        }
      })],
      mutations: {
        increment: state => state.count++,
        decrement: state => state.count--
      }
    });
    

    决定自己的高度的是你的态度,而不是你的才能

    记得我们是终身初学者和学习者

    总有一天我也能成为大佬

  • 相关阅读:
    使用Docker搭建nginx环境
    使用Docker搭建apache环境
    字符编码-字库表,字符集,字符编码
    go中的sync.pool源码剖析
    JAVA基础语法
    Linux 文件目录管理
    c++ 学习之常用时间函数一览
    MySQL Innodb 中的锁
    MySQL 索引与 B+ 树
    MySQL 表分区操作详解
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/14398130.html
Copyright © 2011-2022 走看看