vuex 的使用

xiaoxiao2021-02-28  49

参考官方文档 https://vuex.vuejs.org/zh-cn/

Vuex 是什么?

官方是这么解释的: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态, 并以相应的规则保证状态以一种可预测的方式发生变化。 Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、 状态快照导入导出等高级调试功能。 读完了,你发现,这说的啥啊?完全没有看懂啊? 好吧!那就简单总结一句话,vuex就是处理vue中组件之间通信的 有了这个,你再也不用烦恼vue跨组件通信了。 因为Vuex里的数据都是响应式的,任何组件使用同一store的数据, 只要store的数据变化,与之对应的组件都会立即变化

安装

npm安装 npm install vuex --save CDN https://unpkg.com/vuex 这种方式引入的话,要放在vue.js后边 <script src="/path/to/vue.js"></script> <script src="/path/to/vuex.js"></script> 装好后怎么使用它? 首先在src目录下建立一个store文件,再这个文件夹下新建一个index.js,打开index.js

写入代码:

import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ }) 或者 const store = new Vuex.Store({ }) export default store

在main.js引入这个文件

// index.js创建完毕然后打开main.js import Vue from 'vue' import App from './App' // 引入store文件下的index.js,如果你是index.js文件 // 引入的时候可以省略index.js,若是其它文件名.js请全部引入 // 比如:import store from './store/store.js' import store from './store' new Vue({ el: '#app', store, // 然后再这里使用一下 components: { App }, template: '<App/>' })

下边介绍核心概念就4个

State Getter Mutation Action 废话不多说,啥意思看官方解释,这里只说怎么用

State

state干啥的,官方解释一大堆,看完了我也觉得懵逼,这是啥啊? 其实state简单理解就是存储数据的,相当于我们的.vue文件里的data里造数据差不多

打开store文件下的index.js

