vue全家桶--vux

142 阅读5分钟

vuex介绍

  • vuex的作用是解决多组件状态共享的问题,在大型的项目中,组件通讯会变得很混乱,使用vuex可以统一管理组件之间的通讯
  • 它是独立于组件而单独存在的,所有的组件都可以把它当作一座桥梁来进行通讯。

image.png

使用vuex好处

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

vuex使用场景

  • 开发中我们组件传值大多还是使用父子组件传值,少部分才使用vuex 比如:数据需要在非常多的页面使用 如用户头像 全局设置....
  • 不是所有的场景都适用于vuex,只有在必要的时候才使用vuex,如果不必要,尽量别用
  • 使用了vuex之后,会一定程度上增加了项目的复杂度
  • 适合使用vuex场景
  • 这个数据需要在很多个地方使用,如果采用组件传值方式,写起来很麻烦,而且多个地方都要写
  • .不适合使用vuex场景
  • 这个数据不需要多个地方使用,如果某个数据仅仅只是在两个组件之间通讯,优先使用props或$emit

那我们总结一下:

vuex的作用简单来说就是实现所有组件数据共享 一旦vuex数据修改,所有使用的地方数据都会自动更新

vuex使用流程

使用步骤:

  • vue-cli中整合==(如果使用vue ui创建创建,直接勾选vuex,会自动帮我们完成配置)
  • vue add vuex :
  • 1.如果提示选择 y,
  • 2.创建了/src/store/index.js,
  • 3.main.js导入并挂载到Vue实例上
  • state中定义数据
  • 任意组件中this.$store.state.xxx即可取值改值 ; template中可以不用写this ;可以通过计算属性简化编码
  • .js文件中导入store对象即可获取属性

vuex核心概念-state

