Vue2-vuex使用

前言

此篇为本人自学时做的笔记,不完全算教学篇,如有错误或解释不清楚的地方,或者有更好的建议,请指出,我会及时更正

一、vuex的介绍

1.概述

vuex是一个vue中的一个插件,可以帮我们管理vue通用(多组件共享)的数据

2.应用场景

某个或某些数据被多个组件共享

3.优势

3.1数据集中化管理

在使用vuex之前,在创建的组件越来越多的情况下,组件之间的数据操作会越来越麻烦,学习vuex之后,可以使数据集中化管理,即把数据放在一个特有的地方,可看作是一个仓库,所有组件都可以直接通过仓库操作数据

3.2响应式变化

任意一个组件对仓库的数据进行修改时,随着仓库中数据的变化,所有用到该仓库数据的组件都会随之响应式更新(一个变化全都变)

3.3语法简洁

vuex中提供了一些辅助函数,帮助我们更加简洁快速的操作仓库中的数据


二、 vuex的基本使用

如何创建一个存放数据的仓库

1.安装vuex

创建好VueCli项目后,在该项目中打开终端

输入yarn add vuex@3 或npm install vuex@3 

注:如果使用npm安装出现报错,需在后面添加--legacy-peer-deps

2.新建vuex模块文件

在src目录下创建一个store(仓库)目录,在该目录下创建index.js文件

所有与vuex相关的核心代码都写在新建的index.js文件中

3.创建仓库

4.在main.js中导入挂载


三、vuex的进阶使用

在3.3中提到了vuex提供了许多简洁的语法及函数,我会详细介绍它们的用法

1.state状态(数据)

学习state可以掌握如何给仓库提供数据,如何使用仓库中的数据

1.1在仓库中通过state提供、存储数据

1.2使用数据

第一种:通过store直接访问

第二种:通过mapState辅助函数(语法简洁)

 mapState是 Vuex 提供的一个辅助函数,用于将 Vuex 的状态映射到 Vue 组件的计算属性中

使用辅助函数前,需要用{{ $store.state.msg }}来获取值,通过mapState函数的使用,我们可以直接用{{msg}}显示数据,简洁了语法

问:为什么要用展开运算符?

使用展开运算符之前

computed:mapState(['msg','count'])

这样的写法是正确的,但是缺少了可拓展性,即不能添加额外的其他计算属性,所以更改成

 computed: {
    ...mapState(['msg', 'count']),
    outerComputed(){
    //其他计算属性
    }
  }

问:为什么更改之后要用展开运算符?有什么区别?

不使用展开运算符时

computed: {
  mapState(['msg', 'count'])  
}

这段代码等效于

computed: {
  mapState: mapState(['msg', 'count'])
}

使用展开运算符后:

computed: {
  ...mapState(['msg', 'count'])  
}

等效于以下代码

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

总结:

  • 使用展开运算符computed: { ...mapState(['msg', 'count']) } 使 msgcount 成为 computed 的直接属性。

  • 不使用展开运算符computed: { mapState(['msg', 'count']) } 会导致 computed 中包含一个 mapState 属性,而不是将 msgcount 展开为计算属性。


2.mutations(修改数据)

由于vuex同样遵循单项数据流,即组件中不能直接修改仓库数据

错误写法:

this.$store.state.count++// 直接在组件中修改仓库中的数据

注:该错误写法不会报错,对于初学者来说我们希望将错误代码实现报错,可开启严格模式

const store = new Vuex.Store({

    strict: true,//开启严格模式,项目上线时需关闭,减少性能消耗

    state:{
        count:180
    }
})

正确写法:

2.1通过mutations定义方法修改数据

const store = new vuex.Store({
  state: {
    count: 0,
    msg: 'hello vuex'
  },
  // 1.定义mutations
  mutations: {
    add (state) {
      state.count++//增加数据
    },
    sub (state) {
      state.count--//减少数据
    }
  }
})

2.2给要修改的数据添加方法,例如给按钮添加点击事件绑定方法

<button @click="addDemo">值 + 1</button>

