周亚博的个人博客

  • 首页
  • 盛夏光年
  • 陪风去荡
  • 布响丸啦
我频繁记录着 因为生活值得
  1. 首页
  2. 盛夏光年
  3. 正文

Vuex

2022-09-06 88点热度 0人点赞 0条评论

一、什么是Vuex

Vuex是vue应用开发的状态管理模式,采用集中式存储管理

注意:

vue2中使用vuex3 npm i vuex@3

vue3中使用vuex4

1、状态管理

如果组件之间的层级过多,组件之间的数据传递变得非常困难,所以需要数据共享

实际上就是将多个组件共享的变量存储在一个对象里边,将对象放在顶层的vue实例之中,实现共享,而且数据发生改变时所有共享数据的页面可以实现响应式的刷新

虽然可以将共享数据添加到vue原型中,也可以实现共享,但是无法实现响应式

2、使用场景

多个组件依赖于同一状态 | 来自不同组件的行为需要变更同一状态

并不是所有的共享数据都需要Vuex,例如父子组件数据共享,通过父子传值已经足够

  • 登陆状态,用户名、头像、地理位置
  • 商品的收藏,购物车中的信息

对于以上的状态,就可以使用Vuex进行保存和管理,实现响应式

二、Vuex的使用

// 安装vuex
npm install vuex --save
// 创建store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

// 将插件挂载到vue实例,必须在store实例化之前挂载
Vue.use(Vuex)
// 创建对象
const store = new Vuex.Store({
    // 保存共享的状态
    state: { num:1 },
    mutations: {
    // 定义修改state的方法,这里默认会把state参数传递过来
    add(state){
      state.num++
    }
    },
    actions: {},
    getters: {},
    modules: {}
})
// 导出store
export default store
// 最后将store挂载到vue实例中,出现$store属性
import store from './store'
new Vue({
    el: '#app',
    store,
    render: h=>(App)
})

img

工作原理分析

注意:

  • 不建议直接修改state中的共享数据@click="$store.state.num++",通过Mutation修改才能使用devtools进行修改的记录监听,但是devtools工具只能跟踪同步操作,所以异步操作要在action中进行

  • 修改步骤:store.dispatch('action中的方法名', 数据)

    ​store.commit('mutations中的方法名', 数据)

    如果没有其他业务逻辑,可以直接越过action,直接进行commit

三、state

state单一状态树概念:将所有需要管理的信息全部放到一个store之中进行管理,使用一个状态树管理应用层级的全部状态,能够直接地访问到某个状态的片段。

而放到多个store之中,维护会变得非常困难

state: { 
    num:1,
    age: [19,44,12,7,34],
    info: {
        name: 'zhou',
        age: 20
    }
}

// 使用
<p>{{$store.state.num}}</p>

>将state中的内容导入到组件计算属性之中使用:

1、可以将数据配置在计算属性之中,模板中可以直接使用num
computed:{
    num(){
        this.store.state.num
    }
}
2、使用mapState自动生成    {计算属性名: state中的值}
import {mapState} from 'vuex'
computed:{
    // 返回结果是一个计算属性组成的对象(计算属性名和state属性名可以不一样)
    ...mapState({sum:'sum'})
}
3、使用数组写法,意味着生成的计算属性名和state中的属性名一致
computed:{
    ...mapState(['sum'])
}

// mapState实际上是将数据赋值给了vue对象一份
// 可以通过this.store.state.num修改数据
// 不能通过this.num修改数据

四、getters

类似计算属性,对数据进行处理,收到一个参数state

getters: {
    newNum(state){
        return state.num+=1
    },
    // 可以传入getters对象为第二个参数
    newNum2(state,getters){
        return state.num * getters.newNum
    }
    // 可以返回一个函数,可以由外部自定义参数进行处理
    age(){
        return function (age){
            return state.age.filter(s => s>age)
        }
    }
}

// 使用(直接按照属性的方式使用,不需要括号)
<p>{{store.getters.newNum}}</p>

// 外部传入参数,显示大于8岁的年龄
<p>{{store.getters.age(8)}}</p>

