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
功能.