VUEX文档
概念
vuex 是 Vue 配套的 公共数据管理工具,它可以把一些共享的数据,保存到 vuex 中,方便整个程序中的任何组件直接获取或修改我们的公共数据;即Vuex是一个全局的共享数据存储区域,就相当于是一个数据的仓库。
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以可预测的方式发生变化。
使用步骤
-
安装包
cnpm i vuex -S
-
导入包
import Vuex from 'vuex'
,前提是要导入VUE包import Vue from 'vue'
-
将vuex注册到vue中
Vue.use(Vuex)
-
new Vuex.Store() 实例,得到一个数据仓储对象
var store = new Vuex.Store({ state: { isLogin : false, username:' ' }, mutations: { login(state){ state.isLogin = true, state.username = username }, loginout(state){ state.isLogin = false }, }, getters: { welcome: function (state) { return '欢迎:' + state.username } }, actions:{ login({commit}, username) { return new Promise((resolve, reject) => { setTimeout(() => { //模拟用户登录完成后调用increment if (username === 'admin') { commit('login',username) resolve() } else { reject() }}, 1000); }) } } })
-
将 vuex 创建的 store 挂载到vue实例上, 这样任何组件都能使用 store 来存取数据
const vm = new Vue({ el: '#app', render: c => c(App), store })
vue-cli安装:vue add vuex
核心概念
state
state
相当于组件中的 data ,专门用来存储数据的- 如果在组件中,想要访问
store
中的数据,可以通过this.$store.state.***
来访问
mutations
- 如果要操作
store
中的state
值,只能通过调用mutations
提供的方法,才能操作对应的数据,不推荐直接操作state
中的数据,因为 万一导致了数据的紊乱,不能快速定位到错误的原因,因为,每个组件都可能有操作数据的方法; mutations
相当于组件中的方法,可以通过this.$store.commit('方法名')
- 这种调用
mutations
方法的格式,和this.$emit('父组件中方法名')
相似。 - 在这里定义的方法最多支持两个参数,参数1 是 state 状态; 参数2是 通过 commit 提交过来的参数; 由于参数只能有两个参数,所以如果要传多个参数,可以以对象的形式把参数传过来
-
派生状态
getters
已经有了一些状态,可以对这些状态做一些操作,得到一些新的状态,getters是一旦原有状态发生变化,这些派生的状态也跟着变化,其实是计算属性在vuex中的迁移
getters
中的方法, 和组件中的过滤器比较类似,过滤器和getters
都没有修改原数据, 都是把原数据做了一层包装,提供给了调用者;getters
, 只负责对外提供数据,不负责修改数据,如果想要修改state
中的数据,请去找mutations
getters
和 计算属性computed
比较像, 只要function
内部,所用到的任何数据发生变化时,就会立即触发getters
的重新求值;getters
可以通过this.$store.getters.
方法名调用getters
的方法必须return
一个值
action
-
action
提交的是mutation
,而不是直接变更状态。 -
action
可以包含任意异步操作。 -
参数1是vuex传递的上下文context:{commit,dispatch,state},参数2是通过
dispatch
提交过来的参数 -
action
可以通过this.$store.dispatch.
方法名调用,如下this.$store.dispatch('login', 'admin').then(() => { this.$router.push(this.$route.query.redirect) }).catch(() => { alert('用户名或密码错误') })
模块化
使用modules定义多个子模块利于组件复杂状态
步骤:
1.创建子模块并导出它
user.js:
export default {
namespaced: true,
state: {
isLogin : false
},
mutations: {
login(state){
state.isLogin = true
},
loginout(state){
state.isLogin = false
},
},
getters: {
},
actions:{
login({commit}, username) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (username === 'admin') {
commit('login')
resolve()
} else {
reject()
}}, 1000);
})
}
}
}
注意:要设置namespaced
为true
,避免多个子模块命名冲突
- 在index.js中导入子模块,并在
modules
中注册模块
import Vue from 'vue
import Vuex from 'vuex'
import user from './user'
vue.use(Vuex)
export default new Vuex.Store({
modules:{
user
}
})
- 在入口文件中引入
new Vue({
router,
store,
render:h=>h(App)
}).$mount('#app')
访问方式响应变化,访问子组件时要加上命名空间
// 在state后加上命名空间后访问
<button @click="login" v-if="!$store.state.user.isLogin">登录</button>
this.$store.dispatch('user/login', 'admin').then(() => {
const redirect = this.$route.query.redirect || '/'
this.$router.push(redirect)
}).catch(() => {
alert('用户名或密码错误')
})
mapState()
/mapMutation()
/mapAction()
/mapGetters
通过这些映射方法可以让大家少敲几个字,避免对$store直接访问。
访问state:
//在对应的子组件中引入mapState
import { mapState } from 'vuex'
computed: {
...mapState('user', ['isLogin']) //this.$store.state.user.isLogin
//在html中可以直接使用isLogin访问,mapStateu全部在computed使用
}
访问action
import { mapActions } from 'vuex'
methods: {
login() {
this['user/login']('admin').then(...) // this.$store.dispatch("user/login",admin).then(...)
},
...mapActions(['user/login', 'user/logout'])
},
访问actiongetters
import { mapGetters } from 'vuex'
computed: {
...mapGetters ('user', ['welcome']) //this.$store.getters.welcome
//在html中可以直接使用welcome访问
}
注:映射的名字不要和data中的变量冲突
严格模式
严格模式下,无论何时发生了状态变更且不是由 mutation
函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。开启严格模式 strict: true
const store = new Vuex.Store({
strict: true
})
vuex插件
Vuex 的 store 接受 plugins 选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件本身是一个函数,它的形参是当前的store实例
const myPlugin = store => {
// 当 store 初始化后调用
}
注册插件:
const store = new Vuex.Store({
// ...
plugins: [myPlugin]
})
范例:实现登录状态持久化,store/plugins/persist.js
步骤1:创建plugins目录和js插件persist.js
步骤2:完成插件功能,并导出
export default store => {
// 初始化时从localStorage获取数据
if(localStorage) {
const user = JSON.parse(localStorage.getItem('user'))
if (user) {
store.commit('user/login')
store.commit('user/setUsername', user.username)
}
}
// 用户状态发生变化时缓存之
//vuex的API subscribe,可以订阅所有的mutation,只要mutation有变化就执行这个回调函数
store.subscribe((mutation, state) => {
if (mutation.type === 'user/login') { //调用登录方法时存储登录信息
localStorage.setItem('user', JSON.stringify(state.user))
} else if (mutation.type === 'user/logout') { //调用注销方法时删除登录信息
localStorage.removeItem('user')
}
})
}
vuex的API subscribe
,可以订阅所有的mutation
,只要mutation
有变化就执行这个回调函数
mutation.type
返回调用的mutation中的方法名,如果是子组件的,就返回组件名/方法名
步骤3:在index.js中导入插件,并在plugins
中注册插件
import Vue from 'vue
import Vuex from 'vuex'
import user from './user'
import persist from './plugins/persist' //导入插件
vue.use(Vuex)
export default new Vuex.Store({
modules:{
user
},
plugins:[persist ], //注册插件
strict: true
})