什么是状态管理
前端现在主流的模式是数据驱动视图,一份数据对应的就是页面在特定条件下的状态,状态管理也就是数据管理,这里讨论的主要是数据在各个模块之间的共享问题。
在vue中,单个vue页面的数据是定义在data中的,定义在data中的数据会被改造成响应式的数据,在template, methods, watch, computed中都可以获取到。
父子组件之间也有单向的数据流props, 子组件也可以通过事件来改变父组件的数据,兄弟组件之间也可以通过父子组件之间的通信来实现互相数据的影响。
但是这样很麻烦,于是我们有vuex。
最简单的状态管理
最简单的状态管理就是一个对象
其实我们只要新建一个store.js
// store.js
const aa = {
name: '小明'
}
export default aa
然后在vue文件中, 引入这个对象,并在data中声明一个参数,值为aa这个对象,那么aa这个对象就会被转化为响应式的,在其他页面也引入这个对象的时候,当在一个页面改变了对象中属性的值, 其他页面对应地方的值也会响应式的发生改变。
export default {
data(){
return{
name: aa
}
},
vuex中的store模式
在项目比较简单的时候,vuex推荐我们使用简单的store模式,而不是引入vuex插件,这里的store模式就是上面那样一个简单的对象,但是vuex推荐我们拒绝直接修改状态的值,而是通过action函数来统一的提交修改,这样有助于更好的管理状态
// store.js中
var store = {
debug: true,
state: { message: 'Hello!' },
setMessageAction (newValue) {
if (this.debug) console.log('setMessageAction triggered with', newValue)
this.state.message = newValue
},
clearMessageAction () {
if (this.debug) console.log('clearMessageAction triggered')
this.state.message = ''
}
}
var vmA = new Vue({
data: { privateState: {},
sharedState: store.state
}
})
var vmB = new Vue({
data: { privateState: {},
sharedState: store.state
}
})
浅析vuex的实现
vuex中,我们既不需要在每个页面中都引入这个保存状态的对象,也不需要手动把这个对象转为响应式的,主要通过两个步骤实现:
对Vue的挂载
vue提供了mixin接口,这个接口内部能够拿到vue的实例,我们把实例的$store挂载为我们的状态管理对象,这样在每个vue页面,我们就可以通过$store拿到状态管理的对象了
这里先介绍一下vue.use()
vue.use()
安装 Vue.js 插件。如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。
该方法需要在调用 new Vue() 之前被调用。
当 install 方法被同一个插件多次调用,插件将只会被安装一次。
vue.mixin()
全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。插件作者可以使用混入,向组件注入自定义的行为。
上代码
// store.js
let Vue
function install(_vue) {
Vue = _vue
Vue.mixin({ beforeCreate: vuexInit })
}
function vuexInit(){}
let store= {
install
}
export default store
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
import store from './store.js'
Vue.use(store)
Vue.config.productionTip = false
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')
通过vue实现响应式
这里我们可以直接新建一个vue实例,借助vue本身的特性实现响应式
function vuexInit(){
const options = this.$options
if(options.store){
// this.$store = typeof options.store === 'function' ? options.store() : options.store
this.$store = new Vue({
data: {a: 2},
methods: {
add(){
this.a++
}
}
})
} else if(options.parent && options.parent.$store){
this.$store = options.parent.$store
}
}
页面中使用
<template>
<div>
<div>body</div>
<div>{{$store.a}}</div>
<div>
<button @click="add">加</button>
</div>
</div>
</template>
<script>
export default {
name: 'bodys',
data(){
return{
}
},
methods:{
add(){
this.$store.add()
}
}
}
</script>
这样就实现了一个简化的vuex