VUE 入门及应用 ( VueX )

8.状态管理 vuex

vuex 是一个专门为vue.js应用程序开发的状态管理模式。用于解决大规模单页应用(SPA)中复杂状态管理和组件间通信的问题。

Vuex 采用了集中式存储管理应用的所有组件的状态,并通过一系列严格的规则来确保状态变更的可预测性和可控性。

可以理解为 存储操作 共享数据

8.0.导入vuex

由于 vue2 对应的 是 vuex3 版本, 而 vue3 对应的 是 vuex4 版本, 所以导入时要注意版本

npm install vuex@3 --save

8.1.基本概念

8.1.1.基本对象

vuex中,有默认的五种基本的对象:

8.1.1.1.状态(State)

state:状态(变量)是整个应用的核心数据源,所有的状态都保存在一个单一的、全局可访问的对象中。

这个状态树对所有组件都是可见的,并且是响应式的,当状态发生改变时,依赖它的组件会自动更新。

8.1.1.2.计算值 ( Getters )

getters:对数据获取之前的再次编译,可以理解为state的计算属性。

8.1.1.3.改变( mutations)

mutations:用于同步修改状态值。是唯一改变 state 的途径,每一个 mutation 都是一个纯函数,它接受 state 作为第一个参数,以及一个 payload(载荷)。

所有状态的修改必须通过提交 mutation 来完成,这样可以确保每次状态变更都有迹可循。

8.1.1.4.动作( actions )

actions:异步操作的处理器,它们可以触发 mutations,但不能直接修改 state。

Actions 通常用于处理异步逻辑(如网络请求),然后通过 commit 方法提交 mutation 来改变 state。

在组件中使用是$store.dispath(’ 函数名’)

8.1.1.5.模块 ( modules )

modules:store的子模块,随着应用规模的增长,状态管理可能会变得非常庞大。

Vuex 允许我们将 store 分割成多个模块(Module),每个模块有自己的 state、mutation、action 和 getter,以此来更好地组织和管理状态。。

8.1.2.配置文件

8.1.2.1.配置文件

@/store/index.js

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

8.1.2.2.main.js

注意这里 导入的不是 vuex 插件 , 而是导入 主配置文件的 store 对象

因为 import 会在最先执行, 先于 Vue.use() 语句之前执行

而 stroe对象 要先 导入 vuex , 再 执行 Vue.use(Vuex) 才能得到

所以 要在 状态管理器配置文件 中 调用 Vue.use(Vuex)

import Vue from 'vue'
import App from './App.vue'
import router from './router'

// 状态管理器 
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

8.1.3.准备测试页面

8.1.3.1.准备MyState.vue

增加新的 /views/MyState.vue 文件

<template>
  <div>
    <h1>MyState</h1>
  </div>
</template>
<script>
export default {
  name: "MyState"
}
</script>
8.1.3.2.路由中引入

在路由的 index.js 文件中引入文件

import MyState from '@/views/MyState.vue'
8.1.3.3.配置路由

增加路由配置, 在 路由后追加了 :id , :title

{
    path: '/myState',
    name: 'myState',
    component: MyState
}

8.2.测试

8.2.1.State 使用

8.2.1.1.修改state 对象
  state: {
    count: 0,
    user : {
      name: '王小二',
      age : 20,
      hobby : ['java', 'html', 'vue']
    }
  },
8.2.1.2.接值

在 MyState 组件中 , 通过 this.$store.state 对象取值

<template>
  <div>
    <h1>MyState</h1>
    <hr>
    <h2>{{'count : ' + this.$store.state.count }}</h2>
    <h2>{{'user : ' + this.$store.state.user.name }}</h2>
    <h2>{{'hobby : ' + this.$store.state.user.hobby }}</h2>
  </div>
</template>

8.2.2.mutations 使用

8.2.2.1.定义函数

