日常咱们的全局状态管理统统都交给
Vuex
来,Vuex
也的确是很是好的工具,并被官方做为指定的状态管理器。今天给你们介绍有个新的思路进行状态管理。可能你们对provide / inject
这对api
有点陌生,的确也是,日常开发中咱们基本也不会用到。vue
看图片能够知道,provide
指望传入一个Object
,而inject
能够接受的值包括(1)一个字符串数组 (2)一个对象。代码以下:(最简单的写法)api
// 父组件 App.vue
export default {
name: 'App',
provide: {
parentKey: 'aaa'
}
}
复制代码
// 子组件 chidlren.vue
export default {
inject: ['parentKey'],
created () {
console.log(this.parentKey)
}
}
复制代码
在打印台能够看到aaa被输出了出来,既然inject
指望值是个数组,那应该也能够这样数组
// 父组件 App.vue
export default {
name: 'App',
provide: {
parentKey: { a: 'haha' },
parentKey2: [1, 2]
}
}
复制代码
// 子组件 chidlren.vue
export default {
inject: ['parentKey', 'parentKey2'],
created () {
console.log(this.parentKey, this.parentKey2)
}
}
复制代码
以前咱们传递是个字符串,发现其实传递什么均可以,对应的对象和数组都打印出来了。 若是仅仅只是这样,好像也没什么。看到api有这样一句话:bash
提示:
provide
和inject
绑定并非可响应的。这是刻意为之的。然而,若是你传入了一个可监听的对象,那么其对象的属性仍是可响应的。app
咱们能够试下:iview
// 父组件 App.vue
<template>
<div class="app">
<router-view></router-view>
<button @click="changeKey"> 按钮</button>
</div>
</template>
export default {
provide () {
return {
parentKey: this.key
}
},
methods: {
changeKey () {
this.key.push(2)
}
},
data () {
return {
key: [1]
}
}
}
复制代码
// 子组件 chidlren.vue
export default {
inject: ['parentKey'],
created () {
let afterKey = JSON.stringify(this.parentKey)
let timer = setInterval(() => {
console.log(this.parentKey)
if (afterKey !== JSON.stringify(this.parentKey)) clearInterval(timer)
}, 1000)
}
}
复制代码
最后能够看见当点击按钮以后,在子组件chidlren.vue
中输出的值变化了,定时器也中止了。ide
这里面有几个要注意的地方 (1). 这时候provide
必须为一个工厂函数,若是你是这样写的provide: {parentKey: this.key}
也就是跟以前这种写法,控制台会报未定义key的错误 (2)不要传字符串之类的值过去,好比:parentKey: this.key
而你在data
中是这样定义key
的key: 'aaa
,提示下,他并非一个可响应的数据,你可能会说,那不对啊,我在当前组件改变这个值,模板里输出的也会变啊。这时候其实可响应的值是this
当前组件 (3)你们不要试图替换数组来响应(为何说这条,由于不注意我也犯了这个错误 :) (4)一旦注入了某个数据,好比上面示例中的 parentKey
,那这个组件中就不能再声明 parentKey
这个数据了,由于它已经被父级占有)函数
注意:在变异 (不是替换) 对象或数组时,旧值将与新值相同,由于它们的引用指向同一个对象/数组。Vue 不会保留变异以前值的副本。(来源Vue官网)工具
好像说了这么久,没说到与标题相关的。:)-- 接下来久介绍下构建全局状态管理的思路网站
// 父组件(也能够说是根组件) App.vue
export default {
name: 'App',
provide () {
return {
app: this
}
},
methods: {
changeKey () {
this.key.push(2)
}
},
data () {
return {
key: [1],
transitionName: 'slide-right'
}
}
}
复制代码
// 子组件 chidlren.vue
export default {
inject: ['app'],
created () {
console.log(this.app)
console.log(this.app.key)
this.app.changeKey()
}
}
复制代码
这样你就能够拿到根节点app
全部的东西了,还能够访问他的方法。以此将根节点做为状态管理器。 若是你以为这样状态多起来,十分难管理,你可使用混合mixins
,将不一样的逻辑分开到不一样的 js 文件里。固然这种事是仁者见仁智者见智,你可使用this.$root
访问根节点,还能够挂载在Vue.prototype
的原型上。哈哈,这些方法是否是感受有点邪门歪道的感受。因此官网有这么一句话:
provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。
给你们介绍下这个网站dev.iviewui.com,这个网站就是使用此方法作出来的,这样减小了Vuex
的依赖使用vue
自己做为状态管理器,固然,若是你的网站很大,仍是建议使用Vuex
。
这对api还有不少东西能够挖掘的,好比使用ES2015的Symbol
做为惟一值,inject
中可使用default
做为默认值等等。用法仍是同窗们去看看官网。此次久到此为止,清明放假了,仍是休息休息。:)
若有错误,欢迎指出。