vuex

什么是 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:提供修改参数的 mutations
  • 4:把 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 里面的方法名称定义为常亮

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值