数据共享:VueX学习

举报
Studying-swz 发表于 2022/10/16 20:19:21 2022/10/16
【摘要】 1.Vuex是干什么的?本质:多个界面一起管理某些数据它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。有什么状态时需要我们在多个组件间共享的呢?如果你做过大型开放,你一定遇到过多个...

1.Vuex是干什么的?

本质:多个界面一起管理某些数据

  • 它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
  • Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
  • 有什么状态时需要我们在多个组件间共享的呢?如果你做过大型开放,你一定遇到过多个状态,在多个界面间的共享问题。比如用户的登录状态、用户名称、头像、地理位置信息等等。比如商品的收藏、购物车中的物品等等。

2.Vuex状态管理图

image.png

  • Vuex的核心概念:State、Mutations、Actions、Getters、Modules
  • State:全局共享变量
  • Mutations:修改State
  • Getter:State的变异值(如平方、+10、-10等)
  • Actions:异步修改State,类似于Mutations
  • Modules:模块化

3.Vuex入门案例

  • 安装:npm install vuex@3.6.2 -save

  • 实现案例:

    image.png

  • 1.创建store文件夹,创建index.js文件

    import Vue from 'vue'
    import Vuex from 'vuex'
    //1.安装插件
    Vue.use(Vuex)
    
    //2.创建对象
    const store = new Vuex.Store({
        state:{
            counter:100,
            students:[
                {id:110,name:'why',age:18},
                {id:111,name:'kobe',age:24},
                {id:112,name:'james',age:30},
                {id:113,name:'curry',age:10},
            ],
            info:{
                name:"kobe",
                age:40,
                height:1.98
            }
    
        },
         //定义方法,state默认传过来
         //store状态的唯一更新方式
         //异步操作的时候,devtools 检测不到
        mutations: {
            increment(state){
                state.counter++;
            },
            decrement(state){
                state.counter--;
            }
        }
    })
    
    //3.导出store对象
    export default store
    
    
  • 2.挂载到Vue实例(main.js)

    image.png

  • 3.App.vue

    <template>
      <div id="app">
        <h2>----------App内容:state相关信息-----------------</h2>
        <h2>{{message}}</h2>
        <h2>{{$store.state.counter}}</h2>
    
        <!-- <button @click="$store.state.counter++">+</button>
        <button @click="$store.state.counter--">-</button> -->
    
        <button @click="addtion">+</button>
        <button @click="subtraction">-</button>
    
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      components: {
        
      },
      data(){
        return {
          message:"我是App组件",
          counter:0
        }
      },
      methods:{
        addtion(){
          this.$store.commit('incrment')
        },
        subtraction(){
          this.$store.commit('decrement')
        }
      }
    }
    </script>
    
    <style>
    
    </style>
    
    

4.State单一状态树

  • 案例:在国内我们有很多的信息需要被记录,比如上学时的个人档案,工作后的社保记录,公积金记录,结婚后的婚姻信息,以及其他相关的户口、医疗、文凭、房产记录等等(还有很多信息)。这些信息被分散在很多地方进行管理,有一天你需要办某个业务时(比如入户某个城市),你会发现你需要到各个对应的工作地点去打印、盖章各种资料信息,最后到一个地方提交证明你的信息无误。这种保存信息的方案,不仅仅低效,而且不方便管理,以及日后的维护也是一个庞大的工作(需要大量的各个部门的人力来维护,当然国家目前已经在完善我们的这个系统了)。
  • 这个和我们在应用开发中比较类似:如果你的状态信息是保存到多个Store对象中的,那么之后的管理和维护等等都会变得特别困难。
  • 所以Vuex也使用了单一状态树来管理应用层级的全部状态。单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。
  • 使用:参考基本案例。