在 mutations 定义函数

  mutations: {
    ADD_COUNT:(state, param)=>{
      state.count += param;
    },
    CHANGE_USER:(state, param)=>{
      // state.user = param;
      Object.assign(state.user, param)
    },
      
  },
8.2.2.2.修改State中的值

在 MyState 组件中 , 增加按钮

<button @click="addCount">addCount</button>

对应的处理函数, 在组件中使用$store.commit( ' 函数名 ', params)。这个和我们组件中的自定义事件类似。

methods: {
    addCount() {
        this.$store.commit('ADD_COUNT', 2)
    }
}
8.2.2.3.修改对象

在 MyState 组件中 , 再增加按钮

<br>
<button @click="editUser">editUser</button>

对应的处理函数

editUser() {
    this.$store.commit('CHANGE_USER', {name: '李小三' })
}

8.2.3.Getters使用

8.2.3.1. 增加 getters 配置

Getters接收state作为其第一个参数, getters 作为第二个参数

 getters: {
    // 返回字符串
    msg:(state)=>{
      return 'hello';
    },
    // 返回 state中的信息
    getUserName:(state)=>{
      return state.user.name;
    },
    // 返回 state 及  getters中的信息
    sayHi:(state, getters)=>{
      return getters.msg + ' , ' + state.user.name;
    }
  },
8.2.3.2.显示信息

在 MyState 组件中 , 通过 this.$store.getters 对象取值

<template>
  <div>
    <h1>MyState</h1>
    <hr>
    <h2>{{'msg : ' + this.$store.getters.msg }}</h2>
    <h2>{{'user_name : ' + this.$store.getters.getUserName }}</h2>
    <h2>{{'sayHi : ' + this.$store.getters.sayHi }}</h2>
  </div>
</template>

注意这里 state 中的信息变化了, getters 返回信息也 响应变化结果

8.2.4.Actions 使用

8.2.4.1.增加 actions中的异步函数

这里用延时来模拟异步 , 实际项目中这里可能是异步获取数据

再通过 传入参数context 中的 commit函数来调用 mutations中的函数 来修改 state中的数据

  actions: {
    // 异步 增加Count
    asyncAddCount:(context, param)=>{
      // 这里用延时来模拟异步
      setTimeout(()=>{
        // 通过 commit 来调用 mutations中的函数
        context.commit('ADD_COUNT', param);
      }, 1000)
    },
  },
8.2.4.2.页面调用

在 MyState 组件中 , 增加按钮

    <br>
    <button @click="incrCount">incrCount</button>

按钮 对应的函数 , 通过 this.$store.dispatch() 调用 actions中的函数

incrCount() {
    this.$store.dispatch('asyncAddCount', 3)
}
8.2.4.3.异步修改对象

注意 这回 直接使用 解构 传入 context中的 commit函数

  asyncEitUser:({commit}, param)=>{
      setTimeout(()=>{
        commit('CHANGE_USER', param);
      }, 1000)
    }
8.2.4.4.调用 异步修改对象

在 MyState 组件中 , 增加按钮

<br>
<button @click="updateUser">updateUser</button>

按钮 对应的函数 , 通过 this.$store.dispatch() 调用 actions中的函数

updateUser() {
    this.$store.dispatch('asyncEitUser', {name: '赵小四'})
}

8.3.mapXxx 扩展

8.3.1.mapState, mapGetters基本格式

...mapState(["settings"]) 是 Vue.js 中结合 Vuex 使用的一个辅助函数语法,

用于从 Vuex store 中映射(或者说解构)全局状态(state, getters)到局部组件的计算属性(computed)。

当我们在组件中这样使用时:

import { mapState } from 'vuex';

export default {
  computed: {
    ...mapState(["属性名"]),
  }
}

这意味着该组件现在拥有了一个名为 settings 的计算属性,该属性的值直接对应 Vuex store 中的 settings 状态。每当 store 中的 settings 值发生变化时,组件中的 settings 计算属性也将自动更新,从而驱动组件视图的重新渲染。

