一、定义
官网:
Vuex 是什么? | Vuex (vuejs.org)
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
二、安装
cdn
<script src="/path/to/vuex.js"></script>
npm
(@3是为了指定版本,否则装的是最新版)
做过淘宝镜像的使用cnpm命令,如果没有做过,请使用npm命令
cnpm install vuex@3 --save
三、特点
这个状态自管理应用包含以下几个部分(也是特点,从官网获取):
-
state
,驱动应用的数据源;
(也就是说state的用来放状态数据的)
-
view
,以声明方式将
state
映射到视图;
(也就是将state的数据展示在浏览器的内容中)
-
actions
,响应在
view
上的用户输入导致的状态变化。(
用户需要通过actions来触发改变状态数据)
以下是一个表示“单向数据流”理念的简单示意图(从官网获取):因其顺序不可逆,所以是单向数据流
为了解决遇到多组件共享状态时,依旧维持单向数据流的简洁性,以及保持视图和和状态间的独立性,我们将组件的共享状态抽取出来,形成一个全局单例模式管理。这样,我们的代码将会变得更结构化且易维护。
(此为阅读官网后的个人理解,如有错误请指正,谢谢♪(・ω・)ノ)
如下图:
Vue Components:组件。最终将数据呈现在视图中。所以数据Render(渲染)出来。
此结构也是不可逆的,再次证明其是是单向数据流的形式。
如果用户需要改变数据的流程:
需要通过Dispatch方式去改,把最新值给到Actions。再通过Commit将数据提交给Mutations,其作用是专门修改state状态数据。此时state的值就是最新值,然后再次Render(渲染)给Vue Components
Backend API:接口。在Actions这块,我们可以做一些异步交互请求操作,拿到最新值。
Devtools:调试工具。我们可以通过调试工具看Mutations的最新值和旧值。
四、vuex的应用
每一个 Vuex 应用的核心就是 store(仓库)。——> 使用Vuex的目的就是为了得到store仓库
“store”基本上就是一个容器,它包含着你的应用中大部分的
状态 (state)
Vuex 和单纯的全局对象有以下两点不同:
-
Vuex 的状态存储是响应式的。
当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
-
改变 store 中的状态的唯一途径就是显式地
提交 (commit) mutation
。
引入vuex和创建store对象不需要自己写,在
Vue自主搭建项目
的时候就可以自动生成基本结构。
链接请点:
Vue自主搭建项目
4.1引入。(引入后就可以在任何组件中拿到状态数据了)
以下为自主搭建好的项目demo中,store文件夹里index.js的格式(注释是我自己写的)
1.
引入vuex及创建并导出store对象
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
Vue.use(Vuex)
// 创建store对象
/**
* 接收参数:Object
* 该对象包含5个核心:state,actions,mutations,getters,modules
*/
export default new Vuex.Store({
/**
* 存放状态数据
*/
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})
2.在入口文件main.js中引入store并放入vue实例当中(此结构也是自动生成)
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 1.引入store
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
// 2.再将store放入vue实例当中
store,
render: h => h(App)
}).$mount('#app')
4.2使用
-
基础配置:
在src目录下创建pages文件夹,在pages文件夹中创建Box1.vue文件,建好基本结构。要访问Box1里的组件需要先在router的index.js中引入组件以及配置规则。
(此前要在App.vue文件中设置路由出口<router-view></router-view>)
<template>
<div>
<router-view></router-view>
</div>
</template>
Box1.vue
<template>
<div>
<h2>Box1组件</h2>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
index.js
// 引入组件
const Box1=()=>import('@/pages/Box1')
// 规则
const routes = [
{
path: '/box1',
component: Box1
},
]
-
通过State将数据渲染到页面中。(mapState辅助函数)
当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键。
1)在Box1.vue中导出辅助函数mapState。接收参数:[ ]/{ },返回值:对象
import { mapState } from 'vuex'
2)在计算属性computed中使用辅助函数
computed:{
...mapState({
//:左侧为自定义属性名 :右侧为映射到state中的属性名
newName:'name',
age:'age'
})
}
3)Box1.vue全部代码
<template>
<div>
<h2>Box1组件</h2>
<div>name值:{{ newName }}</div>
<div>age值:{{ age }}</div>
</div>
</template>
<script>
// 导出辅助函数mapState
import { mapState } from 'vuex'
export default {
computed:{
...mapState({
//:左侧为自定义属性名 :右侧为映射到state中的属性名
newName:'name',
age:'age'
})
}
}
</script>
<style>
</style>
此时页面中为:
-
提交修改数据Actions
1)actions作用:(1)commit mutations (2)异步请求 (3)自调
2)actions使用:(1)方法名自定义 (2)系统自动注入参数:context。context中有commit方法、 dispatch方法、state属性
声明两个自定义方法并提交修改数据:
nameActions(context,name){
//console.log(context);
//console.log(name);
//提交mutations中的事件 参数:值(字符串形式)
context.commit('changeName',name)
},
ageActions(context,age){
context.commit('changeage',age)
},
3)在Box1.vue中加入button按钮以及使用dispatch方法。
dispatch作用:映射actions中的事件
dispatch参数:事件名(字符串形式)、修改的数据
<button @click="changeName('wsx')">修改name</button>
methods:{
changeName(name){
this.$store.dispatch('nameActions',name)
},
changeage(age){
this.$store.dispatch('ageActions',age)
}
}
此时点击修改name按钮就能在控制台拿到要修改的name值。
4.修改state状态数据mutations
方法名自定义,系统自动注入参数state。
actions中的 context.commit(‘changeName’,name)代码将要修改的name值提交给mutations。(age值一样)
需要在mutations中定义的方法里接收name和age值。
// 作用:专门修改state状态数据
mutations: {
/**
* 1.方法名自定义
* 2.系统自动注入参数state
*/
changeName(state,name){
// state中的name属性=新的name值
state.name=name
},
changeage(state,age){
state.age=age
}
},
点击按钮修改成功如下:
五、代码总结
Box1.vue
<template>
<div>
<h2>Box1组件</h2>
<div>name值:{{ newName }}</div>
<div>age值:{{ age }}</div>
<button @click="changeName('wsx')">修改name</button>
<button @click="changeage(26)">修改age</button>
</div>
</template>
<script>
// 导出辅助函数mapState
import { mapState } from 'vuex'
export default {
computed:{
...mapState({
//:左侧为自定义属性名 :右侧为映射到state中的属性名
newName:'name',
age:'age'
})
},
methods:{
changeName(name){
this.$store.dispatch('nameActions',name)
},
changeage(age){
this.$store.dispatch('ageActions',age)
}
}
}
</script>
<style>
</style>
index.js
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
Vue.use(Vuex)
// 创建store对象
/**
* 接收参数:Object
* 该对象包含5个核心:state,actions,mutations,getters,modules
*/
export default new Vuex.Store({
/**
* 存放状态数据
*/
state: {
name:'pjm',
age:'24'
},
getters: {
},
// 作用:专门修改state状态数据
mutations: {
/**
* 1.方法名自定义
* 2.系统自动注入参数state
*/
changeName(state,name){
// state中的name属性=新的name值
state.name=name
},
changeage(state,age){
state.age=age
}
},
/**
* actions作用:1.commit mutations 2.异步请求 3.自调
*/
actions: {
/**
* 1.方法名自定义
* 2.系统自动注入参数:context
* 3.context:{commit,dispatch,state}
*/
nameActions(context,name){
/* console.log(context);
console.log(name); */
/**
* 提交mutations中的事件
* 参数1 mutations中的事件 值->字符串
*/
context.commit('changeName',name)
},
ageActions(context,age){
context.commit('changeage',age)
// console.log(context);
},
},
modules: {
}
})