5.Getters的基本使用

  • 将其放入上面的index.js文件中,主要时原始数据state进一步处理后返回,一些简单的操作:平方、+10 等等

  • 但是这些操作不会改变原来的值,相当于Getters只是copy一份state进行修改,而原来的值不会发生变化,主要通过mutations来修改state的值

  • 默认参数state

         //对于共享数据进一步处理后地数据
    
        getters: {
            powerCounter(state){
                return state.counter * state.counter;
            },
            more20stu(state){
                return state.students.filter(s => s.age>20 )
            },
            more20stuLength(state,getters){
                return getters.more20stu.length;
            },
            moreAgestu(state){
                // return function(age){
                //     return state.students.filter(s => s.age>age )
                // }
    
                return age =>{
                    return state.students.filter(s => s.age>age )
                }
            },
        },
    
  • App中使用如下:

  • 其中moreAgestu可以传递参数,这时候getters需要利用函数处理

        <h2>-----------App内容:getters相关信息</h2>
        <h2>{{$store.getters.powerCounter}}</h2>
        <h2>{{$store.getters.more20stu}}</h2>
        <h2>{{$store.getters.more20stuLength}}</h2>
        <h2>{{$store.getters.moreAgestu(12)}}</h2>
    

6.Mutations的基本使用

  • Vue中store状态的更新唯一方式:Mutations

  • 1.参数传递

  • 其中updateInfo函数可以实现State数据实时变化(包括添加对象、删除对象等)

  • index.js

       mutations: {
            increment(state){
                state.counter++;
            },
            decrement(state){
                state.counter--;
            },
            incrementCount(state,count){
                state.counter += count
            },
            addStudent(state,stu){
                state.students.push(stu)
            },
            updateInfo(state){
                //state.info.name = 'codewhy'
                //state.info['address'] = '洛杉矶' //自动拼接 
                //Vue.set(state.info,'address','洛杉矶')
    
                //Vue.delete(state.info,'age')
    
            }
        },
    
  • App.vue

     methods:{
        addtion(){
          this.$store.commit('increment')
        },
        subtraction(){
          this.$store.commit('decrement')
        },
        addCount(count){
          //payload:负载
          //1.普通的提交风格
          this.$store.commit('incrementCount',count)
    
          //2.特殊的提交风格--感觉这个有点麻烦
          // this.$store.commit(
          //   {
          //     type:'incrementCount',
          //     count:count
          //   }
          // )
        },
        addStudent(){
          const stu = {id:115,name:'ale',age:30}
          this.$store.commit('addStudent',stu)
        },
        updateInfo(){
          this.$store.commit('updateInfo');
        }
     }
    
  • 2.常量

    • 在mutation中, 我们定义了很多事件类型(也就是其中的方法名称).

    • 当我们的项目增大时, Vuex管理的状态越来越多, 需要更新状态的情况越来越多, 那么意味着Mutation中的方法越来越多.

    • 方法过多, 使用者需要花费大量的经历去记住这些方法, 甚至是多个文件间来回切换, 查看方法名称, 甚至如果不是复制的时候, 可能还会出现写错的情况.

      1. 创建文件mutations-types.js
        image.png
    • 2.编写(这里只写了一个常量为例子)

      image.png

    • 3.index.js中导入

      image.png

    • 4.App.vue引入如下

      image.png

    • 5.mutation引入如下

      image.png

  • 3.Mutations的响应规则

    • Vue的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新.
  • 4.Mutations的监控规则

    • 当我们使用devtools时, 可以devtools可以帮助我们捕捉mutation的快照.
    • 但是如果是异步操作, 那么devtools将不能很好的追踪这个操作什么时候会被完成.
    • 安装的话:谷歌商城下载插件
      image.png