8.3.2.mapState, mapGetters使用

8.3.2.1.解构导入

在 MyState 组件中 , 解构导入

import { mapState, mapGetters } from 'vuex'
8.3.2.2.扩展取值

在计算属性中 , 通过 … 扩展运算符 来将对象(数组) 转成 多个变量

computed: {
    // ...mapState({
    //   count: state => state.count,
    //   user: state => state.user
    // }),
    
    // ...mapState({
    //   count: 'count',
    //   user: 'user'
    // }),
    
    ...mapState(['count', 'user']),
    
    ...mapGetters([
      'msg',
      'getUserName',
      'sayHi'
    ]),
    // ...mapGetters({
    //     msg: 'msg',
    //     getUserName: 'getUserName',
    //     sayHi: 'sayHi'
    // })

  },
8.3.2.3.直接取值

在模板中使用

<h2>{{ 'count : ' + count }}</h2>
<h2>{{ 'user : ' + user.name }}</h2>
<h2>{{ 'sayHi : ' + sayHi }}</h2>

8.3.3.mapMutations, mapActions

8.3.3.1.导入
import { mapMutations, mapActions } from 'vuex'
8.3.3.2.修改methods
  methods: {

    ...mapMutations({
      addCount: 'ADD_COUNT',
      editUser: 'CHANGE_USER'
    }),
    ...mapActions({
        incrCount: 'asyncAddCount',
        updateUser: 'asyncEitUser'
    })
  }
8.3.3.3.传参

用以上方式时, 如果对应函数要传入参数, 就要在调用时传入参数

<hr>
<button @click="addCount(2)">addCount</button>
<br>
<button @click="editUser({name: '李小三' })">editUser</button>
<br>
<button @click="incrCount(3)">incrCount</button>
<br>
<button @click="updateUser({name: '赵小四'})">updateUser</button>

8.4.分模块

8.4.1.分拆文件

当 配置信息比较多, 又属性不同的业务组时, 可以将配置文件进行分拆

如 当前配置文件, 分拆成 num.js , info.js

8.4.1.1.num.js

@/store/modules/num.js

const num = {
    state:{
        count: 0
    },
    mutations:{
        ADD_COUNT:(state, param)=>{
            state.count += param;
        },
    },
    actions:{
        // 异步 增加Count
        asyncAddCount:(context, param)=>{
            // 这里用延时来模拟异步
            setTimeout(()=>{
                // 通过 commit 来调用 mutations中的函数
                context.commit('ADD_COUNT', param);
            }, 1000)
        },
    },
}

export default num
8.4.1.2.info.js

@/store/modules/info.js

const info = {
    state:{
        user : {
            name: '王小二',
            hobby : ['java', 'html', 'vue']
        }
    },
    getters:{
        // 返回 state中的信息
        getUserName:(state)=>{
            return state.user.name;
        },
    },
    mutations:{
        CHANGE_USER:(state, param)=>{
            // state.user = param;
            Object.assign(state.user, param)
        },
    },
    actions:{
        asyncEitUser:({commit}, param)=>{
            setTimeout(()=>{
                commit('CHANGE_USER', param);
            }, 1000)
        }
    },
}

export default info
8.4.1.3.getters.js

@/store/getters.js

const getters =  {
    // 返回字符串
    msg:(state)=>{
        return 'hello';
    },

    // 返回 state 及  getters中的信息
    sayHi:(state, getters)=>{
        return getters.msg + ' , ' + state.user.name;
    }
}
export default getters
8.4.1.4.主配置文件

这样原来的配置文件可以修改成

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

import num from './modules/num'
import info from './modules/info'
import getters from './getters'

Vue.use(Vuex)

export default new Vuex.Store({

  modules: {
    num,
    info
  },
  getters
})

8.4.2.直接调用$store

取 state的值 , 要增加 模块名

<h2>{{'count : ' + this.$store.state.num.count }}</h2>
<h2>{{'user : ' + this.$store.state.info.user.name }}</h2>
<h2>{{'hobby : ' + this.$store.state.info.user.hobby }}</h2>