>将getters中的内容导入到组件计算属性之中使用:

// getters
export default {
  cartLength(state) {
    return state.cartList.length
  },
  cartList(state) {
    return state.cartList
  }
}
// 要使用getters的组件
import {mapGetters} from 'vuex'
computed:{
    ...mapGetters(['cartLength','cartList'])
    // 可以添加一层映射,直接使用属性名进行使用
    ...mapGetters({
        length: 'cartLength',
        list: 'cartList'
    })
}

// 使用
{{cartLength}}或者{{length}}

五、mutation

1、store状态更新

store状态更新唯一的方式,提交mutation,默认会把state参数传递过来

// 定义
mutations: {
  // 定义修改state的方法,这里默认会把state参数传递过来
  add(state){
    state.num++
  }
}

// 使用
methods: {
    change(){
        // 使用commit('方法名')对state进行修改
        this.$store.commit('add')
    }
}

>在methods中调用commit方法:

import {mapMutations} from 'vuex'
// {方法名: mutation属性} | [方法名(mutation属性)]
methods: {
    ...mapMutations({add:'add'})
    // 或者
    ...mapMutations(['add'])
}
// 在methods中添加了方法,如果有参数,需要在调用时候进行传递

2、使用时传参

使用mutation更新数据时侯,有时希望携带参数,也称作mutation的载荷(Payload)

——使用时传入参数:

<p @click="change(5)"></p>
methds: {
    change(count){
        this.$store.commit('add',count)
    }
}
----------
// 增加多少由使用者决定
mutations: {
  // 这里默认会把state参数传递过来,同时也会加上count参数
  add(state,count){
    // 每次加5
    state.num+=count
  }
}

如果参数不止一个,Payload也可以是一个对象

3、Mutation的提交风格

Vue除了上面的普通风格外,还提供了另一种风格,它是一个包含type属性的对象

<p @click="change(5)"></p>
methds: {
    change(count){
        // 将数值提交,这里提交的是一个对象,包括type和count属性
        this.$store.commit({
            type: 'add',
            count: count
        })
    }
}
----------
mutations: {
    // 这时候接收到的不是数字,而是一个对象包括type和count属性
  add(state,payload){
    state.num+=payload.count
  }
}

4、Mutation响应规则

  • 提前在store中初始化所需属性
  • 使用以下方式添加属性
    • Vue.set(要修改的对象,'属性',修改的值),此方法也可以进行修改
    • 用新对象给旧对象重新赋值
state: { 
    // 定义时添加属性,属性会添加到响应式系统之中,监听属性的变化,实时更新界面
    info: {
        name: 'zhou',
        age: 20
    }
}
----------
// 修改属性
updateInfo(state){
    // 可以实现响应式
    state.info.name="zhouyabo"
}

// 增加属性
updateInfo(state){
    // info中可以添加sex属性,但是界面不会响应刷新
    state.info.['sex']="男"

    // 解决方法,实现响应式添加
    Vue.set(state.info,'sex','男')
}

// 删除属性
delInfo(state){
    // 能删除info中的属性,但是不能实现响应式
    delete state.info.age
    // 解决方法
    Vue.delete('state.info','age')
}

5、mutation常量类型

在mutations之中,定义了许多事件类型(方法名称),多个文件切换可能会出现方法名错的情况

// 将方法名单独抽离成一个文件motations_type.js
export const UPDATE = 'updateinfo'
---------
import {UPDATE} from './motations_type.js'
mutations: {
    [UPDATE](state){}
}

----------
import {UPDATE} from './motations_type.js'
methods: {
    this.$store.commit(UPDATE)
}

6、mutation同步函数

通常情况下,Mutation中的方法必须是同步方法,如果是异步方法,devtools将不能很好的跟踪操作是否完成

// 异步修改属性:错误的写法
updateInfo(state){
    setTimeout(()=>{
        state.info.name="zhouyabo"
    },1000)
}
// 页面可以更改,info也可以实现更改,但是devtool不会更改,没有记录新信息

