vuex的理解和使用_vue.js项目实战

Vue (58) 2023-09-07 16:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说vuex的理解和使用_vue.js项目实战,希望能够帮助你!!!。

1.概述

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

Vuex 和单纯的全局对象有以下两点不同:

1.Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新;2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用

**2.安装使用 **

2.1.使用Vue-cli开发安装vue包

cnpm install vuex --save

2.2.在src目录下创建store文件夹并创建index.js如下(src/store/index.js)

import Vue from 'vue'
import Vuex from 'vuex'
 
Vue.use(Vuex);
 
export default new Vuex.Store({
 state: {
 
 },
 getters: {
 
 },
 mutations: {
 
 },
 actions: {
 
 }
});

然后在src文件下的main.js中使用

import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
 
 
new Vue({
 el: '#app',
 store,
 components: { App },
 template: '<App/>'
})

3.用法简介

** 3.1.state**

state是保存共享数据的,现在改store/index.js如下:

state: {
 count:0
 },

在components目录下创建Index.vue如:

<template>
 <div class="index">
 {{count}}
 </div>
</template>
 
<script>
 export default {
 name: "index",
 computed:{
 count(){
 return this.$store.state.count;
 }
 }
 }
</script>

结果如下:

vuex的理解和使用_vue.js项目实战_https://bianchenghao6.com/blog_Vue_第1张

我们可以通过组件的计算属性来保存state里面的值,那么问题来了,如果store太多的话,我们组件里面的计算属性岂不是成了这个样子:

computed:{
 count(){
 return this.$store.state.count;
 },
 stateA(){
 return this.$store.state.stateA;
 },
 stateB(){
 return this.$store.state.stateB;
 }
}

这样获取共享状态的数据也没有什么问题不过看起来还是有大量的重复冗余代码,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:

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

import {mapState} from 'vuex'
 export default {
 name: "index",
 computed:{
 ...mapState(['count']),
 }
 }

小结:使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。

3.2.getter

有的时候我们需要对共享状态里面的某一个属性做一些处理后再使用,我们可以把数据获取后再在组件的计算属性中处理,举个例子如下:

// store/index.js
state: {
 count:0,
 numbers:[0,1,2,3,4,5,6,7,8]
 },
// Index组件
<template>
 <div class="index">
 {{count}}
 <br>
 {{numbers.join()}}
 </div>
</template>
<script>
 import {mapState} from 'vuex'
 export default {
 name: "index",
 computed:{
 ...mapState(['count']),
 numbers(){
 return this.$store.state.numbers.filter((item)=>{
 return item>3;
 })
 }
 }
 }
</script>

结果如下:

vuex的理解和使用_vue.js项目实战_https://bianchenghao6.com/blog_Vue_第2张

那么问题来了,如果多个组件都要做同样的处理,我们就需要把一份代码复制到多个地方,显然是不大合理的,于是有了getter,可以理解为组件里面的计算属性。示例如下:

/ store/index.js
getters: {
 filterNumbers(state){
 return state.numbers.filter((item)=>{
 return item>3;
 })
 }
 },
// Index组件
<template>
 <div class="index">
 {{count}}
 <br>
 {{filterNumbers.join()}}
 </div>
</template>
 
<script>
 import {mapState} from 'vuex'
 export default {
 name: "index",
 computed:{
 ...mapState(['count']),
 filterNumbers(){
 return this.$store.getters.filterNumbers;
 }
 }
 }
</script>

结果完全一样,我们可以根据this.$store.getters.属性名来获取getters,也可以通过 mapGetters 辅助函数将 store 中的 getter 映射到局部计算属性:

具体实现方式如下:

<template>
 <div class="index">
 {{count}}
 <br>
 {{filterNumbers.join()}}
 <br>
 {{antherNumbers.join()}}
 </div>
</template>
 
<script>
 import {mapState,mapGetters} from 'vuex'
 export default {
 name: "index",
 computed:{
 ...mapState(['count']),6
 ...mapGetters(['filterNumbers']),
 ...mapGetters({
 antherNumbers:'filterNumbers'
 })
 }
 }
</script>

如果用同一名字直接把数组作为参数,如果想改一个名字,可以传入一个对象作为参数,结果如下:

vuex的理解和使用_vue.js项目实战_https://bianchenghao6.com/blog_Vue_第3张

3.3.mutation

在组件内,来自store的数据只能读取,不能手动改变,改变store中数据唯一的途径就是显示的提交mutations。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。改变代码如下:

// store/index.js
mutations: {
 add(state){
 state.count++;
 }
},
 
// Index组件
**
 <button @click="add">+</button>
**
 methods:{
 add(){
 this.$store.commit('add');
 console.log(this.count);
 }
**

vuex的理解和使用_vue.js项目实战_https://bianchenghao6.com/blog_Vue_第4张

连续点击5次增加按钮,发现count的值也改变了。当然,我们也可以传参进去

// store/index.js
mutations: {
 add(state,n){
 state.count+=n;
 }
},
 
// Index组件
**
 <button @click="add">+</button>
**
 methods:{
 add(){
 this.$store.commit('add',10);
 console.log(this.count);
 }
**

触发方法语句为:this.$store.commit(方法名);也可以使用辅助函数mapMutations代替:

methods:{
 ...mapMutations(['add']),
}

3.4.action

前面我们讲过,mutation有必须同步执行这个限制,我们在业务需求中有时候需要在获取ajax请求数据之后再操作或定时器操作数据,这些都属于异步请求,要用actions来实现。具体实现如下:

// store/index.js
mutations: {
 changeCount(state){
 state.count=3000;
 },
 },
 actions: {
 changeCount3000s(context){
 setTimeout(()=>{
 context.commit('changeCount')
 },3000)
 
// Index组件
<button @click="changeCount3000s">点击按钮3s后count的值改变</button>
methods:{
 ...mapMutations(['add']),
 changeCount3000s(){
 this.$store.dispatch('changeCount3000s');
 }
 }

我们在点击按钮3s后count的值改变为3000,我们可以通过this.$store.dispatch(方法名)来触发事件,也可以通过辅助函数mapActions来触发。

import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
 methods:{
 ...mapMutations(['add']),
 ...mapActions(['changeCount3000s'])
 }

学会以上几个属性的使用基本就可以满足平时业务中的需求了,但使用Vuex会有一定的门槛和复杂性,它的主要使用场景是大型单页面应用,如果你的项目不是很复杂,用一个bus也可以实现数据的共享,但是它在数据管理,维护,还只是一个简单的组件,而Vuex可以更优雅高效地完成状态管理,所以,是否使用Vuex取决于你的团队和技术储备。

对前端的技术,架构技术感兴趣的同学关注我的头条号,并在后台私信发送关键字:“前端”即可获取免费的架构师学习资料

知识体系已整理好,欢迎免费领取。还有面试视频分享可以免费获取。关注我,可以获得没有的架构经验哦!!

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

发表回复