但 调用 getters, mutations , actions 中的函数, 可以直接调用, 不用调整

8.4.3.mapState, mapGetters

8.4.3.1.mapState导组件

修改代码, 直接导入组件

...mapState(['num','info']),

取值

<h2>{{ 'count : ' + num.count }}</h2>
<h2>{{ 'user : ' + info.user.name }}</h2>
8.4.3.2.mapGetters 导组件

修改代码, 直接导入组件

...mapGetters(['info']),

取值, 无变化

<h2>{{'user_name : ' + this.$store.getters.getUserName }}</h2>
8.4.3.2.***使用命名空间

在 num.js , info.js 文件中加入 namespaced:true, 属性, 这样就为组件 分别命名,

修改 导入, 前面为 对应的 命名,

...mapState("num", ['count']),
...mapState("info", ['user']),

前面为 对应的 命名,与配置文件中对应 , 后面为导入 的变量 , 所以显示修改为直接使用变量

<h2>{{ 'count : ' + count }}</h2>
<h2>{{ 'user : ' + user.name }}</h2>

要注意 这时 getters 的 取值方式 发生变化

<h2>{{'user_name : ' + this.$store.getters["info/getUserName"] }}</h2>

而 动作调用

addCount() {
    this.$store.commit('num/ADD_COUNT', 2)
},
editUser() {
    this.$store.commit('info/CHANGE_USER',
    {name: '李小三' })
},
incrCount() {
    this.$store.dispatch('num/asyncAddCount', 3)
},
updateUser() {
    this.$store.dispatch('info/asyncEitUser', {name: '赵小四'})
},

8.4.4.mapMutations, mapActions

namespaced:true, 属性,这时使用 mapMutations, mapActions

就变成

...mapMutations("num",{
    addCount: 'ADD_COUNT',
}),
...mapMutations("info",{
    editUser: 'CHANGE_USER'
}),
...mapActions("num",{
    incrCount: 'asyncAddCount',
}),
...mapActions("info",{
    updateUser: 'asyncEitUser'
})

8.4.5.getters.js

将 分拆出的 getters.js 内容

修改 getters.js , 使用不同 模块的 state 数据时 , 增加所属模块名

const getters =  {
    // 返回字符串
    msg:(state)=>{
        return 'hello';
    },

    // 返回 state 及  getters中的信息
    sayHi:(state, getters)=>{
        return getters.msg + ' , ' + state.info.user.name;
    }
}
export default getters

相关推荐

  1. VUE 入门应用 ( VueX )

    2024-03-16 11:44:02       20 阅读
  2. <span style='color:red;'>Vue</span><span style='color:red;'>入门</span>

    Vue入门

    2024-03-16 11:44:02      16 阅读
  3. Vue中的组件通信方式应用场景

    2024-03-16 11:44:02       39 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-16 11:44:02       14 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-16 11:44:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-16 11:44:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-16 11:44:02       18 阅读

热门阅读

  1. 飞桨自然语言处理套件PaddleNLP初探

    2024-03-16 11:44:02       19 阅读
  2. stm32 I2C结构体解析

    2024-03-16 11:44:02       17 阅读
  3. SpringBoot 如何快速过滤出一次请求的所有日志

    2024-03-16 11:44:02       17 阅读
  4. 二维数组_矩阵交换行

    2024-03-16 11:44:02       14 阅读
  5. 第八章、设计模式

    2024-03-16 11:44:02       18 阅读
  6. Python keyword-only参数

    2024-03-16 11:44:02       17 阅读
  7. python pytest 最简单的接口自动化测试框架

    2024-03-16 11:44:02       17 阅读
  8. ISCE2StaMPS全流程

    2024-03-16 11:44:02       14 阅读
  9. AutoMapper12.0.1 扩展方法封装

    2024-03-16 11:44:02       19 阅读