百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 博客教程 > 正文

VueX使用干货 vuex详解和用法

connygpt 2024-10-11 11:56 4 浏览



vuex简介

  • Vuex是一个为Vue.js应用程序开发的状态管理模式
    • 采用集中式存储管理应用的所有组件的状态,并且相应的规则保证状态以一种可预测的方式发生变化
    • Vuex也集成到Vue的官方调试工具 devtools extension,提供了注入令配置的time-travel调试,状态快照导入导出功能
  • 状态管理是什么:
    • 可以简单的将其看成把需要的多个组件共享的变量全部存储在一个对象里面
    • 然后将这个对象放在顶层的Vue实例中,让其他组件可以使用
    • 那么,多个组件就可以共享这个对象中的所有变量属性了
    • 简单来说就是多个组件需要共享一个状态(或者是变量),那么这个状态放在哪个组件中都不合适,那么就单独的new一个对象,把这个对象看作是一个管家,来管理这些共享的状态信息
  • 有什么状态时需要多个组件共享:
    • 如果一个项目,存在多个界面共享问题
    • 比如用户的登陆状态,用户名称,头像,地理位置信息,商品收藏,购物车中的物品等等
    • 这些状态信息,都可以放在统一的地方,对它进行保存和管理,而且它们还是响应式的

Vuex 安装

  1. 命令行安装
npm install vuex --save
  1. 在src文件夹下创建 store文件夹,在该文件夹下创建 index.js文件,其中写入:
import Vue from "vue";
import Vuex from "vuex"

//1. 安装插件
Vue.use(Vuex);

//2. 创建vuex对象
const store = new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {}
})

//3. 导出story对象
export default store;
  1. 在main.js文件中引入vuex对象
import Vue from 'vue'
import App from './App'
import router from './router'
//引入 vuex 的store对象
import store from "./store";

Vue.config.productionTip = false
new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})

通过 mutation 修改vuex管理的状态

  • 要修改vuex管理的状态必须通过mutation
  • index.js文件
import Vue from "vue";
import Vuex from "vuex"

//1. 安装插件
Vue.use(Vuex);

//2. 创建vuex对象
const store = new Vuex.Store({
  state: { //定义被vuex管理的各个状态
    counter: 10
  },
  mutations: {//定义方法用于修改vuex管理的状态
    increment(state){
      state.counter++;
    },
    decrement(state){
      state.counter--;
    }
  },
  actions: {},
  getters: {},
  modules: {}
})
//3. 导出story对象
export default store;
  • App.vue文件
<template>
<div id="app">
  <h3>{{$store.state.counter}}</h3>
  <!--操作vuex管理的状态-->
  <button @click="addition">+</button>
  <button @click="subtration">-</button>
  <hr>
  <hello-vuex/>
</div>
</template>

<script>
    import HelloVuex from "./components/HelloVuex";
    export default {
      name: 'App',
      components:{
        HelloVuex
      },
      methods:{
        addition(){
          //通过mutation修改被vuex管理的状态
          this.$store.commit('increment')
        },
        subtration(){
          //commit()传入的是在index.js中mutations中定义的方法名
          this.$store.commit('decrement')
        }
      }
    }
</script>
  • 具体描述
    • 提取出一个公共的store对象,用于保存多个组件中共享的状态
    • 将store对象放置在 new Vue对象中,这样可以保证在所有的组件中都可以使用到
    • 在其他组件中使用store对象中保存的状态即可
      • 通过 this.$store.属性 的方式来访问状态
      • 通过 this.$store.commit('mutation方法名') 来修改状态
  • 注意事项:
    • 通过提交 mutation的方式,而非直接改变 store.state.属性
    • 这是因为Vuex可以更明确的追踪状态的变化,所以不要直接改变store.state.counter 的值

vuex Getters 的使用

  • 有时候,需要从store 中获取一些state 变异后的状态
  • 在组件中需要拿到 store中的数据,而且这个数据是需要变化后才给到组件或者页面的时候,这时就需要永高getters
  • 抽取出的vuex的index.js配置文件
import Vue from "vue";
import Vuex from "vuex"

//1. 安装插件
Vue.use(Vuex);