import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state:{ //这里我们创建个数组 foodlist:[ {name:'大米',price:20,count:5}, {name:'鸡腿',price:10,count:8}, {name:'沙拉',price:5,count:10}, {name:'土豆',price:13,count:2} ] } })

准备两个组件(名字你随意啊) Header.vue

// 在Header.vue中拿到存在state里的数据然后渲染在页面中 // 1.直接使用$store.state.foodlist获取state里的数据(你在state里定义的是什么名字就用什么名字) <template> <div class="header"> <span>食物</span> <span>价格</span> <span>数量</span> <ul> <li v-for="(food,index) in list" :key="index"> {{food.name}}———{{food.price}}————{{food.count}} </li> </ul> </div> </template> <script> export default { data(){ return{ list:this.$store.state.foodlist } } }; </script> <style scoped> span{ margin-left: 40px; } .header { width: 600px; height: 200px; margin-left: 50px; border: 1px solid #000; background-color: antiquewhite; } </style>

Foot.vue

<template> <div class="foot"> <span>食物</span> <span>价格</span> <span>数量</span> <ul> <li v-for="(food,index) in list" :key="index"> {{food.name}}———{{food.price}}————{{food.count}} </li> </ul> </div> </template> <script> export default { data(){ return{ list:this.$store.state.foodlist } } }; </script> <style scoped> span{ margin-left: 40px; } .foot { width: 600px; height: 200px; margin-left: 50px; background-color: azure; border: 1px solid #000; margin-top: 50px; } </style> 使用了$store 两个组件的数据是不是一毛一样!这时候不同的组件就都拿到了数据 后边的3个方法就只用一个组件测试了!其它组件用法都一样的

改写header.vue

// 上边这种方法虽然也可以拿到数据,但官方推荐使用计算属性的方式获取数据 <template> <div class="foot"> <span>食物</span> <span>价格</span> <span>数量</span> <ul> <li v-for="(food,index) in getList" :key="index"> {{food.name}}———{{food.price}}————{{food.count}} </li> </ul> </div> </template> <script> export default { computed:{ // 定义一个方法,return 你的数据 getList(){ return this.$store.state.foodlist; } } }; </script>

Mutation

这里不先说getter,因为很好明白,state存数据,那getter看名字就知道是取数据,因为已经有$store.state可以 取到数据了,我们等会说getter,这里我们说改变数据,在组件内,来自store的数据只能读取,那我们肯定想怎么改 state里的数据,而修改store里的数据的唯一途径就是显示的提交mutation,啥意思啊!看不懂最后一句,没有关系, 我们知道你有改数据的需求的地方,只会在某一个组件内,而你不可能手动去store里改,因为state里的数据都是接口 请求下来的,那么怎么改呢,我们需要用$store.commit(),官方解释的这个方法是在组件内向store里显示提交mutation 说白了,就是在你的mutation里先定义好了一个操作state里的数据的方法,然后在你的组件里调一下你定义 ----------------------------------------------------- 在mutation里那个的方法名,不过需要注意的是mutation里的方法不推荐进行异步操作,这个我们等会说 -----------------------------------

打开store的js文件

import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state:{ //这里我们创建个数组 foodlist:[ {name:'大米',price:20,count:5}, {name:'鸡腿',price:10,count:8}, {name:'沙拉',price:5,count:10}, {name:'土豆',price:13,count:2} ] }, mutations:{ // 定义一个增加价格的方法 addPrice(state){ // 先遍历数组,获取到价格属性 state.foodlist.forEach(e => { //这里得到每一个对象 //console.log(e) e.price +=5; //每次点击+5 }); } } })

Header.vue文件中调用

// 准备一个点击事件(样式代码就不贴了) <template> <div class="foot"> <span>食物</span> <span>价格</span> <span>数量</span> <ul> <li v-for="(food,index) in getList" :key="index"> {{food.name}}———{{food.price}}————{{food.count}} </li> </ul> //按钮点击事件 <button @click="add">点击加5</button> </div> </template> <script> export default { computed:{ getList(){ return this.$store.state.foodlist; } }, methods:{ add(){ // 这里调用你定义的增加价格的方法 this.$store.commit('addPrice') } } }; </script>

有装vue-devtools插件的看的很清楚贴个图

// 这里也是接受传参的,修改代码传个参数5 <script> export default { computed:{ getList(){ return this.$store.state.foodlist; } }, methods:{ add(){ this.$store.commit('addPrice',5) } } }; </script>

store里的js

// mutation 默认接收的第一个参数就是state mutations:{ // 定义一个增加价格的方法 addPrice(state,num){ // 先遍历数组,获取到价格属性 state.foodlist.forEach(e => { //这里得到每一个对象 //console.log(e) e.price +=num; //每次点击+5 }); } }


mutation 异步操作出现的问题

上边说过,mutation里的方法不推荐进行异步操作,那会出现什么问题, 这里我们用延时模拟个异步,我们点击按钮进行+5的操作,2秒后让页面数据改变

打开store下的js文件

// 模拟延时2秒 mutations:{ // 定义一个增加价格的方法 addPrice(state,num){ // 先遍历数组,获取到价格属性 state.foodlist.forEach(e => { setTimeout(function(){ e.price +=num; },2000) //延时2秒 }); } } 这时候你在页面中点击按钮一次,过了两秒,数据改变了,当你连点时,你会发现你都不点了,数据还在页面中慢慢变化, 这显然不是我们想要的,这时候你打开控制台,你会看到方法都执行了,数据还没有变化,知道运行到最后一次执行的时 候,数据才变化完,这个时候我们就要用另一个属性了action


Action

action和muation很像,只不过不同的是action里提交的mutation,啥意思? 就是在action属性里调用的是mutation里的方法,而且只能对mutation进行操作

打开store下的js文件

// 添加action属性 import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state:{ //这里我们创建个数组 foodlist:[ {name:'大米',price:20,count:5}, {name:'鸡腿',price:10,count:8}, {name:'沙拉',price:5,count:10}, {name:'土豆',price:13,count:2} ] }, mutations:{ // 定义一个增加价格的方法 addPrice(state,num){ // 先遍历数组,获取到价格属性 state.foodlist.forEach(e => { //这里得到每一个对象 //console.log(e) e.price +=num; //每次点击+5 }); } }, actions:{ Moniyibu(context){ console.log(context) setTimeout(function(){ context.commit('addPrice',5) },2000) } } })

header.vue中

// 在组件内触发 action 里的方法,只能通过$store.dispatch 来触发 <template> <div class="foot"> <span>食物</span> <span>价格</span> <span>数量</span> <ul> <li v-for="(food,index) in getfood" :key="index"> {{food.name}}———{{food.price}}————{{food.count}} </li> </ul> <button @click="add">+</button> </div> </template> <script> export default { computed:{ getList(){ return this.$store.state.foodlist; }, getfood(){ return this.$store.getters.getfoodName } }, methods:{ add(){ // 触发action的方法Moniyibu this.$store.dispatch('Moniyibu',5) } } }; 这时候你再查看那个控制台,你会发现,点击按钮,2秒钟后方法才执行

Getter

该说的都说了,最后来说下getter,上边说了,getter也是获取数据的,但它里边的数据通常都是处理过的数据 比如有这样一个需求,我们获取state里食物价格大于10的数据

打开store下的js文件

import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state:{ //这里我们创建个数组 foodlist:[ {name:'大米',price:20,count:5}, {name:'鸡腿',price:10,count:8}, {name:'沙拉',price:5,count:10}, {name:'土豆',price:13,count:2} ] }, // getters 使用 getters:{ // 获取价格大于10的数据 getfoodName:state =>{ /** * filter 过滤,会根据你的判端条件进行筛选,把满足条件的数据返回组成一个新的数组, * 这里要把这个数组再return 回去,你也可以定一个变量接收这个新数组,然后return这个变量 */ return state.foodlist.filter(foodname =>{ //获取每一条对象 console.log(foodname) // 返回每条数据价格大于10的数据 return foodname.price > 10 }) } }, mutations:{ // 定义一个增加价格的方法 addPrice(state,num){ // 先遍历数组,获取到价格属性 state.foodlist.forEach(e => { //这里得到每一个对象 //console.log(e) e.price +=num; //每次点击+5 }); } } })

Header.vue中获取getter里的数据

// 依旧写在计算属性里 使用 $store.getters.getter里的方法名 <template> <div class="foot"> <span>食物</span> <span>价格</span> <span>数量</span> <ul> <li v-for="(food,index) in getfood" :key="index"> {{food.name}}———{{food.price}}————{{food.count}} </li> </ul> <button @click="add">+</button> </div> </template> <script> export default { computed:{ getList(){ return this.$store.state.foodlist; }, getfood(){ return this.$store.getters.getfoodName } }, methods:{ add(){ this.$store.commit('addPrice',5) } } }; </script> 还有一个module没有说,这个先暂时不说了,看下文档就懂了,接下来说下怎么通过调接口的方式把数据存到store里边, 这里我们mock下数据https://www.easy-mock.com/注册账号后进入:

然后找个get请求:

点击编辑接口数据:这里用这个测试了哈! https://www.easy-mock.com/mock/5ae4909f24b57d1001c9c190/test

打开main.js

//main.js 引入axios 这里就不配置baseurl了 import Vue from 'vue' import App from './App' import store from './store' import axios from 'axios' Vue.prototype.$http = axios /* eslint-disable no-new */ new Vue({ el: '#app', store, components: { App }, template: '<App/>' })

Header.vue

// 在created钩子里调接口 <script> export default { created(){ this.$http.get('https://www.easy-mock.com/mock/5ae4909f24b57d1001c9c190/test').then(res => { if(res.status==200){ console.log(res.data.foodlist) // 通过 提交mutation 将接口返回的数据作为参数传给mutation this.$store.commit('getApi',res.data.foodlist) } }) }, }; </script>

在store的js里接收参数

import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) // 通过getApi这个方法 就把接口数据 拿到了,然后再进行赋值 export default new Vuex.Store({ state:{ //这里我们创建个数组 foodlist:[] }, mutations:{ // 得到接口数据 getApi(state,payload){ // 进行赋值 state.foodlist = payload; } }, actions:{ Moniyibu(context){ console.log(context) setTimeout(function(){ context.commit('addPrice',5) },2000) } } })
转载请注明原文地址: https://www.6miu.com/read-2629562.html

最新回复(0)