vuex

Vuex_State

安装

npm install vuex --save

使用

  1. 在src目录下新建store文件,在store中创建store.js
    在这里插入图片描述
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default store

Vuex 通过store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中。
通过在根实例中注册store选项,该store实例会注入到根组件下的所有子组件中,且子组件能通过this.$store访问。如下。

  1. store.js
    在这里插入图片描述
    创建一个组件,当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:在computed中使用mapState,使用不同的变量接收不同的值。
    首先要引入
    在这里插入图片描述

在这里插入图片描述
可以简写如下

// 简写
    storeCount: 'count', // 等同于 state => state.count

然后在页面中就可以渲染
在这里插入图片描述


Vuex_Getter

store的计算属性。getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

Getter 接收state作为其第一个参数、getters作为其第二个参数。
在store.js中

getters: {
  doubleCount (state) {
    return state.count * 2;
  }
}

当然我们可以让getter返回一个函数
在这里插入图片描述
我们用组件中的computed接收他
在这里插入图片描述
在页面就就可以渲染我们想要的结果
在这里插入图片描述
也可以通过属性访问
Getter会暴露为store.getters对象:this.$store.getters.doubleCount
在这里插入图片描述
getter也拥有他的mapGetters 辅助函数,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
在这里插入图片描述
我们可以给他起个名字方便使用
在这里插入图片描述


Vuex_Mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
如下我们把想要更改state中的name值在store.js中:在这里插入图片描述
我们在组件中写一个方法,改变name值为当前我们设置的msg
在这里插入图片描述

在这里插入图片描述
这时我们渲染的值就会更改为我们当前data中设置的msg。
在这里 store.commit 传入的额外参数,即 mutation 的 载荷(payload):大多数情况下载荷为对象如下

mutations: {
  showPeople (state, payload) {
    state.name += payload.name
  }
}
store.commit('showPeople', {
  name: 欣欣
})

这时渲染值为原始名字+欣欣

当然我们可以使用mapMutations辅助函数
在这里插入图片描述

当然我们在store.js中修改age的值,然后在组建件页面提交后,值会被相应的修改
在这里插入图片描述
对象风格的提交方式

提交 mutation 的另一种方式是直接使用包含 type 属性的对象:

store.commit({
  type: 'increment',
  amount: 10
})

当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数,因此 handler 保持不变:

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

表单处理

发现一个问题:在Vuex的state上使用v-model时,由于会直接更改state的值,所以Vue会抛出错误。
在这里插入图片描述
在这里插入图片描述
会报错如下
在这里插入图片描述

解决办法:
Vuex 强调的是单向数据库, state 只能被读取,要写入 state 必须靠 mutation ,因此 v-model 无法直接写入 state 。

  1. 手写v-model的实现
    在这里插入图片描述
    storeName为state传过来的name值
    在这里插入图片描述
    在这里提交修改,onInputName负责接收 input event,呼叫 setName mutations 修改 name state。
    在这里插入图片描述
  2. Computed with Setter
    在这里插入图片描述

这里的name不是data中的而是computed中的
在这里插入图片描述
get() :负责从name state 抓数据
set() :负责呼叫 setName mutation 写入 state
当然前提是要提交状态变更
在这里插入图片描述
感觉第二种更优雅

Mutation 必须是同步函数

mutations: {
  [COUNT_INCREMENT] (state) {
    setTimeout(() => {
      state.count ++;
    }, 1000)
  },
}

执行上端代码,我们会发现更改state的操作是在回调函数中执行的,这样会让我们的代码在devtools中变的不好调试:当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用,任何在回调函数中进行的状态的改变都是不可追踪的。

Vuex_Action

Action 类似于 mutation,不同在于:

Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

分发Action

store.dispatch('increment')

支持同样的载荷方式和对象方式进行分发:

// 以载荷形式分发
store.dispatch('increment', {
  amount: 10
})

// 以对象形式分发
store.dispatch({
  type: 'increment',
  amount: 10
})
虽然和mutation差不多,但是在action中,可以执行异步操作,但是mutation中不行!!!
actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

在组件中分发 Action

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')`
    })
  }
}

组合 Action
Action 通常是异步的,那么如何知道 action 什么时候结束呢?

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}
store.dispatch('actionA').then(() => {
  // ...
})

Vuex 管理模式

Vuex_Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter。

const moduleA = {
  state: () => ({
    count: 0
  }),
  mutations: {
    increment (state) {
      // 这里的 `state` 对象是模块的局部状态
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}
获取 state:this.$store.state.moduleName.xxx
获取 getter:this.$store.getters.xxx
提交 mutation:this.$store.commit(‘xxx’);
分发 action:this.$store.dispatch(‘xxx’);
可以通过mapXXX的方式拿到getters、mutations、actions,但是不能拿到state,如果想通过这种方式获得state,需要加命名空间。

默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。例如:

const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true,

      // 模块内容(module assets)
      state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin']
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // 嵌套模块
      modules: {
        // 继承父模块的命名空间
        myPage: {
          state: () => ({ ... }),
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        // 进一步嵌套命名空间
        posts: {
          namespaced: true,

          state: () => ({ ... }),
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值