本文主要是介绍Tracy 小笔记 Vue - Vuex,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Vuex
- 它是一个插件,提供了一个全局对象,并且这个对象可以实现响应式更新
Vuex 使用单一状态树(Single Source of Truth: 也可叫单一数据源)来管理应用层的全部状态 - 一般什么情况下应用?
- 用戶的登入状态
- 用户名称、头像、地理位置等信息
- 商品的收藏、购物车中的物品
- 它是一个插件,因此需要安装 npm install vuex
- 它要存在 src 下的 store 文件夹 index.js 文件
import Vue from 'vue' import Vuex from 'vuex'//1.安装插件 Vue.use(Vuex)const moduleA = {state: {counter: 66},mutations: {},actions: {},getters: {} }//2.创建对象 const store = new Vuex.Store({state: { //这里放置全局变量counter: 5,students: [{ name: "Tracy1", age: "11" },{ name: "Tracy2", age: "21" },{ name: "Tracy3", age: "31" },],info: { name: '11', value: '22' }},mutations: {increaseCounter(state) { //这里的 state 是自动获取的state.counter++;}},actions: {addPropTimeOut(content) {setTimeout(() => {content.commit('addProp'); //action 只调用异步,真正修改对象的值还是得像这样调用 mutation 中的方法}, 3000);},},getters: {doubleCounter(state) {return state.counter * 2;}},modules: {a : moduleA,} }); //3.导出 store export default store
- main.js 添加 code
import store from './store'
并且将 store 和 router 一样挂载在 Vue 实例中new Vue({el: '#app',router,store,render: h => h(App) })
- Vuex 状态管理图例
这个图的一些解释
- Vue components : 我们的组件树
- State: 放我们各种数据的,任何组件都可以直接显示这个 State (eg:$store.state.name)
- Mutations: 比如一个按钮点击的时候,调佣一个 mutation 里的函数,在这个函数里去修改 State 中的数据(如果在组件中直接更改全局变量的值:不通过Mutation,这个值也可以硬改,但是 Devtools 就监听不到了,不利于大型项目的追踪和维护)
- Actions: 如果在本次提交的时候有一些异步的数据(比如网络请求)就需要在 Action 中处理,因为 Mutations 中是不可以处理异步请求的,这里和 Backend API (后端的一些接口)请求一些数据
- Devtools 是 Vue 开发的一个浏览器插件,可以监听 Vuex 中全局变量的动态变化
Devtools 的安装
vue其实提供了一个devtools,方便我们对组件或者vuex进行调试:
我们需要安装beta版本支持vue3,目前是6.0.0 beta15;
它有两种常见的安装方式:
方式一:通过chrome的商店;
Chrome 添加扩展程序 : 打开 Chrome 网上应用商店 搜 devtool : 安装 Vue.js devtools
方式二:手动下载代码,编译、安装;
去 github 搜索 vue devtool
或者直接打开下载:https://github.com/vuejs/devtools/tree/v6.0.0-beta.15
不推荐直接下载,我们找到 tag 找到这个版本来下载
执行 yarn install 安装相关的依赖;
执行 yarn run build 打包;
打包之后回到浏览器 加载已解压的扩展程序,我们要找的文件夹就是:packages\shell-chrome
安装之后再控制台 “console” 那行会多出来一个 “Vue”
还要在浏览器右上角点亮它
一个网站如果是 vue 开发的话 它就会亮起来
用了这个 tool 就可以看到插件的监听了,它会显示在什么时间,哪个全局变量被改成了什么
左边是组件,右边是组件里的各种状态
想看 vuex 的话 切换这里
如果在使用中发现报错this.$store.commit is not a function ,请打开你项目的配置文件package.json,查看你正在使用的vuex的版本,我正在使用的是vuex2.0,如果想删除旧版本的vuex并安装新版本的vuex
请使用
npm rm vuex --save
然后安装最新的vuex
npm install vuex --save
即可解决这个错误,或者是查看vuex官网api修改提交mutation的语句
Vuex 核心概念
- Vuex 对象中有几个比较核心的概念
const store = new Vuex.Store() - State: 变量存储的地方
页面直接显示{{$store.state.counter}}
如果觉得这个写法有点长,那么我们可以使用一个辅助函数 mapState -
/ vue2 用法 options APIimport {mapState} from 'vue'1.数组写法 html 调用原来的名字 {{counter}}, {{userInfo}},{{conference}}computed:{...mapState(["counter","userInfo", "conference"]) }// ... 展开运算符,相当于我们目前有了 三个计算属性2.对象写法(可以重命名) html 调用新的名字 {{counterNew}}, {{userInfoNew}},{{conferenceNew}} computed:{...mapState({counterNew:state => state.counter,userInfoNew:state => state.userInfo,conferenceNew:state => state.conference,})}Vue3 用法 setup 函数html 调用新的名字 {{sCounter}}import {mapState, useStore} from 'vue' import {computed} from 'vue'export default { setup(){// setup 函数是没有 this 的,因此这里是不能用 $this.store.state 调用vuex中的变量的const store = useStore; // 拿到 storeconst sCounter = computed(()=>store.state.counter)return {sCounter,}} }
- Getters:就相当于计算属性,就是让 State 里的参数经过一系列变化展示到页面上而不改变参数本身的数据
- Getter 调用: 页面直接显示 getter 中返回的变量 {{$store.getters.doubleCounter}}
- Getter 设置
daican(state) { //带参数返回一个带参数的函数即可return data => {return state.counter * data;}},ageMoreThan(state) { //返回年纪大于 age 的学生return age => {return state.students.filter(s => s.age >= age);}},ageMoreThanLength(age, getters) { //返回年纪大于 data 的学生的数量//这里涉及到getter 函数之间是如何调用的return age => {return getters.ageMoreThan(age).length;}}
Getter 调用 : {{$store.getters.daican(5)}} //带参数的
getter 里的方法如果在某一个页面想要直接调用 {{daican(5)}}{{别名1(5)}},可以在调用的页面如此引用
import {mapGetters} from "vuex" (mapGetter 辅助函数)
然后在 computed 中写
...mapGetters(['daican','ageMoreThan']);//调用哪个写哪个
或者 ...mapGetters({别名1:'daican', 别名2:'ageMoreThan'}); - Mutation: Vue Store 状态唯一的更新方式
Vue 要求我们在 mutation 中的方法必须是同步方法 主要的原因是当我们使用追踪插件的时候用异步方法会失效。 也就是说有网络请求的时候不能在 mutation 中写
更新变量的时候一定要在这里更新,在外面是能直接更新但是一旦在外面更新 vue 自带的追踪插件就会失效,程序小还可以,大型项目中就很不利于调试了。- Mutation 设置 : 这里的 state 是自动获取的,买个 mutation 函数都带这个默认的参数
increaseCounter(state) { state.counter++;}
Mutation 调用: this.$store.commit('increaseCounter'); - Mutation 设置 : 传参数 num
decreaseCounter(state, num) {state.counter -= num;},
Mutation 调用: this.$store.commit('decreaseCounter', 3); - Mutation 设置 : 传参数 payload 对象
decreaseCounter1(state, payload) { state.counter -= payload.num;},
Mutation 调用 (另外一种调用方法): this.$store.commit({ type:"decreaseCounter1", num: 3 }); - Mutation 设置: 给对象响应式的添加属性
addProp(state) { state.info = { ...state.info, 'newProp': 1 }}
mutations-type.js- 在 mutation 定义了很多时间类型:也就是方法名称
- 项目越来越大的时候,方法越来越多,所以可以创建一个 mutations-type.js 在单独管理 mutations 中的方法名
- 使用方式:
mutations-type.js 中写: export const INCREASECOUNTER = 'increaseCounter'
然后 store/index.js 中要引入: import {INCREASECOUNTER} from "./mutations-type.js"
原来的方法: increaseCounter(state) {} 现在就变成了 [INCREASECOUNTER](state) {},
这里需要了解的知识是一个方法可以有这样两种书写方式 a(){} 和 ['a'](){}
前端页面调用方法的时候就这样写: this.$store.commit(INCREASECOUNTER);
- mutations 可以自己单出来一个 js 文件
- 如果有 mutations-type.js, 就先引入 import {想要引入的变量名1, 变量名2....} from "./mutations-type.js"
- export default { 里面是各种方法}
- index.js 中写 import mutations from './mutations.js'
- Mutation 设置 : 这里的 state 是自动获取的,买个 mutation 函数都带这个默认的参数
- Action: Action 类似于 mutation, 它是用来代替 mutation 进行异步操作的;如网络请求
或者说一些复杂的逻辑也是在 Action 里写,尽量让 mutation 只执行最简单的操作,不涉及到任何逻辑判断 - Action 设置: content参数代表上下文,每个 action 都带这个默认参数
-
-
addPropTimeOut(content) { setTimeout(() => {content.commit('addProp'); //action 只调用异步,真正修改对象的值还是得像这样调用 mutation 中的方法}, 3000);},
Action 调用 :this.$store.dispatch('addPropTimeOut'); - Action 设置:返回 new Promise
addPropTimeOutWithPromise(content) { return new Promise((resolve, reject) => {setTimeout(() => {content.commit('addProp');resolve("往外带参数外面的 res 来接这个参数"); //Promise 成功后执行}, 3000);})},
Action 调用:带参数 this.$store.dispatch('addPropTimeOutWithPromise').then(res =>{console.log(res, "new Promise");}); - Action 设置
addPropTimeOutWithParas(content, payload) { setTimeout(() => {content.commit('addProp');}, payload);},
Action 调用 this.$store.dispatch('addPropTimeOutWithParas', 1000); - Action 设置:带参数,参数是一个对象
addPropTimeOutWithCallback(content, payload) { setTimeout(() => {content.commit('addProp');console.log(payload.message);payload.success();}, 3000);}
Action 调用:this.$store.dispatch('addPropTimeOutWithCallback', { message:"携带的参数", success:() => {console.log('属性添加完毕')} });
actions 函数的另外一个调用方式:辅助函数
在想要调用的文件中 import { mapActions } from 'vuex'
methods:{
...mapActions(['addToCart']), //mapActions 辅助函数,直接用 vueX 中 Action 的函数
addGood(good) {
this.addToCart(good);
},
} -
- Module: 模块, 当 应用非常复杂的时候,所有东西都存在一个 store 里不方便管理。 此时 Vuex 允许我们将 store 对象分割成模块,每个模块有自己的 state,mutation,action, getter 等
这里的 action、mutation 和 getter 是注册在全局的,因此调用方式都是一样的,并且是不能重名的。
state 是可以重名的- 前台调用 module a 中的 state : {{$store.state.a.counter}}
- module a 中的 getters 中的 方法调用 root store 中的 State
fullName3(statem getters, rootState){return getter.fullname2 + rootState.counter}//这里的 fullname2 是本 module 中 getter 中的方法
- module a 中的 Actions 中的方法调用 root store 中的 State
incrementRoom({state, commit, rootState}){if(state.count + rootState.count > 10) {commit('increment')}}
- 等 action, getter, mutation 等都变成单独的文件之后
index.js 中的 写法就特别简单了,先各自引入,然后const state = { ...//state 不要自己写单独的文件,直接提出来单独的对象即可}const store = new Vuex.Store({state,mutations,actions,getters,modules: {a : moduleA,} });
这篇关于Tracy 小笔记 Vue - Vuex的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!