vuex

mac2026-04-11  4

什么是 vuex

官网解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。 划重点: 注意1: vuex 只能在vuejs项目使用 注意2:为 vuejs 项目提供统一的数据仓库(我们可以把vuejs项目中所有的模型数据都统一放置在 vuex,为了解决组件间通信的问题) 注意3:vuex 里面管理的数据是单向的数据流(在操作数据的时候,只能按照一个方向去操作,或者换句话说,我们不能直接的操作数据,需要遵循 vuex 规范才可以操作数据。(看图))。 注意4:提供一个调试的工具,非常方便的查看vuex管理的数据。

为什么要使用 vuex

可以方便组件间的通信问题(重点)可以提供缓存的特性(异步请求)可以很好的做调试

在使用 vux 之前,我们要知道他的数据是怎么修改的

数据存储修改方式

我们用下面这幅图来解释一下:我们提供了一个数据容器(仓库:store),数据(state)全部放在里面,组件要获取数据就从仓库里进行获取,并且如果组件要修改数据的话,要发送一个请求,在仓库里修改,自己不能修改数据

页面数据的改变

我们在上面就说过,不能再组件内修改数据,而是要把它传到仓库里,在仓库里进行修改,我们用下面这幅图来解释一下 1:如果是同步修改数据,就直接 commit ,将要进行的操作和数据都传给 Mutations, 在里面进行数据的修改 2:如果是异步数据修改,则要先发送一个异步请求 dispatch ,然后在 commit ,将要进行的操作和数据传给 mutations,进行数据的修改

vuex 的使用

1:安装 vuex

yarn add vuex

2:引入并且安装(在一个模块化的打包系统中,必须显式地通过 Vue.use() 来安装 Vuex)

import Vuex from 'vuex' Vue.use(Vuex)//安装

3:使用 vuex

