vuejs全家桶之vuex

mac2026-03-14  4

什么是vuex?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。 总结一下上面官方给出的解释:

注意1: vuex 只能在vuejs项目使用 注意2:为 vuejs 项目提供统一的数据仓库(我们可以把vuejs项目中所有的模型数据都统一放置在 vuex,为了解决组件间通信的问题) 注意3:vuex 里面管理的数据是单向的数据流(在操作数据的时候,只能按照一个方向去操作,或者换句话说,我们不能直接的操作数据,需要遵循 vuex 规范才可以操作数据。 注意4:提供一个调试的工具,非常方便的查看vuex管理的数据。

vuex状态管理思想

为什么要使用vuex?

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

同步修改数据和异步修改数据

vuex的使用

1, vuex 只能在vuejs项目使用,所以我们用vue-cli这个脚手架快速构建一个vue项目

yarn add @vue/cli npx vue create myapp

2,下载vuex,并在项目的main.js文件中导入并使用

import Vuex from 'vuex' Vue.use(Vuex)

3,(1)创建一个仓库(store)(2)提供state(3)提供修改数据的mutation

const store = new Vuex.Store({ state: { count: 0, }, mutations: { },

(4)注册store

new Vue({ //store在这里注册,然后渲染到页面上 store, router, render: h => h(App) }).$mount('#app')

4,同步修改数据 (1)在App.vue主组件中的template中,先写一个按钮组,并定义点击事件,加减操作span里面的数据,这里是定义页面触发行为,然后创建一个生命周期函数,然后将函数导出 (2)在生命周期函数里面的methods中提交(commit)加减函数到mutation中 (3)在store的mutation中,定义加减函数应该进行什么操作(修改state),然后渲染页面 (4)将仓库里的state映射到组件的data里面(需要映射成计算属性才行)

<1> 在App.vue中引入mapState import { mapState} from ‘vuex’; <2>然后在computed里面映射 …mapState({countAias: ‘count’,movieData:‘movieData’}) <3>底层原理 countAias:function(){ return this.$store.state.count }

(5)把仓库里面的mutations映射到组件中的methods

<1> 在App.vue中引入mapMutations import { mapState,mapMutations} from ‘vuex’; <2>然后在methods里面映射 …mapMutations([‘increment’,‘decrement’]), <3>底层原理 increment:function () { this.KaTeX parse error: Expected 'EOF', got '}' at position 31: …ncrement') }̲, decrement:fun…store.commit(‘decrement’) }

5,异步修改数据

(1)在App.vue中定义页面触发行为 (2)页面触发行为,dispatch(分发)在store中的action,在action中完成异步操作,去向服务器请求数据 (3)action请求完成以后,将响应回来的数据commit到mutation中 (4)然后将请求回来的数据保存下来,所以这里向action操作完了之后,要commit action 和payload (5)我们希望仓库帮我们管理数据,保存数据到仓库 (6)将在仓库里面的数据映射到data里 …mapState({countAias: ‘count’,movieData:‘movieData’}) (7)将action映射到methods里面

…mapActions({clickHandler:‘getMovie’}), 底层原理 clickHandler:function(){ this.$store.dispatch(‘getMovie’) },

(8)App.vue的template中渲染

(9)筛选(getters专门负责对数据的筛选过滤操作)

<1>在store 中定义一个getter,这里定义是一个方法,按照属性方式使用,和计算属性一样 <2>定义一个方法,筛选信息,将信息返回到页面中 <3>将getters映射到computed中 import {mapState, mapMutations, mapActions, mapGetters} from ‘vuex’; …mapGetters([‘returnStarBig12w’])

(10)vuex的缓存特性

<1>当第一次向服务器发送网络请求是,浏览器会对数据进行缓存,我们已经有了数据,但是在这里第二次第三次还是会向服务器请求数据,这样太耗费性能 <2> 我们可以在向服务器发送网络请求前,判断一下仓库里面有没有数据,如果没有,发送网络请求,如果有,则不发送

(11)loading效果

由于网络请求所耗费的时间是不确定,意味用户等待的时长也是不确定,为了防止乱点击,烦躁。一般在发送网络请求后,会在页面上出一个 loading的效果。数据成功回来后,loading消失。 1. loading.gif 2. 插件 3. css3 loading 效果 <1>我用css3loading效果,先在App.vue中放置html,和样式 <2>因为loading和数据是互斥的,所以我们分别给他们两个加上v-if=“flag”,v-else <3>我们让flag映射到data里面 …mapState({countAias: ‘count’,movieData:‘movieData’,flag:‘flag’}), <4>在action中,还没有网络请求的时候进行提交commit,payload默认为true,也就是loading是默认显示的 store.commit(‘modifyFlag’, true); <5>在mutation中关于modifyFlag进行操作 <6>在已经请求回来数据时(savemovieData),将flag改为false

(12)调试

store:

import Vue from "vue"; import Vuex from "vuex"; import axios from "axios"; Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0, //异步修改数据第二步:因为我们希望仓库来帮我们管理接口数据,所以我在这里放一个电影列表的容器,待会我把数据请求回来了就放在这里,这一步做完了之后,我们让页面触发一个行为,dispatch movieData:[] }, //mutation接收到提交过来的行为和载荷,操作仓库里的数据state mutations: { //store里面有一个state数据,这是一个对象,对象里面含有count数据 //当点击加号的时候,count=count+payload increment (state) { state.count += 1 }, //store里面有一个state数据,这是一个对象,对象里面含有count数据 //当点击加号的时候,count=count+payload decrement (state) { state.count -= 1 }, //异步修改数据第五步:保存数据到仓库,state 是数据 saveMovie(state,payload){ state.movieData=payload state.flag=false }, modifyFlag:function(state,payload){ state.flag=payload } }, //异步修改数据第四步:action向服务器端请求数据,然后将请求回来的数据保存下来,所以这里向action操作完了之后,要commit action 和payload actions:{ getMovie:function(store, payload){ var url='https://movie.52kfw.cn/index.php/Api/Movie/alst?page=1&size=20' //当第一次向服务器发送网络请求是,浏览器会对数据进行缓存,我们已经有了数据,但是在这里第二次第三次还是会向服务器请求数据,这样太耗费性能 // 我们可以在向服务器发送网络请求前,判断一下仓库里面有没有数据,如果没有,发送网络请求,如果有,则不发送 if(store.state.movieData.length>0){ console.log('数据来自缓存!') return } //loading store.commit('modifyFlag', true); axios.get(url).then(response=>{ console.log(response) if(response.status=== 200 && response.data.error_code===0){ //这里的保存数据的操作是对数据库进行操作,只有mutation才可以操作数据库,所以saveMovie这个方法要写在mutation当中 store.commit('saveMovie',response.data.result) } }) } }, getters:{ returnStarBig12w:function(state){ console.log(state) return state.movieData.filter(item =>{ return item.star>=120000; }) } } }) export default store;

App.use:

<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </div> <button @click="decrement">-</button> <span>{{ countAias }}</span> <button @click="increment">+</button> <button @click="clickHandler">获取电影列表</button> <div class="loading" v-if="flag"> <span></span> <span></span> <span></span> <span></span> <span></span> </div> <ul v-for="ele in movieData" v-else> <li>{{ ele.id }}</li> <li>{{ ele.actors}}</li> <li>{{ ele.title}}</li> </ul> <h2>收藏数大于12w</h2> <ul v-for="ele in returnStarBig12w"> <li>{{ ele.id }}</li> <li>{{ ele.actors}}</li> <li>{{ ele.title}}</li> </ul> <router-view/> </div> </template> <script> //可以将仓库里的state映射到组件的data里面(好处:不用写this.$store.state.count这么一大串了),但是需要映射成计算属性才行 //可以将仓库中的mutations(只能通过这个来修改仓库中的数据)映射到组件的method里面 import { mapState,mapMutations,mapActions,mapGetters} from 'vuex'; export default { //数据初始阶段就开始了 created:function() { console.log(this.$store); }, computed:{ //将仓库里的state里的count和movieData映射到组件的data里面 ...mapState({countAias: 'count',movieData:'movieData',flag:'flag'}), ...mapGetters(['returnStarBig12w']) //上面这句话的底层原理就是下面这个函数,相当于返回了仓库里的count,好处:1,简洁,2防止重名可以用对象的方式重命名 // countAias:function(){ // return this.$store.state.count // } }, methods:{ //把仓库里面的mutations映射到组件中的methods中 ...mapMutations(['increment','decrement']), //上面这句话的底层原理如下 //点击网页上的按钮,页面触发一个改变数据的行为,直接使用commit向mutation提交action和payload // increment:function () { // this.$store.commit('increment',10) // }, // decrement:function () { // this.$store.commit('decrement',10) // } ...mapActions({clickHandler:'getMovie'}), //异步修改数据第三步:页面触发一个请求数据的行为,页面dispatch这个行为(action),然后action向服务器端请求数据 // clickHandler:function(){ // this.$store.dispatch('getMovie') // }, } } </script> <style lang="less"> ul{ li{ list-style: none; } } #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } #nav { padding: 30px; a { font-weight: bold; color: #2c3e50; &.router-link-exact-active { color: #42b983; } } } .loading{ width: 80px; height: 40px; margin: 0 auto; margin-top:100px; } .loading span{ display: inline-block; width: 8px; height: 100%; border-radius: 4px; background: lightgreen; -webkit-animation: load 1s ease infinite; } @-webkit-keyframes load{ 0%,100%{ height: 40px; background: lightgreen; } 50%{ height: 70px; margin: -15px 0; background: lightblue; } } .loading span:nth-child(2){ -webkit-animation-delay:0.2s; } .loading span:nth-child(3){ -webkit-animation-delay:0.4s; } .loading span:nth-child(4){ -webkit-animation-delay:0.6s; } .loading span:nth-child(5){ -webkit-animation-delay:0.8s; } </style>
最新回复(0)