// 将异步操作放到action中执行
updateInfo(state){
    state.info.name="zhouyabo"
}

解决办法:action是用来处理异步操作的

六、action

1、基本使用

类似于mutation,是用来代替mutation处理异步操作的,对异步操作进行处理

actions: {
    // action中的方法也有默认属性,但是不是state,而是context(上下文:store)
    actionUpdate(context){
        setTimeout(()=>{
            // 不能直接在这里修改state,修改state唯一的途径就是mutation
            context.commit('updateInfo')
        },1000)
    },

}

>在methods中调用dispatch方法:

methods: {
    changeInfo(){
        // 这里不能使用commit,commit是提交mutation的
        thsi.$store.dispatch('actionUpdate')
    }
}
--------------------------
同样可以使用mapActions进行操作
import {mapActions} from 'vuex'
methods: {
    ...mapActions({changeInfo:'changeInfo'})
    // 或者
    ...mapAction(['changeInfo'])
}
若有参数,需要在调用时候传递

2、执行回调

  • 方法一,函数回调
methods: {
    changeInfo(){
        // 可以传递一个对象
        thsi.$store.dispatch('actionUpdate',{
            message:'传递的信息',
            success:()=>{console.log('提示信息')}
        })
    }
}
----------
actions: {
    actionUpdate(context,payload){
        setTimeout(()=>{
            context.commit('updateInfo')
            // 执行传递进来对象的成功函数进行提示
            payload.success()
        },1000)
    }
}
  • 方法二,Promise 回调
actions: {
    actionUpdate(context,payload){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
        context.commit('updateInfo')
        resolve('ok')
            },1000)
        })
}
----------
methods: {
    changeInfo(){
        thsi.$store.dispatch('actionUpdate','传递的信息').then(res=>{
            console.log(res)    // ok
        }
    }
}

七、modules

state单一状态树使得代码越来越臃肿,所以可以使用module划分模块进行保存

export default new Vuex.Store({
    modules: {
        a: {
            // 开启命名空间,默认为false
            namespaced: true,
      state: {
        name:'Tom'
      },
      mutations: {
        getData(){}
      },
      actions: {},
      getters: {}
    },

    b: {
        namespaced: true,
      state: {},
      mutations: {},
      actions: {},
      getters: {}
    }
    }
})

目的:让代码更好地维护,数据分类更加明确

开启命名空间后,读取state的数据

方法一:直接读取
this.$store.state.a.name
方法二:借助mapState读取
.mapState('a', ['name'])

开启命名空间后,读取getters数据

方法一:直接读取
this.$store.getters['a/要读取的属性']
方法二:使用mapGetters读取
.mapGetters('a',['要读取的属性'])

开启命名空间后,组件中调用dispatch

方法一:直接调用
this.$store.dispatch('a/方法名', 参数)
方法二:使用mapAction
...mapAction('a', {methods中方法名, actions中的方法名})

开启命名空间后,组件中调用commit

方法一:直接commit
this.$store.commit('a/方法名', 参数)
方法二:使用mapMutations
...mapMutations('a', {methods中的方法名, mutations中的方法名})

八、store文件夹的目录组织

=store

=modules

————moduleA.js

———index.js

———mutations.js

———actions.js

———getters.js

文件通过export default 导出,通过impot导入

标签: vuex
最后更新:2022-09-24

粥呀Bo

所谓惊喜,就是苦苦等候的兔子来了,后面却跟着狼

点赞
< 上一篇
下一篇 >

文章评论

取消回复
目录
  • 一、什么是Vuex
    • 1、状态管理
    • 2、使用场景
  • 二、Vuex的使用
  • 三、state
  • 四、getters
  • 五、mutation
    • 1、store状态更新
    • 2、使用时传参
    • 3、Mutation的提交风格
    • 4、Mutation响应规则
    • 5、mutation常量类型
    • 6、mutation同步函数
  • 六、action
    • 1、基本使用
    • 2、执行回调
  • 七、modules
  • 八、store文件夹的目录组织

COPYRIGHT © 2022 zhouyaker.cn. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

陕ICP备2022009272号