1:创建一个仓库2:提供 state(数据)3:提供修改参数的 mutations4:把 store 注册到 vue 实例上,这样我们在所有的组件上都能通过 this.$store 来获取当前的仓库 const store = new Vuex.store({ // state:仓库里面的数据(之前说的模型数据),一般我们叫做 state 状态 state: { //放数据 count: 0 }, mutations: { // 这个对象里面定义对 state 的操作(curd) } }) new Vue({ //把 store 注册到 Vue 实例对象上面。以后在vuejs项目的所有的组件里面我们都可以通过 this.$store 获取到当前的仓库 store, router, render: h => h(App) }).$mount('#app')

这样一个基础的仓库就完成了,以后我们就可以在里面进行数据的操作

我们来用一下这个仓库

在组件中获取数据

在上面创建一个仓库的时候,我们写了一个数据进去(你也可以写其他的或者不写),我们现在就到组件页面上去获取一下它(页面组件一般写在 views 文件夹下,我就在about 组件上改了,当然也可以自己在创建一个页面)

<template> <div class="about"> <h1>This is an about page</h1> <p>我是从仓库中获取的数据:{{ this.$store.state.count }}</p> </div> </template>

接下来我们来操作一下从仓库中获取的数据

操作数据

我们给一个加减按钮,使它可以改变

<template> <div class="about"> <h1>This is an about page</h1> <button @click="deCrease">-</button> //template 里 this 可以不写 <p>我是从仓库中获取的数据:{{ this.$store.state.count }}</p> <button @click="inCrease">+</button> </div> </template>

按照我们之前的做法,就直接在组件中修改

<script> export default { methods: { deCrease: function(){ this.$store.state.count -- }, inCrease: function(){ this.$store.state.count ++ } } } </script>

我们发现这样也能改变页面上的数据,主要是因为我们没有开启 vuex 的严格模式,如果开启了严格模式,是不允许直接修改仓库里面的 state ,并且 vuex 管理思想里面,说了数据的修改必须是通过 commit 进行提交,然后由 mutations 进行数据的修改。

接下来我们就开启一下严格模式(在 仓库的最上面加上:strict:true(默认为false)),然后由 mutations 来修改数据 1:在组件中把要触发的行为和数据传给 nutations

<script> export default { methods: { deCrease: function(){ // this.$store.state.count -- //参数1:在 mutations 中要触发的行为 //参数二:传递的数据 this.$store.commit('deCrease',{ number: 1})//会触发 mutations 里对应的行为 }, inCrease: function(){ this.$store.commit('inCrease',{ number: 10}) } } } </script>

2:在 nutations 里接收从组件传过来的行为和数据,并在这里进行处理

mutations: { //deCrease:就是在单组件中设置的行为 //参数1:仓库里的 state //参数2:单组件中 commit 时传过来的第二个参数(也就是从单组件中传过来的数据) deCrease: function(state,payload){ state.count -- //每次减 1 }, inCrease: function(state,payload){ state.count += payload.number;//每次就加上我们传过来的数 10 } }

接下来我们去操作一下异步数据

操作异步数据

1:在要获取数据(异步)的组件里

<script> export default { methods: { getData: function(){ //自己不要做,告诉仓库,让仓库来做 //异步的话就要用 dispatch 来派发 this.$store.dispatch('getData'); } } } </script>

2:异步操作数据写在 actions 里,同步操作写在 mutations 里

actions: { //参数1:仓库对象 //参数2:组件中传过来的参数 getData: function(store,payload){ var url = 'https://movie.52kfw.cn/index.php/Api/Movie/alst?page=1&size=20' axios.get(url).then((response)=>{ if(response.status === 200 && response.data.error_code === 0){ //把获取的数据 commit ,放到 mutations 里处理(这个时候已经获取到数据,在进行操作就是同步的了) store.commit('saveData'); } }).catch((error)=>{ console.log(error); }) } }

3:到 mutations 里处理异步获取回来的数据,把数据放到仓库里

//在 state 里定义一个属性来接收 saveData: function(state,payload){ state.getData = payload; }

4:将数据在页面上显示,数据已经在仓库了,所以我们只要从仓库里拿数据就好了

<template> <div> <h1>我是列表页</h1> <button @click="getData">获取数据</button> <p>{{ $store.state.getData }}</p> </div> </template>

同步和异步数据怎么操作我们都知道了,现在我们来把代码优化一下

1:

<script> // 需要从 vuex 里面导出一个函数 mapState(作用,可以把仓库里面的state映射到组件的 data 里面,要映射成计算属性才可以) map 映射 State 状态: 把 state 里面的状态隐射到组件的内容使用,减少 this.$store.state import {mapState} from 'vuex'; export default { computed: { //如果 computed 里之前就存在其他属性,可以用展开运算符:... //如果computed 本身就有一个getData,会产生冲突,我们可以给他取一个别名:...mapState({mydata: 'getData'}) ...mapState(['getData']) /* * mapState(['getData']):底层 * count: function(){ return this.$store.state.count; } */ } } </script>

这样我们就可以直接用 getData,而不需要写那么长

既然 state 可以映射,那么我们仓库里的其他属性应该也可以映射 仓库里面的 mutations 映射到组件的 methods 里面,则我们就可以直接修改 state

<script> //仓库里面的 mutations 映射到组件的 methods 里面,则我们就可以直接修改 state,同步用mapMutations,异步用mapActions import {mapState, mapMutations, mapActions} from 'vuex'; export default { name: "list.vue", methods: { ...mapActions(['getData']) // getData: function(){ // //自己不要做,告诉仓库,让他来做 // //异步的话就要用 dispatch 来派发 // this.$store.dispatch('getData'); // } }, computed: { ...mapState(['getData']) /* * mapState(['getData1']):底层 * count: function(){ return this.$store.state.count; } * */ } } </script>

仓库里除了 actions 和 mutations,还有其他操作,我们来看一下 getters

getters 是专门负责数据的过来操作 注意:它的特性是:定义是一个方法,按属性的方法使用

getters: { idMore2: function(state){ return state.getData1.filter(item=>{ return item.id>2 }) } }

缓存

网络请求,完全可以做个内存缓存,先去检测仓库里面是否存在数据,如果存在,则不发送网络请求;不存在发送 后台,肯定上缓存 memcache redis 内存缓存 io 》》》 磁盘IO mysql

//在我们要发送异步请求的地方 if( store.state.movieData.length > 0 ){ // 代表用户之前肯定点击获取电影,发送过网络请求 console.log('数据来自缓存信息!'); return; }

由于网络请求所耗费的时间是不确定,意味用户等待的时长也是不确定,为了防止乱点击,烦躁。一般在发送网络请求后,会在页面上出一个 loading的效果。数据成功回来后,loading消失。

1 :在页面组件上 放置一个 loading 效果 loading 和 下面的列表展示是互斥的。 硬币的投掷就是一个互斥事件;一个事情存在正反两面,如果正发生,发面一定不会发生;如果发面发生了,正面一定不会发生

<div class="loading" v-if="flag"> <span></span> <span></span> <span></span> <span></span> <span></span> </div> <ul v-else v-for="ele in movieData"> <li>序号:{{ ele.id }}</li> <li>名称:{{ ele.title }}</li> <li>收藏数:{{ ele.star }}</li> </ul>

2:在 state 里定义 flag,默认为false 3:修改状态

store.commit('modifyFlag', true);//在还没有数据的时候为 true

4:在 actions 里定义modifyFlage 的操作 5:当数据来了,将其改为true

单一 store

将 main.js 里关于store 的操作放到另一个文件夹内,并导出(export default store) 在需要的地方引入:import store from ‘./store’

常量表

将仓库中的 actions,mutations 等行为定义为常量

1:在当前文件夹下创建一个 constant.js 文件

export const INCREMENT = 'inCrement' export const DECREMENT = 'deCrement'

2:在需要的地方导入

import {INCREMENT, DECREMENT} from './constant'

3:将对应的变量替换成常量 注:在 vuex 里尽可能吧 actions 和 mutations 里面的方法名称定义为常亮

最新回复(0)