菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
205
0

Vue复习五(vuex)

原创
05/13 14:22
阅读数 30364

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--
  }
});

发表评论

0/200
205 点赞
0 评论
收藏
为你推荐 换一批