what’s vuex?
单向数据流模式
vuex模式
why vuex?
当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
因此,vuex把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。
Vuex状态管理跟使用传统全局变量的区别:
- vuex的状态存储是响应式的,当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会得到高效更新。
- 不能直接改变store的变化,改变store中状态的唯一途径是commit、mutation。方便于跟踪每一个状态的变化。
how use Vuex
这里以uniapp的登录模板为例
首先需要新建一个store目录,在该目录下新建一个index.js文件
import Vue from 'vue' //引入vue
import Vuex from 'vuex' //引入vuex
Vue.use(Vuex) //使用vuex
//创建vuex实例store
const store = new Vuex.Store({
})
//导出store
export default store
在main.js引入store,注册到vue实例中
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
//挂载$store为store方便访问
Vue.prototype.$store = store
App.mpType = 'app'
const app = new Vue({
store,
...App
})
app.$mount()
接下来添加需要的全局数据
state
state: {
forcedLogin: false,
hasLogin: false,
userName: ""
},
在组件中就能获取state中的数据了
<template>
<view class="content">
<view class="hasLogin">
hasLogin:{{this.$store.state.hasLogin}}
</view>
<view class="forceLogin">
forceLogin:{{this.$store.state.forcedLogin}}
</view>
<view class="username">
usename:{{this.$store.state.userName}}
</view>
</view>
</template>
mapstate;
this.$store.state.hasLogin写起来太麻烦,尤其是有很多需要获取的数据情况下。
采用mapstate可以让你少写些代码
<template>
<view class="content">
<view class="hasLogin">
hasLogin:{{hasLogin}}
</view>
<view class="forceLogin">
forceLogin:{{forcedLogin}}
</view>
<view class="username">
usename:{{userName}}
</view>
</view>
</template>
<script>
import {mapState} from 'vuex'
export default {
data() {
return {
title: ''
}
},
computed: {
...mapState(['forcedLogin', 'hasLogin', 'userName'])
},
}
</script>
将state映射为prototype,通过computed监听改变。
Getters:
可以理解为是state的computed,
这里遇到个很有趣的事,
案例1:
案例2:
关于js的++i和i++。
mutation
Mutation 必须是同步函数
现在通过state.haslogin我们能获取到用户的登录状态,那么如果用户登录,或退出登录,如何改变state.haslogin
mutations: {
login(state, userName) {
state.userName = userName || '新用户';
state.hasLogin = true;
},
logout(state) {
state.userName = "";
state.hasLogin = false;
}
}
methods: {
...mapMutations(['login','logout']),
}
一条重要的原则就是要记住 mutation 必须是同步函数,官方说明
Actions
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
actions:{
asynclogin(context){
context.commit('login')
},
asynclogout(context){
context.commit('logout')
}
}