7.Actions的基本使用

  • 我们强调, 不要再Mutation中进行异步操作.

  • 但是某些情况, 我们确实希望在Vuex中进行一些异步操作, 比如网络请求, 必然是异步的.

  • 这个时候怎么处理呢? Action类似于Mutation, 但是是用来代替Mutation进行异步操作的.

  • 使用方法:dispatch函数,之前的mutations是commit方法

    image.png

  • 参数传递:payload传递(mutations的第二种参数传递方法)

    image.png

  • 基本案例:
    • App.vue
        updateInfo(){
          //this.$store.commit('updateInfo')
          //this.$store.dispatch('aUpdateInfo','我是payload');
    
          this.$store.dispatch('aUpdateInfo','我是携带的信息').then(res => {
            console.log('里面完成了提交');
            console.log(res);
          })
        },
    
    • index.js
       actions: {
        //解决异步操作的时候,devtools 检测问题
        //context:上下文
        //context==store
    
        // aUpdateInfo(context,payload){
        //     setTimeout(()=>{
        //         context.commit('updateInfo')
        //         console.log(payload);
        //     },1000)
        // }
        
        aUpdateInfo(context,payload){
            return new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    context.commit('updateInfo')
                    console.log(payload);
    
                    resolve('11111111')
                },1000)
            })
           
        }
    },
    
    • 分析:actions是为了解决异步操作的,内部会调用mutations中的方法,通过new Promise可以实现异步调用,并将结果返回给App组件,并且可以实现devtools插件的检测。

8.Modules的基本使用

Module是模块的意思, 为什么在Vuex中我们要使用模块呢?

  • Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理.
  • 当应用变得非常复杂时,store对象就有可能变得相当臃肿.
  • 为了解决这个问题, Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutations、actions、getters等

在index.js文件中,则格式如下:

image.png

需要注意的两点:

  • 1:在模块中的getters使用根模块的state

//2.创建对象
const moduleA = {
    state:{
        name:'zhangsan'
    },
    mutations: {
        updateName(state,payload){
            state.name=payload
        }
    },
    actions: {
        aUpdateName(context){
            setTimeout(()=>{
                context.commit('updateName','wangwu')
            },1000)
        }
    },
    getters: {
        fullname(state){
            return state.name + '1111';
        },
        fullname2(state,getters){
            return getters.fullname + '22222';
        },
        //这里:在模块中使用根模块的state
        //第三个参数rootState
        fullname3(state,getters,rootState){
            return getters.fullname2 + rootState.counter;
        }
    }
}

const store = new Vuex.Store({
    state:{
        counter:100,
        students:[
            {id:110,name:'why',age:18},
            {id:111,name:'kobe',age:24},
            {id:112,name:'james',age:30},
            {id:113,name:'curry',age:10},
        ],
        info:{
            name:"kobe",
            age:40,
            height:1.98
        }
        
    },
     //定义方法,state默认传过来
     //store状态的唯一更新方式
     //异步操作的时候,devtools 检测不到
     mutations: {
        [INCREMENT](state){
            state.counter++;
        },
        decrement(state){
            state.counter--;
        },
        incrementCount(state,count){
            state.counter += count
        },
        addStudent(state,stu){
            state.students.push(stu)
        },
        updateInfo(state){
            //state.info.name = 'codewhy'
            //state.info['address'] = '洛杉矶' //自动拼接 
            //Vue.set(state.info,'address','洛杉矶')

            //Vue.delete(state.info,'age')

        }
    },
    actions: {
        //解决异步操作的时候,devtools 检测问题
        //context:上下文
        //context==store

        // aUpdateInfo(context,payload){
        //     setTimeout(()=>{
        //         context.commit('updateInfo')
        //         console.log(payload);
        //     },1000)
        // }
        
        aUpdateInfo(context,payload){
            return new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    context.commit('updateInfo')
                    console.log(payload);

                    resolve('11111111')
                },1000)
            })
           
        }
    },
    //对于共享数据进一步处理后地数据
    getters: {
        powerCounter(state){
            return state.counter * state.counter;
        },
        more20stu(state){
            return state.students.filter(s => s.age>20 )
        },
        more20stuLength(state,getters){
            return getters.more20stu.length;
        },
        moreAgestu(state){
            // return function(age){
            //     return state.students.filter(s => s.age>age )
            // }

            return age =>{
                return state.students.filter(s => s.age>age )
            }
        },
    },
    modules: {
        a : moduleA
    }
})

  • 2:App.vue如何调用模块中的state、getters、mutations、actions