//2. 创建vuex对象
const store = new Vuex.Store({
  state: { //定义被vuex管理的各个状态
    students: [
      {id: 1, name: 'bob', age: 18},
      {id: 2, name: 'kobe', age: 22},
      {id: 3, name: 'xyx', age: 25},
      {id: 4, name: 'john', age: 17}
    ]
  },
  getters: {
    //这里定义的是state中变化后的内容
    more20stu(state){
      return state.students.filter(s => s.age > 20);
    }
  }
})
//3. 导出story对象
export default store;
<template>
<div id="app">
  <p>getters中定义的powerConter内容----</p>
  <h3>{{$store.getters.powerConter}}</h3>
  <p>通过getters 中的more20stu 获取state中age大于20的对象---</p>
    <!--通过getters拿到变化后的store中的内容-->
  	{{$store.getters.more20stu}}
</div>
</template>

<script>
export default {
  name: 'App',
}
</script>

getters作为参数和传递参数

  1. 作为参数
  • 以上面的代码为例,如果需要拿到 {{$store.getters.more20stu}} 获取的学生的个数
  • 在getters中定义的函数还可以传入第二个参数
import Vue from "vue";
import Vuex from "vuex"

//1. 安装插件
Vue.use(Vuex);

//2. 创建vuex对象
const store = new Vuex.Store({
  state: {
    counter: 10,
    students: [
      {id: 1, name: 'bob', age: 18},
      {id: 2, name: 'kobe', age: 22},
      {id: 3, name: 'xyx', age: 25},
      {id: 4, name: 'john', age: 17}
    ]
  },
  getters: {
    more20stu(state){
      return state.students.filter(s => s.age > 20);
    },
    //传入的第二个参数代表就是当前对象中的getters
    more20stuLenthg(state,getters){
      return getters.more20stu.length;
    }
  },
})

//3. 导出story对象
export default store;
<template>
<div id="app">
  <p>通过getters 中的more20stu 获取state中age大于20的对象---</p>
  {{$store.getters.more20stu}}
  <p>getters 作为参数</p>
  <h3>{{$store.getters.more20stuLenthg}}</h3>
</div>
</template>

<script>
export default {
  name: 'App'
}
</script>
  1. 传递参数
  • getters默认是不能传递参数的,如果希望传递参数,那么只能让getters本身返回另一个函数
  • 要获取年龄大于 age的stu对象,age由外部传递进来
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex);

const store = new Vuex.Store({
  state: { //定义被vuex管理的各个状态
    counter: 10,
    students: [
      {id: 1, name: 'bob', age: 18},
      {id: 2, name: 'kobe', age: 22},
      {id: 3, name: 'xyx', age: 25},
      {id: 4, name: 'john', age: 17}
    ]
  },
  getters: {
    //获取年龄大于 age 的学生,这个Age不是写死的,而且别的地方传入进来的
    moreAgeStu(state) {
        //返回一个函数
      return function (age) {
        return state.students.filter(s => s.age > age);
      }
    }
  }
})
//3. 导出story对象
export default store;
<template>
<div id="app">
  <p>getters 传递参数----</p>
    <!--传入一个22给getters中定义的方法,这个方法返回一个函数,这个22就是函数的参数-->
  <p>{{$store.getters.moreAgeStu(22)}}</p>
</div>
</template>

<script>
export default {
  name: 'App'
}
</script>

mutainons 携带参数

  • vuex的store状态的更新唯一方式是:提交Mutations
  • mutations主要包括两部分
  • 字符串的事件类型(type)
  • 一个回调函数(handler) ,该回调函数的第一个参数就是state
  • mutations的定义方式:
mutations: {
    increment(state){
        state.count++;
    }
}
  • 通过mutations更新
increment: function(){
    this.$stote.commit('increment')
}
  • 之前的mutations改变counter是每次 ++ 或者 --,现在需要每次点击按钮 + 多少 -多少由外部传入
mutations: {
    // 第二个参数是外部传入的
    incrementCount(state,count){
        state.counter += count;
    }
},
<template>
<div id="app">
  <p>mutations 传递参数----</p>
  <h4>{{this.$store.state.counter}}</h4>
  <button @click="addCount(5)">+5</button>
  <button @click="addCount(10)">+10</button>
</div>
</template>

<script>
export default {
  name: 'App'
  methods:{
    addCount(count){
        //提交,并传入参数
      this.$store.commit('incrementCount',count);
    }
  }
}
</script>
  • mutitaions传递参数就是在提交comiit的时,commit的第二个参数就是传递给mutations的参数

mutitaions 传入多个参数

  • 多个参数使用一个对象传入
addStu(){
      const stu = {id: 5, name: 'alan', age:30};
      this.$store.commit('addSutdent',stu);
}

