vue 都是组件化的开发模式.
整个组件树中,组件和组件之间的关系如下图所示.
组件结构树父子组件传值一般用 props
& events
即可.
但是非父子组件之间,如何传值会有很多的解决方案.
一般都建议使用 vuex
官方提供的集中式状态管理工具.
但此方案有可能过于笨重,写起来也并不方便,还需要专门引入 vuex
库,增大项目的打包体积.
使用 store 模式
使用 store
模式来解决组件间数据状态共享的问题.
store
模式的核心很简单:
- 每个组件实例都能访问到这个
store
对象. - 当
store
对象的某个值发生改变时,所有依赖于这个store
组件的对象都会更新.
第一种 store 模式
定义一个很简单的全局单例对象,此提供一些数据,在组件间共享.
将此对象定义在需要使用到的组件,并设置在 data
属性上即可.
export default {
shareName: "张三",
changeName (name) {
this.shareName = name
},
changeNameAsync (name) {
setTimeout(() => {
this.shareName = name
}, 2000);
}
}
A 组件需要使用.
import shareData from "../share_data/share_data";
export default {
name: "HelloWorld",
data () {
return {
shareData, // 此数据被框架内部的 initData 设置成响应式,被设置依赖的收集和触发.
};
},
methods: {
changeShareName () {
this.shareData.changeName("李四");
},
},
};
B 组件需要使用.
import shareData from "../share_data/share_data";
export default {
name: "HelloWorld",
data () {
return {
shareData,
};
},
methods: {
changeShareName () {
this.shareData.changeNameAsync("王五");
},
},
};
效果:
单例模式.gif总结:
- 定义一个数据单例 <span style="color:red">(
export default & import
在 webpack 打包后,就是单例的,没有必要在进行特别处理)</span>对象用于存储需要在组件间共享的数据. - 共享数据对象间接依赖组件本身的
data
节点,将它转换成响应式,并完成数据的依赖收集和更新触发.
第二种 store 模式
第一种
store
模式虽然已经完成了数据的共享和数据的修改,但有时候,我们需要更为精细的对数共享数据的操作和控制.
第二种,使用一个 new Vue
实例,去承载共享数据的功能. 实例内部的 methods
, computed
, watch
等,可以用于对数的监视和控制.
此
new Vue
实例,主要功能是在共享数据提供.它不需要在 UI 上显示.所以,也不需要template
以及render
. 它是一个以数据管理为主要目的的组件实例
.
import Vue from 'vue'
// 提供一个不在 UI 上显示的 Vue 组件实例.
// 让其的主要目的是为了保持数据共享和响应式.
const share_data = new Vue({
data () {
return {
shareName: '张三'
}
},
methods: {
changeName (name) {
this.shareName = name
},
async changeNameAsync (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
this.shareName = name
resolve(this.shareName)
}, 2000);
})
}
},
watch: {
shareName: {
handler (newVal, oldVal) {
if (newVal === oldVal) return
// otherwise do something.....
},
immediate: true
}
}
})
export default share_data
// main.js
import shareData from './share_data/share_data'
Vue.prototype.$shareData = shareData
在 A 组件上使用
<template>
<div class="hello">
<h2>通过单例非显示 UI 组件-享元模式数据:{{ $shareData.shareName }}</h2>
<button @click.stop="changeShareName">修改名称(同步)</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
methods: {
changeShareName () {
this.$shareData.changeName('李四')
},
},
};
</script>
在 B 组件上使用
<template>
<div class="hello">
<h2>通过单例非显示 UI 组件-享元模式数据:{{ $shareData.shareName }}</h2>
<button @click.stop="changeShareName">修改名称(异步)</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data () {
return {
innerName: ""
}
},
methods: {
changeShareName () {
this.$shareData.changeNameAsync('赵六').then((res => {
this.innerName = res
}))
},
},
};
</script>
效果:
非显示组件模式.gif总结:
- 定义一个非显示的
new Vue
组件实例,用于数据管理. - 相比较简单的
plain object
共享, 组件实例提供了丰富了数据管理的API
功能.
网友评论