Vuex 五分钟带你初识Vuex|基础__Vue.js
发布于 8 个月前 作者 banyungong 441 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

前言

此文章比较适合初学者,如有什么不准确的地方欢迎大佬指正!

Vuex是什么?

官方概念:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex文档地址 Vuex官方地址

换句话说:就是帮助我们储存多个组件共享的数据,方便存取我们和修改,将数据或者状态进行集中式管理。

如何使用Vuex?

目前我们还没有引入vuex,我们需要先下载vuex,并且引入它

  • 首先全局安装Vuex
npm install vuex --save
  • 安装成功后就可以新建项目啦(当然现有的项目也可以)
  • 在项目src目录新建store文件,在store文件夹内新建index.js文件
  • 打开index.js导入Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
  • 创建一个vuex实例并抛出
const store = new Vuex.Store({})
export default store
  • 最后我们在main.js中导入并全局注册
import store from './store/index'
new Vue({
  store,
  render: h => h(App),
}).$mount('#app'

Vuex几大核心属性

大概的框架我们已经搭载完毕 现在我们来了解一下Vuex的几大核心属性吧~

Vuex有五个核心属性:

1.state

2.mutation

3.action

4.getters

5.moudle

我们来分别说一下每个属性吧~

  • state:唯一的数据源与vue实例中我们熟悉的data遵从一样的规则 获取state定义的值 $store.state.key名
  • mutation:在vuex中更改store中的状态唯一的方法就是提交mutation,这非常类似于时间 使用$store.commit(‘方法名’)触发。
  • action:action类似于mutation 但值得注意的是 action是提交mutation 并不是直接变更状态,而且action可以包含任意的异步操作。
  • getters:可以认为是 store 的计算属性,就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值。
  • module 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块module。

小Demo初探Vuex

属性了解之后 我们通过一个小案例一起来初探一下vuex吧~ 在此之前我们已经搭建了一个大概的框架,现在我们开始尽情的玩耍Vuex吧

  • 首先我们回到index.js 在我们创建的属性中添加一个state属性,并定义一个数据
const store = new Vuex.Store({
        state:{
            count:0
        },
    })

  • 接下来我们回到任意一个.vue文件中使用 $store.state.count获取在vuex定义的数据
<template>
  <div id="app">
    <h1>{{ $store.state.count }}</h1>
  </div>
</template>

  • 这时我们运行页面 就会看到神奇的一幕 在页面中就会看到我们定义的数据。

运行结果

获取state中数据的第二种打开方式

  • 首先从Vuex中按需导入mapState辅助函数
import { mapState,mapMutations } from 'vuex'
  • 在computed属性中声明要获取的state数据
   computed: {
    ...mapState(["count"])
  },
  • 在视图中进行插值表达式绑定,运行结果和上图一致。
<template>
  <div id="app">
    <h1>{{count }}</h1>
  </div>
</template>

mutation修改数据

到这里我们回想一下 首先安装vuex 创建store实例并抛出去 在main.js引入 并使用 $store.state.key 名在页面中使用了数据 那么我们要如何修改数据呢? 前面说过 更改 store 中的状态的唯一方法就是提交 mutation 那么我们来尝试一下吧。

  • 在我们的刚刚.vue文件中新增两个按钮:
<template>
  <div id="">
    <button>+</button>
        <h1>{{ $store.state.count }}</h1>
    <button>-</button>
  </div>
</template>
  • 回到store文件夹下的index.js 在刚刚创建的实例中加入mutation属性 该方法接收两个参数,默认接收state为第一个参数,另一个为自定义参数 我们在mutation中定义两个方法:
const store = new Vuex.Store({
  state: {
    count: 0,
  },
  mutations: {
    increment(state) {
      state.count++;
    },
    decrement(state) {
      state.count--;
    },
  },
});
  • 定义完成回到.vue文件 如何使用mutation呢,其实就和我们自定义事件非常相似 还记得如何触发mutation吗 使用$store.commit(‘方法名’)
<template>
  <div id="">
    <button [@click](/user/click)="increment()">+</button>
        <h1>{{ $store.state.count }}</h1>
    <button [@click](/user/click)="decrement()">-</button>
  </div>
</template>

 methods: {
    increment() {
      this.$store.commit("increment");
    },
    decrement() {
      this.$store.commit("decrement");
    },
  },

此时我们来浏览器看一下,我们点击按钮会发现数据变化了!成功触发了mutation~

运行结果

Mutation 参数传递

前面说过每个mutation都会默认接收state作为第一个参数,除此之外还可以接收我们动态传递过去的参数,以刚才的例子为例,现在我们点击按钮式传递一个参数,让state动态增加或减少我们所传递过去的参数。

  • 同样在页面中新增两个按钮
<template>
  <div id="app">
    <button [@click](/user/click)="add()">+</button>
    <button>+N</button>
    {{ count }}
    <button>-N</button>
    <button [@click](/user/click)="reduce()">-</button>
  </div>
</template>
  • 回到store文件夹下的index.js mutations 写入方法,方法中第一个参数是我们的state,第二个参数就是接收我们传递过去的参数的。
 incrementN(state,step) {
      state.count+=step;
    },
    
 decrementN(state,step) {
      state.count-=step;
    },
  • 定义完成回到.vue文件 触发定义的mutation,此时运行页面点击+N或-N就会增加或减少我们所传递的参数值。
<template>
  <div id="app">
    <button [@click](/user/click)="add()">+</button>
    <button [@click](/user/click)="addN()">+N</button>
    {{ count }}
    <button [@click](/user/click)="reduceN()">-N</button>
    <button [@click](/user/click)="reduce()">-</button>
  </div>
</template>
methods: {
    //点击按钮count+1
    add() {
       this.$store.commit("increment");
    },
    //点击按钮count-1
    reduce() {
      this.$store.commit("decrement");
    },
    //点击按钮传递参数count+n
    addN() {
      this.$store.commit("incrementN", 3);
    },
    //点击按钮传递参数count-n
    reduceN() {
      this.$store.commit("decrementN", 3);
    },
  },

运行结果

Mutation 的第二种使用方式

  • 从vuex中导入mapMutations 辅助函数
import { mapState,mapMutations } from 'vuex'
  • 在methods方法中声明我们要用到的mutation,就可以直接调用啦~
methods: {
    ...mapMutations(["increment", "incrementN", 'decrement','decrementN']),
    //点击按钮count+1
    add() {
       this.increment()
    },
    //点击按钮count-1
    reduce() {
      this.decrement()
    },
    //点击按钮传递参数count+n
    addN() {
      this.incrementN(3)
    },
    //点击按钮传递参数count-n
    reduceN() {
      this.decrementN(3)
    },
  },

Action的核心概念

我们刚刚实现了计数器的自增自减,假如现在有一个新的需求,我希望点击按钮修时等待一秒在修改数据,应该怎么做呢?

那么就要介绍一个vuex的另一个核心概念 action 因为mutation不支持异步操作,我们大可以通过action来实现异步。

  • 同样在.vue文件中定义按钮
<template>
  <div id="app">
    <button>异步+N</button>
{{ count }}
 	<button>异步-N</button>
  </div>
</template>
  • 回到store文件夹下的index.js,在 store 实例中新增 actions,并写入方法,action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此我们可以调用 context.commit 提交一个 mutation
 actions:{
    incrementNAsync(context,step){
      setTimeout(() => {
        context.commit('incrementN',step)
      },1000)
    },
    decrementNAsync(context,step){
      setTimeout(() => {
        context.commit('decrementN',step)
      },1000)
    }
  }
  • 定义完成回到.vue文件使用 $store.dispatch 来触发,此时点击按钮就会发现数据会在一秒之后更改。
<template>
  <div id="app">
    <button [@click](/user/click)="addNAsync()">异步+N</button>
    {{ count }}
    <button [@click](/user/click)="reduceAsync()">异步-N</button>
  </div>
</template>
  methods: {
   addNAsync(){
      this.$store.dispatch('incrementNAsync',3)
    },
    reduceNAsync(){
      this.$store.dispatch('decrementNAsync',3)
    }
  },

action的第二种使用方式

  • 从vuex中导入mapActions函数
import {mapActions} from "vuex";
  • 在methods方法中声明我们要用到的action,就可以直接调用
<template>
  <div id="app">
    <button [@click](/user/click)="addNAsync()">异步+N</button>
    {{ count }}
    <button [@click](/user/click)="reduceNAsync()">异步-N</button>
  </div>
</template>
methods: {
    ...mapActions(["incrementNAsync", "decrementNAsync"]),
    addNAsync() {
      this.incrementNAsync(3);
    },
    reduceNAsync() {
      this.decrementNAsync(3);
    },
  },
这种方式下也可以直接调用mapActions声明的方法,不用在methods从新定义方法, 同样mutaiton也支持此种方式。
<button [@click](/user/click)="incrementNAsync(3)">异步+N</button>
<button [@click](/user/click)="'decrementNAsync'(3)">异步+N</button>
...mapActions(['incrementNAsync', 'decrementNAsync']),

getter核心属性

getter用于对store中的数据进行加工处理,不会修改原数据,类似于 computed 属性 当 store 数据发生变化, getter 也会相应发生变化

  • 在store文件夹下的index.js中新增getters,定义一个新的函数
 getters:{
    showMsg(){
      return '我是getters'
    }
  }
  • 回到.vue文件中使用插值表达式的方式
    <p>{{ $store.getters.showMsg}}</p>
    

getter第二种使用方式

  • 从vuex中导入mapGetters函数
从vuex中导入mapGetters函数
  • 在computed中声明要用到的getters
...mapGetters(['showMsg']),
  • 在页面中直接引入
<p>{{showMsg}}</p>


## 写在最后
这是我在掘金发表的第一篇文章,修修改改好几次,还在持续优化中,如果有哪啦不准确的地方,欢迎指正,最后希望可以得到你手里的小心心~
<p style="line-height: 20px; color: #ccc">
       版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
       作者: 太可爱了啊
       原文链接:<a href='https://juejin.im/post/6854573222051430413'>https://juejin.im/post/6854573222051430413</a>
     </p>
回到顶部