mutations提交风格

  • 之前通过commit进行提交是一种普通的方式
  • Vue还提供了另外一种风格,它是一个包含type属性的对象,被称为mutations负载(payload)
addCount(count){
    //普通的提交风格
    //this.$store.commit('incrementCount',count);
    //特殊的提交风格
    this.$store.commit({
        type: 'incrementCount',
        count
    })
},
mutations: {//定义方法用于修改vuex管理的状态
    incrementCount(state,payload){
      state.counter += payload.count;
    }
}

mutations响应规则

  • vuex的store中的state是响应式的,当state中的数据发生改变时,vue组件会自动更新
  • 这就要求必须遵守一些vuex对应的规则
    • 提前在store中初始化好所需的属性
    • 当给state中的对象添加新属性时,使用下面的方式
      • 方式一: 使用 Vue.set(obj, 'newProp', 123)
      • 方式二: 用新对象给旧对象重新赋值
  • 给state中定义好的对象添加属性
<template>
<div id="app">
  <p>store.state.info的内容是否是响应式的-------</p>
  <button @click="updateInfo">修改 info</button>
  <h2>{{$store.state.info}}</h2>
</div>
</template>

<script>
export default {
  name: 'App',
  methods:{
      //修改info对象,并且是响应式的
    updateInfo(){
      this.$store.commit('updateInfo')
    }
  }
}
</script>
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex);
const store = new Vuex.Store({
  state: { //定义被vuex管理的各个状态  
    info: {
      name: 'xiaoyouxin',
      age: 25,
      height: 1.75
    }
  },
  mutations: {//定义方法用于修改vuex管理的状态
   //通过Vue.set(obj, key, value) 响应式的修改info的信息
    updateInfo(state){
      Vue.set(state.info, 'addr', '重庆');
    }
  }  
})
export default store;
  • 给state中定义好的对象删除属性
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex);
const store = new Vuex.Store({
  state: { //定义被vuex管理的各个状态
    info: {
      name: 'xiaoyouxin',
      age: 25,
      height: 1.75
    }
  },
  mutations: {//定义方法用于修改vuex管理的状态
    deleteInfo(state){
      //删除属性该方式做不到响应式
      // delete state.info.name;
      Vue.delete(state.info, 'name');
    }
  } 
})
export default store;

mutation常量类型

  • 在mutation中,自定义了很多事件类型(也就是其中的方法名称)
  • 当项目增大时,vuex管理的状态越来越多,需要更新状态的情况越来越多,那么意味着mutation中的方法越来越多
  • 方法过多,使用者需要花费大量的精力去记住这些方法,甚至是多个文件之间来回切换,查看方法名称,甚至如果不是复制的时候,可能还会出现写错的情况
  • 这时候可以在store文件夹下创建一个js文件用于保存常量
export const INCREMENT = 'increment';
export const INCREMENTCOUNT = 'incrementCount';
export const DECREMENT = 'decrement';
export const ADDSTUDENT = 'addSutdent';
export const UPDATEINFO = 'updateInfo';
export const DELETEINFO = 'deleteInfo';
  • 然后再index.js文件中引入这些常量,并修改mutations中的方法名为 :
import Vue from "vue";
import Vuex from "vuex"
// 引入这些常量
import {
  INCREMENT,DELETEINFO,DECREMENT,ADDSTUDENT,UPDATEINFO,INCREMENTCOUNT
} from './mutations-types'
Vue.use(Vuex);
const store = new Vuex.Store({
  state: { //定义被vuex管理的各个状态
    counter: 10,
    students: [
      {id: 1, name: 'bob', age: 18},
      {id: 2, name: 'kobe', age: 22},
      {id: 3, name: 'xyx', age: 25},
      {id: 4, name: 'john', age: 17}
    ],
    info: {
      name: 'xiaoyouxin',
      age: 25,
      height: 1.75
    }
  },
  mutations: {
     //修改方法名为 : [常量](){} 的方式
    [INCREMENT](state) {
      state.counter++;
    },
    [DECREMENT](state) {
      state.counter--;
    },
    [INCREMENTCOUNT](state,payload){
      state.counter += payload.count;
    },
    [ADDSTUDENT](state,stu){
      state.students.push(stu);
    },
    [UPDATEINFO](state){
      Vue.set(state.info, 'addr', '重庆');
    },
    [DELETEINFO](state){
      Vue.delete(state.info, 'name');
    }
  }
})
export default store;
  • 在组件中使用这些常量
