【Vuex学习指南】Vuex使用场景有哪些?解决组件通信的方法有哪些?如何创建Vuex?

1,177 阅读3分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第2篇文章,点击查看活动详情

解决组件通信的方法有哪些?

序号组件关系数据通信
1父子关系子传父:$emit ; 父传子:props
2非父子关系eventBus: on+on + emit
3非父子关系vuex

1.Vuex介绍

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex的数据状态管理:管理数据,并且管理数据的状态
vuex作用:实现所有组件间的数据共享

1.vuex的作用是解决多组件状态共享的问题,在大型的项目中,组件通讯会变得很混乱,使用vuex可以统一管理组件之间的通讯

  • 它是独立于组件而单独存在的,所有的组件都可以把它当作一座桥梁来进行通讯。

2.使用vuex好处

  • 响应式 : 只要vuex中的数据变化,对应的组件会自动更新(类似于vue数据驱动)
  • 操作更简洁 : 类似于sessionStorage,只有几个方法

2.Vuex使用场景

实际开发中,组件传值大多数情况下还是使用 父子组件传值少部分情况下会用vuex. (数据需要在非常多的页面使用,比如用户头像,好几个页面都要显示那种)

  • 1.不是所有的场景都适用于vuex,只有在必要的时候才使用vuex,如果不必要,尽量别用

    • 使用了vuex之后,会一定程度上增加了项目的复杂度
  • 2.适合使用vuex场景

    • 这个数据需要在很多个地方使用,如果采用组件传值方式,写起来很麻烦,而且多个地方都要写

      • 例如:用户信息(姓名,头像),可能会在很多个地方使用(个人页面,评论页面等)
  • 3.不适合使用vuex场景

    • 这个数据不需要多个地方使用,如果某个数据仅仅只是在两个组件之间通讯,优先使用props或$emit
  • 4.vuex特点

    • (1)所有组件数据共享
    • (2)响应式: 一旦vuex数据修改,所有使用的地方都会自动更新

3.在Vue脚手架创建vuex

3.1使用vue ui创建创建

直接勾选vuex,会自动帮我们完成配置

image.png

3.2如果创建是没有选择vuex,可以手动添加

在项目根目录执行 vue add vuex

image.png

3.3Vuex的store文件夹

在执行以上的两个命令之中的任何一个后, 会在src文件夹生成一个store文件夹,默认含有一个index.js文件 index.js内容如下

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
  //1.state作用:存储数据
  state: {
  },
  /* 2.2.getter作用: 
  官方术语:从state中派生状态(使用state中的数据,计算得出一些新数据)
  */
  getters: {},
  //3.mutations作用:修改state中的数据
  mutations: {
  },
  //4.action作用: 异步更新数据
  actions: {},
  //5.module作用:模块化处理vuex数据
  modules: {}
});

image.png

4.vuex核心概念-state

4.1.state作用:存储数据

  //1.state作用:存储数据
  state: {
    user: {
      name: "阿斯蒂芬",
      age: 34
    }
  },

组件中获取数据方法

          <p>我的名字是:{{ $store.state.user.name }}</p>
          <p>我的年龄是:{{ $store.state.user.age }}</p>

4.2mapState 辅助函数

当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键 在组件中使用mapstate

上面是vuex官方文档,什么意思呢?通俗的讲就是
我们通过计算属性把store.state属性平铺到组件中的时候,
属性较多时,每个属性都要写一次,computed要写好多次,
使用mapstate只用写一行代码
具体使用方法如下:

  • 先导入辅助函数mapstate: import { mapState } from 'vuex'
  • 展开运算符和mapstate组合使用: ...mapState(['user'])
<script>
//导入辅助函数mapState
import { mapState } from 'vuex'
export default {
  name: "my",
  computed: {
    //计算属性
    //2.将vuex中的user映射成计算属性(与下面代码完全等价)
    ...mapState(['user'])
    // 等价于自动帮我们生成以下代码
    //计算属性:本质还是访问vuex中的数据
    // user(){
    //   return this.$store.state.user
    // }
  },
};
</script>

5.vuex核心概念-getters

getter是state的派生属性
相当于计算属性computed的get(){},
在页面加载时会计算一次,存入内存,此外数据没有变化,则不会执行,而是直接用内存中的数据,减少了计算次数,降低性能消耗

语法如下:
getter的第一个参数是:state
getter 可以选择其他的getter作为第二个参数

getters: {
  // ...
  doneTodosCount (state, getters) {
    return getters.doneTodos.length
  }
}

6.vuex核心概念 Mutations

特点:同步更新数据
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

6.1声明mutations

  • mutations函数最多只能传两个参数,state是默认参数,payload是额外参数(载荷)
(1)声明mutations
mutations: {
mutation名(state,payload){
//修改state数据
}}

6.2组件中使用mutations

  • commit(type:'mutation名',payload)
  • 只能传两个参数,type:"mutation名"是默认参数,payload是额外参数(载荷),
  • 如果一定要传俩个参数,可以吧参数包在对象中作为payload载荷
    doClick() {
      this.$store.commit("mutation名",payload);
    },

6.3 为什么一定要加一个commit才能调用mutations的方法?

  • 因为Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler) 。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。

7.vuex核心概念 actions

异步更新state数据,通过motations间接更新数据

7.0 action传值流程详细图解

image.png

7.1组件中使用dispatch更新

  • 提交action更新:载荷一般为ajax参数
  • this.$store.dispatch('action名',载荷)
  • 任意组件:触发actions this.$store.dispatch('action名',载荷)
    doActions(){   
      this.$store.dispatch('getList',{num:10})
    }

7.2声明actions,actions发送异步请求

 (1)声明actions
action名(context,payload){
//context:vuex实例对象
//payload:载荷(一般是ajax参数)
}
  • context是vuex中的所有对象:state,getters等

  • payload是传过来的参数

 actions: {
    async getList(context, payload) {
      // context是vuex中的所有对象:state,getters等
      // payload是传过来的参数
      const { data: res } = await axios.get("https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books")
      context.commit('updateList', res.data)
    }
  },

7.3提交mutation更新

  mutations: {
    updateList(state, payload) {
      state.list = payload
    }
  },

7.4更新state

  state: {
    list: []
  },

image.png

8.vuex核心概念 Module

当vuex中需要存储的数据很多的时候,就需要使用moudles进行模块化处理

  • 一般实际开发中moudles使用不多。 只有复杂,庞大的项目才可能用到

8.1使用modules语法如下

export default new Vuex.Store({
  // state: 用来保存所有的公共数据
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {
  	模块名1: {
    		// namespaced为true,则在使用mutations时,就必须要加上模块名
      	namespaced: true, 
  		  state: {},
  			getters: {},
  			mutations: {},
  			actions: {},
  			modules: {}
  	},
    模块名2: {
        // namespaced不写,默认为false,则在使用mutations时,不需要加模块名
  		  state: {},
  			getters: {},
  			mutations: {},
  			actions: {},
         modules: {}
  	}  
  }
})

也可以把每一个modules单独写在一个js文件中,然后导入进来

8.2组件中访问Vuex模块数据

访问模块中的数据,要加上模块名

获取数据项:  {{$store.state.模块名.数据项名}}
获取getters: {{$store.getters['模块名/getters名']}}

访问模块中的mutations/actions:

  • 如果namespaced为true,则需要额外去补充模块名
  • 如果namespaced为false,则不需要额外补充模块名
$store.commit('mutations名')        // namespaced为false
$store.commit('模块名/mutations名')  // namespaced为true