2.3在下方注册方法,提交调用mutation

 methods: {
    addDemo() {
      this.$store.commit('add')
    }

注:1.提交的名字要与1.中定义的方法名相同

        2.mutations定义方法可传参,但第一个参数必须为state

        3.mutations参数只能多传一个,如果存在需要传入多个参数的情况,需打包成对象或数组的形式

this.$store.commit('add',obj)

2.4mapMutations辅助函数(简洁语法)

mapMutations 和 mapState很像,它是把位于mutations中的方法提取了出来,映射到组件methods中

例如:在mutations中定义的一个add和一个sub方法

const store = new vuex.Store({
  state: {
    count: 0,
    msg: 'hello vuex'
  },
  // 1.定义mutations
  mutations: {
    add (state) {
      state.count++
    },
    sub (state) {
      state.count--
    }
  }
})

在组件中导入mapMutations包

import { mapMutations } from 'vuex'

在下方methods中使用mapMutations包

//用辅助函数前
methods: {
    addDemo () {
      this.$store.commit('add')
    }
    subDemo () {
    this.$store.commit('sub')
    }
}
methods: {
    ...mapMutations(['add','sub'])//用辅助函数后,语法更简洁
  }

这样就可以直接在组件中用add(),sub()调用方法

<button @click="add">值 + 1</button>

注:如果同时使用mapMutations 和 mapState,在导包时可能会遇到以下错误

解决方法:只需修改成下列代码即可

import { mapState, mapMutations } from 'vuex'

3. actions(异步操作)

actions用于处理异步操作,例如两秒后将数据改为xxx,请求数据等

注:actions不饿能直接操作state,操作state还是需要commit mutation

3.1在store仓库中通过mutations注册方法用来修改state

mutations: {
    add (state,num) {
      state.count = state.count + num
    }
  },

3.2在store仓库中注册actions

actions: {
    setNum (context, num) {
    // 一秒后,调用add方法,使num+1
      setTimeout(() => {
        context.commit('add', num)//add为mutations中定义的方法
      }, 1000)
    }
  }

3.3在页面中用dispatch语法调用

this.$store.dispatch('setNum',180)

3.4mapActions(简洁语法)

与上面两个同理,actions也有自己的辅助函数,语法与上面两个相同

// 1.导入mapActions包
import { mapActions } from 'vuex'
// 2.使用mapActions包
methods: {
    ...mapActions(['setNum'])
}
// 3.应用
<button @click="setNum(180)">1s后值 + 180</button>

4.getters(类似计算属性)

除了state之外,有时我们还需要从state中派生出一些状态,这些状态是依赖state的,此时会用到getters

例如:在state中新定义一个list数组,要求显示所有大于5的数据

state:{
    list:[1,2,3,4,5,6,7,8,9,10]
}

操作步骤:

// 1.定义getters
    filterList(state) {
    return state.list.filter(item => item > 5) // 用filter 过滤出大于五的数据
}

注:1.getters函数的第一个参数必须是state

        2.getters函数必须要有返回值

// 2.通过store访问getters
{{ $store.list.filterList}}

同样,getters也有自己的辅助函数mapGetters,用法与前三个类似

// 1.导入mapGetters包
import { mapGetters } from 'vuex'
// 2.使用mapGetters包
computed: {
    ...mapGetters(['filterList'])
}
// 3.应用
<div>{{ fliterList }}</div>

注:由于getters与计算属性类似,所以放在computed中而不是methods中,

应用时直接用{{ fliterList  }}而不是像方法 fliterList()那样调用

5.module(进阶语法)

随着仓库中state数据越来越多,项目的可维护性变差,此时需要module语法使state模块化,即把数据分给多个不同的模块js组件,再通过moudule挂载回state上,实现数据的拆分,便于更好的维护

5.1新建一个module文件夹,用来装模块文件,这里举例建了两个模块文件

5.2在新建的模块文件中编写对应模块内容的数据即可

5.3在index.js中导入挂载

// 1.导入
import uesr from './module/uesr'
import setting from './module/setting'
//挂载
modules: {
    uesr,
    setting
  }
// 3.应用
// 根据vue调试工具查看路径
<h2>{{ $store.state.setting.modulestate }}</h2>

也可通过mapState辅助函数来简洁语法

computed: {
    ...mapState(['setting'])
  }

注:由上图我们可以得知setting返回的是一个对象(Object)

所以应用时需要用

<h2>{{ Object.moudelestate }}</h2>

来获取数据

那么我们直接通过setting子模块来获取值而不是根模块,是不是就能简洁一步操作呢?

只需两步

export default {
  namespaced: true, // 1.在子模块中开启命名空间
  state,
  mutations,
  actions,
  getters
}
// 2.通过子模块组件直接获取
computed: {
   //  ...mapState('模块名', ['xxx'])
   // 例如
   ...mapState('setting', ['modulestate'])
  }

这样就可以直接通过{{ modulestate}}来获取数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值