<template>
  <div id="app">
    <h2>----------App内容:modules-----------------</h2>
    <h2>{{$store.state.a.name}}</h2>
     <button @click="updateName">修改名字</button>

    <h2>----------App内容:modules--getters-----------------</h2>
    <h2>{{$store.getters.fullname}}</h2>
    <h2>{{$store.getters.fullname2}}</h2>
    <h2>{{$store.getters.fullname3}}</h2>
    <button @click="asynUpdateName">异步修改名字</button>

  </div>
</template>


<script>

import {
  INCREMENT
} from './store/mutations-types'
export default {
  name: 'App',
  components: {
  },
  data(){
    return {
      message:"我是App组件",
      counter:0
    }
  },
  methods:{
    addtion(){
      //常量统一--减少错误
      this.$store.commit(INCREMENT)
    },
    subtraction(){
      this.$store.commit('decrement')
    },
    addCount(count){
      //payload:负载
      //1.普通的提交风格
      this.$store.commit('incrementCount',count)
    },

    updateName(){
      this.$store.commit('updateName','lisi')
    },
    asynUpdateName(){
      this.$store.dispatch('aUpdateName')
    }
  }
}
</script>

<style>

</style>

9.Store的项目组织结构

image.png

  • 除了state全部抽取出去,为了方便修改

  • mutations.js

    import {
        INCREMENT
    }from "./mutations-types"
    
    export default {
        [INCREMENT](state){
            state.counter++;
        },
        decrement(state){
            state.counter--;
        },
        incrementCount(state,count){
            state.counter += count
        },
        addStudent(state,stu){
            state.students.push(stu)
        },
        updateInfo(state){
            //state.info.name = 'codewhy'
            //state.info['address'] = '洛杉矶' //自动拼接 
            //Vue.set(state.info,'address','洛杉矶')
    
            //Vue.delete(state.info,'age')
    
        }
    }
    
  • getters.js

    export default {
        powerCounter(state){
            return state.counter * state.counter;
        },
        more20stu(state){
            return state.students.filter(s => s.age>20 )
        },
        more20stuLength(state,getters){
            return getters.more20stu.length;
        },
        moreAgestu(state){
            // return function(age){
            //     return state.students.filter(s => s.age>age )
            // }
    
            return age =>{
                return state.students.filter(s => s.age>age )
            }
        },
    }
    
  • actions.js

    export default {
        //解决异步操作的时候,devtools 检测问题
        //context:上下文
        //context==store
    
        // aUpdateInfo(context,payload){
        //     setTimeout(()=>{
        //         context.commit('updateInfo')
        //         console.log(payload);
        //     },1000)
        // }
    
        aUpdateInfo(context,payload){
            return new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    context.commit('updateInfo')
                    console.log(payload);
    
                    resolve('11111111')
                },1000)
            })
    
        }
    }
    
  • moduleA.js

    export default {
        state:{
            name:'zhangsan'
        },
        mutations: {
            updateName(state,payload){
                state.name=payload
            }
        },
        actions: {
            aUpdateName(context){
                setTimeout(()=>{
                    context.commit('updateName','wangwu')
                },1000)
            }
        },
        getters: {
            fullname(state){
                return state.name + '1111';
            },
            fullname2(state,getters){
                return getters.fullname + '22222';
            },
            fullname3(state,getters,rootState){
                return getters.fullname2 + rootState.counter;
            }
        }
    }   
    
  • index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    import mutations from './mutations'
    import actions from './actions'
    import getters from './getters'
    import moduleA from './modules/moduleA'
    //1.安装插件
    Vue.use(Vuex)
    
    //2.创建对象
    
    const store = new Vuex.Store({
        state:{
            counter:100,
            students:[
                {id:110,name:'why',age:18},
                {id:111,name:'kobe',age:24},
                {id:112,name:'james',age:30},
                {id:113,name:'curry',age:10},
            ],
            info:{
                name:"kobe",
                age:40,
                height:1.98
            }
    
        },
        mutations,
        actions,
        //对于共享数据进一步处理后地数据
        getters,
        modules: {
            a : moduleA
        }
    })
    
    //3.导出store对象
    export default store
    
    
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。