vuejs全家桶之vuex

什么是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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值