jiaozitang / Vuejs-note

0 stars 0 forks source link

Vuex #16

Open jiaozitang opened 6 years ago

jiaozitang commented 6 years ago

Vuex

多个组件共享状态时,可以很好的管理父子组件,兄弟组件的共享状态 vuex是一个专门为vue.js设计的集中式状态管理架构。状态?我把它理解为在data中的属性需要共享给其他vue组件使用的部分,就叫做状态。简单的说就是data中需要共用的属性。比如:我们有几个页面要显示用户名称和用户等级,或者显示用户的地理位置。如果我们不把这些属性设置为状态,那每个页面遇到后,都会到服务器进行查找计算,返回后再显示。在中大型项目中会有很多共用的数据,所以尤大神给我们提供了vuex。

安装

npm install vuex --save-dev

import Vuex from 'vuex'

Vue.use(Vuex)

开始

每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。

核心概念

store

根实例中注册 store 选项 子组件能通过 this.$store 访问到 image image

mapState 辅助函数 帮助我们生成计算属性

Getter

可以认为是 store 的计算属性。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。 mapGetters 辅助函数

Mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

Action

Action 可以包含任意异步操作。 Action 通过 store.dispatch 方法触发 image image

项目结构

image

jiaozitang commented 6 years ago

State

由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态.

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

mapState

帮助我们生成计算属性

import { mapState } from 'vuex'

computed: mapState({
        // 箭头函数可使代码更简练,cart是module
        test_num: state => state.cart.test_num,
      }),

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])

对象展开运算符

computed: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}
jiaozitang commented 6 years ago

Getter

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。 Getter 接受 state 作为其第一个参数:

getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
jiaozitang commented 6 years ago

Mutation

更改 Vuex 的 store 中的状态

//cart.js:cart是module
const mutations = {
  increment (state) {
    // 变更状态
    state.test_num++
  }
};
//xxx.vue:
this.$store.commit('increment');

提交载荷(Payload)

向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):

const mutations = {
  increment (state,payload) {
    // 变更状态
    state.test_num+=payload.num
  }
};

this.$store.commit('increment',{
          num:10
        });

在组件中提交 Mutation

import { mapMutations } from 'vuex'

export default {
  // ...
  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')`
    })
  }
}

在 Vuex 中,mutation 都是同步事务:

jiaozitang commented 6 years ago

Action

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。 Action 类似于 mutation,不同在于:

Action 通过 store.dispatch 方法触发

const actions = {
  increment (context,payload) {
    context.commit('increment',payload)
  }
};

mounted(){
        this.$store.dispatch('increment',{
          num:100
        });
      },

...mapActions

import { mapActions } from 'vuex'

export default {
  // ...
  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')`
    })
  }
}
jiaozitang commented 6 years ago

Module

每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

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 的状态

namespaced: true 使其成为带命名空间的模块。