state作用 : 储存公共数据 vuex 可以在任何页面使用 使用方法 : this.$store.state.xxx

  • ./vuex/index.js 储存数据
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  //1.state作用:存储数据
  state: {
    user:{
      name:'ikun',
      age:30
    }
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

  • home.vue 使用数据
  • my.vue也可以使用vuex数据
<template>
  <div>
      <h1>首页</h1>
      <button>点我修改vuex数据</button><br>
      <button>点我发送ajax请求</button>
      <div>
          <h2>个人信息</h2>
          <p>我的名字是:{{ $store.state.user.name }}</p>
          <p>我的年龄是:{{ $store.state.user.age }}</p>
      </div>
      <div>
          <h2>图书管理信息</h2>
          <ul>
              <li></li>
          </ul>
      </div>
  </div>
</template>

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

<style scoped>
p{
    color:red;
}
</style>

getters派生状态(计算属性)

语法如下

现在getters中声明一个计算属性

new Vuex.store({
  // 省略其他...
  getters: {
    // state 就是上边定义的公共数据state
    计算属性名: function(state) {
      return 要返回的值
    }
  }
})

使用getter中的计算属性

  • $store.getters.getter的名字

./vuex/index.js

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

Vue.use(Vuex)

export default new Vuex.Store({
  //1.state作用:存储数据
  state: {
    user:{
      name:'ikun',
      age:30
    }
  },
  /* 2.2.getter作用: 
  官方术语:从state中派生状态(使用state中的数据,计算得出一些新数据)
  说人话: 相当于state的计算属性 
  */
  getters: {
    getInfo(state){
      //state:就是vuex上面的state
      return `我是${state.user.name},我今年${state.user.age}岁了`
    }
  },
  //2.
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

home.vue :

<div>
  <h2>个人信息</h2>
  <p>我的名字是:{{ $store.state.user.name }}</p>
  <p>我的年龄是:{{ $store.state.user.age }}</p>
  <p>自我介绍:{{ $store.getters.getInfo }}</p>
</div>

image.png

vuex核心概念- Mutations

Mutation作用:更新state中的数据

既然可以直接通过this.$store.state来修改,为什么不能这么写呢?

原因: 在组件中直接state,我们的vue tools不会追踪数据的修改,这样不便于维护(不知道这个全局数据什么时候被修改了,再加上vuex是全局响应式的,一旦修改所有使用的地方全部修改。非常不便于维护)

image.png

image.png

Mutation语法如下

  • 分两个格式: 注册的格式,调用的格式
  • 定义格式: 如下
  • 每一项都是一个函数,可以声明两个形参:
  • 第一个参数是必须的,表示当前的state。在使用时不需要传入
  • 第二个参数是可选的,表示载荷,是可选的。在使用时要传入的数据
  • 专业术语载荷:表示额外的参数
  • 使用格式:this.$store.commit('mutation名', 载荷实参 )
  • 这个事件名就是Mutation中的函数名。(类似于$emit的一种事件通知机制)
new Vue.store({
  // 省略其他...
  mutations:{
    // 每一项都是一个函数,可以声明两个形参
  	mutation名1function(state [, 载荷]) {
  
  },
    mutation名2function(state [, 载荷]) {

    },
}
})
  • ./vuex/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  //1.state作用:存储数据
  state: {
    user:{
      name:'ikun',
      age:30
    }
  },
  /* 2.2.getter作用: 
  官方术语:从state中派生状态(使用state中的数据,计算得出一些新数据)
  说人话: 相当于vuex的计算属性 
  */
  getters: {
    getInfo(state){
      //state:就是vuex上面的state
      return `我是${state.user.name},我今年${state.user.age}岁了`
    }
  },
  //3.mutations作用:修改state中的数据
  mutations: {
    setUser(state,newData){
      state.user = newData
    }
  },
  actions: {
  },
  modules: {
  }
})
  • home.vue
export default {
    name:'home',
    methods: {
        doClick(){
            this.$store.commit('setUser', {
                name:'it李宗盛',
                age:38
            })
        }
    },
}

Vuex-mutaions拓展理解

问:为啥是$store.commit('mutations的名字')而不是$store.mutations的名字()?

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

问:数据不可以该在组件内部直接修改吗?

答:不能。虽然语法上不报错,也有响应式的特点。但是不推荐。特别是在严格模式下会报错。若将vue创建 store 的时候传入 strict: true, 开启严格模式,那么任何修改state的操作,只要不经过 mutation的函数,vue就会报错

vuex辅助函数-mapState

官网文档:vuex辅助函数-mapState

mapState作用: 将vuex中的数据映射到组件的计算属性

  • 我们在组件中访问vuex数据,需要通过this.$store.state.属性名,单词太常,写起来很麻烦。
      • 通过mapState函数,可以在组件中直接通过this.属性名来访问vuex中的数据

image.png

mapState语法

  • 在要使用的组件中导入mapState辅助函数: import { mapState } from 'vuex'
  • 在这个组件的computeds中来映射计算属性
export default {
  name: "my",
  computed:{
    //计算属性
    //2.将vuex中的user映射成计算属性(与下面代码完全等价)
    ...mapState(['user'])

    //计算属性:本质还是访问vuex中的数据
    // user(){
    //   return this.$store.state.user
    // }
  }
};

...mapState( ['属性名a' , '属性名b'] )

这行代码相当于自动帮你生成一个对应的计算属性 属性名(){ return this.$store.state.属性名 }

vuex核心概念:actions

actions介绍

  • actions与mutations相同点 :都是修改state数据
    • .actions与mutations不同点

    • mutations:同步更新

    • actions: 异步更新(例如你的数据来源于ajax)

image.png

  • 为什么要有actions, 假如你有一个数据,需要通过ajax请求来获取。然后你想存入vuex,应该怎么做?
  • 1.在组件的created钩子中发送ajax请求
  • 2.服务器响应数据之后,调用$store.commit()提交给mutations更新(手动挡)
  • 方案二:
  • 1.直接在actions中发送ajax请求
  • 2.actions会自动帮你把数据提交到mutations更新(自动挡)

actions语法如下

new Vuex.store({
  // 省略其他...
  actions: {
    // context对象会自动传入,它与store实例具有相同的方法和属性
    action的名字: function(context, 载荷) {
      // 1. 发异步请求, 请求数据
      
      // 2. commit调用mutation来修改数据
      
      // context.commit('mutation名', 载荷)
    }
  }
})

在组件中通过this.$store.dispatch('actions的名字', 参数)来调用action

vuex核心概念modules

  • modules作用:模块化处理vuex数据
  • 当vuex中需要存储的数据很多的时候,就需要使用moudles进行模块化处理
  • 一般开发中moudles使用不多哈。 只有那种特别复杂,庞大的项目才可能用到

使用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文件中,然后导入进来

访问数据和修改数据的调整

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

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

访问模块中的mutations/actions:

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