<template>
<div id="app">
  <p>mutations 传递参数----</p>
  <h4>{{this.$store.state.counter}}</h4>
  <button @click="addCount(5)">+5</button>
  <button @click="addCount(10)">+10</button>

  <p>mutations 传递参数2----</p>
  <button @click="addStu">添加学生</button>
  {{$store.state.students}}

  <p>store.state.info的内容是否是响应式的-------</p>
  <button @click="updateInfo">修改 info 添加属性</button>
  <h2>{{$store.state.info}}</h2>
  <button @click="deleteInfo">修改 info 删除属性</button>
  <h2>{{$store.state.info}}</h2>
</div>
</template>

<script>
  import HelloVuex from "./components/HelloVuex";
    //引入常量
  import {
    INCREMENTCOUNT, ADDSTUDENT, UPDATEINFO, DELETEINFO
  } from "./store/mutations-types"
export default {
  name: 'App',
  methods:{
    addCount(count){
      this.$store.commit({
        type: INCREMENTCOUNT,  
        count
      })
    },
    addStu(){
      const stu = {id: 5, name: 'alan', age:30};
        //使用常量作为commit提交的参数
      this.$store.commit(ADDSTUDENT,stu);
    },
    updateInfo(){
        //使用常量作为commit提交的参数
      this.$store.commit(UPDATEINFO)
    },
    deleteInfo(){
      this.$store.commit(DELETEINFO);
    }
  }
}
</script>

<style>

</style>

Action 基本定义

  • 通常情况下Vuex要求mutation中的方法必须是同步方法
    • 主要原因是当我们使用devtools时,devtools可以帮助我们捕捉mytations的快照
    • 但是如果是异步操作,那么devtools将不能很好的追踪这个操作由什么时候被完成
  • 如果有些情况下,确实需要在vuex中进行一些异步操作,比如网络请求,必然时异步的,这时候使用Action,Action类似于mutations,但是是来替代mutations进行异步操作的
  • 用法,在组件中需要异步修改state中的属性
    • $this.store.dispatch('Action中的函数名')
    • Action中定义的异步函数内部通过mutitaons修改state中的属性
import Vue from "vue";
import Vuex from "vuex"
import {
  INCREMENT,DELETEINFO,DECREMENT,ADDSTUDENT,UPDATEINFO,INCREMENTCOUNT
} from './mutations-types'
Vue.use(Vuex);
const store = new Vuex.Store({
  state: { //定义被vuex管理的各个状态
    info: {
      name: 'xiaoyouxin',
      age: 25,
      height: 1.75
    }
  },
  mutations: {
    [UPDATEINFO](state){
      Vue.set(state.info, 'addr', '重庆');
    }
  },
  actions: {
      //在actions中定义的函数中异步调用mutations中的方法
    aUpdateInfo(context){
      setTimeout(() => {
        context.commit(UPDATEINFO)
      },1000)
    }
  }
})
export default store;
<template>
<div id="app">
  <button @click="updateInfo">修改 info 添加属性</button>
  <h2>{{$store.state.info}}</h2>
</div>
</template>

<script>
  import {
    INCREMENTCOUNT, ADDSTUDENT, UPDATEINFO, DELETEINFO
  } from "./store/mutations-types"
export default {
  name: 'App',
  methods:{
    updateInfo(){
        //通过 dispatch的方式对state中的属性进行异步操作
      this.$store.dispatch('aUpdateInfo')
    }
  }
}
</script>

注意: action传递参数的方式mutitaions的方式一致

modules 的使用

  • vue使用单一状态树,那么也意味着很多状态都会交给vuex来管理
  • 当应用变得非常复杂时,store对象就有了能变得相当臃肿
  • 为了解决这个问题,vuex允许将store分割成模块,而每个模块都拥有自己的state,mutations,actions,gettets等
  • 定义在模块中的东西使用方式和之前是一样的,不做过多笔记
  • 不过getters中定义的函数除了 state,getters之外还可呢传入第三个参数 rootState,这个参数表示之前没有用模块分割的哪个state,可以从这个参数中取出原本定义好的属性
  • 还有一个就是在modules中的cations中定义的函数commit的时候是针对于自己这个模块中的mutations的

项目结构

  • 当vuex管理过多内容时,好的项目结构可以使代码更加清晰
    • index.html
    • main.js
    • api
      • ... 抽取出的API请求
    • components
      • App.vue
      • ...
    • store
      • index.js 组装模块并导出store的地方
      • actions.js 根级别的 action
      • mutations.js 根级别的mutation
      • modules
        • cart.js 购物车模块
        • user.js 用户模块

如果遇到文中代码格式被压缩的情况时,请复制代码到ide中查看

相关推荐

3分钟让你的项目支持AI问答模块,完全开源!

hello,大家好,我是徐小夕。之前和大家分享了很多可视化,零代码和前端工程化的最佳实践,今天继续分享一下最近开源的Next-Admin的最新更新。最近对这个项目做了一些优化,并集成了大家比较关注...

干货|程序员的副业挂,12个平台分享

1、D2adminD2Admin是一个完全开源免费的企业中后台产品前端集成方案,使用最新的前端技术栈,小于60kb的本地首屏js加载,已经做好大部分项目前期准备工作,并且带有大量示例代码,助...

Github标星超200K,这10个可视化面板你知道几个

在Github上有很多开源免费的后台控制面板可以选择,但是哪些才是最好、最受欢迎的可视化控制面板呢?今天就和大家推荐Github上10个好看又流行的可视化面板:1.AdminLTEAdminLTE是...

开箱即用的炫酷中后台前端开源框架第二篇

#头条创作挑战赛#1、SoybeanAdmin(1)介绍:SoybeanAdmin是一个基于Vue3、Vite3、TypeScript、NaiveUI、Pinia和UnoCSS的清新优...

搭建React+AntDeign的开发环境和框架

搭建React+AntDeign的开发环境和框架随着前端技术的不断发展,React和AntDesign已经成为越来越多Web应用程序的首选开发框架。React是一个用于构建用户界面的JavaScrip...

基于.NET 5实现的开源通用权限管理平台

??大家好,我是为广大程序员兄弟操碎了心的小编,每天推荐一个小工具/源码,装满你的收藏夹,每天分享一个小技巧,让你轻松节省开发效率,实现不加班不熬夜不掉头发,是我的目标!??今天小编推荐一款基于.NE...

StreamPark - 大数据流计算引擎

使用Docker完成StreamPark的部署??1.基于h2和docker-compose进行StreamPark部署wgethttps://raw.githubusercontent.com/a...

教你使用UmiJS框架开发React

1、什么是Umi.js?umi,中文可发音为乌米,是一个可插拔的企业级react应用框架。你可以将它简单地理解为一个专注性能的类next.js前端框架,并通过约定、自动生成和解析代码等方式来辅助...

简单在线流程图工具在用例设计中的运用

敏捷模式下,测试团队的用例逐渐简化以适应快速的发版节奏,大家很早就开始运用思维导图工具比如xmind来编写测试方法、测试点。如今不少已经不少利用开源的思维导图组件(如百度脑图...)来构建测试测试...

【开源分享】神奇的大数据实时平台框架,让Flink&amp;Spark开发更简单

这是一个神奇的框架,让Flink|Spark开发更简单,一站式大数据实时平台!他就是StreamX!什么是StreamX大数据技术如今发展的如火如荼,已经呈现百花齐放欣欣向荣的景象,实时处理流域...

聊聊规则引擎的调研及实现全过程

摘要本期主要以规则引擎业务实现为例,陈述在陌生业务前如何进行业务深入、调研、技术选型、设计及实现全过程分析,如果你对规则引擎不感冒、也可以从中了解一些抽象实现过程。诉求从硬件采集到的数据提供的形式多种...

【开源推荐】Diboot 2.0.5 发布,自动化开发助理

一、前言Diboot2.0.5版本已于近日发布,在此次发布中,我们新增了file-starter组件,完善了iam-starter组件,对core核心进行了相关优化,让devtools也支持对IAM...

微软推出Copilot Actions,使用人工智能自动执行重复性任务

IT之家11月19日消息,微软在今天举办的Ignite大会上宣布了一系列新功能,旨在进一步提升Microsoft365Copilot的智能化水平。其中最引人注目的是Copilot...

Electron 使用Selenium和WebDriver

本节我们来学习如何在Electron下使用Selenium和WebDriver。SeleniumSelenium是ThoughtWorks提供的一个强大的基于浏览器的开源自动化测试工具...

Quick &#39;n Easy Web Builder 11.1.0设计和构建功能齐全的网页的工具

一个实用而有效的应用程序,能够让您轻松构建、创建和设计个人的HTML网站。Quick'nEasyWebBuilder是一款全面且轻巧的软件,为用户提供了一种简单的方式来创建、编辑...