在vue的項(xiàng)目里面,組件之間相互通信的方式有很多,比如props/$emit、$on/$emit、vuex以及利用ref通信等方式。跨組件有這么多的通信方式可以選擇,但是當(dāng)需求要求我們跨頁面通信怎么辦呢?
由于每個頁面都是一個獨(dú)立的vue實(shí)例,頁面與頁面之間不存在數(shù)據(jù)上的溝通,所以,從vue框架上暫時行不通了。然后想到可以利用頁面緩存的方式來進(jìn)行通信。
在Web Storage中有兩種儲存數(shù)據(jù)的方式,分別是sessionStorage和localStorage,他們之間的區(qū)別在于生命周期的不同以及作用域(同源條件下)的不同。sessionStorage僅在當(dāng)前會話中有效,關(guān)閉頁面或者瀏覽器后數(shù)據(jù)會被自動清除,其作用域僅限于當(dāng)前頁面,不能跨tab頁面訪問。localStorage的生命周期是永久有效,只要是不主動刪除,數(shù)據(jù)會一直被存儲下來,其作用域也可以跨同源的頁面訪問。
有了localStorage跨頁面的作用域,就可以做到頁面之間的通信了,這下只要能解決如何監(jiān)聽其存儲數(shù)據(jù)的變化就能實(shí)現(xiàn)了。于是想到了一個比較粗暴的方式——利用定時器:在一定間隔時間內(nèi)獲取localStorage中的數(shù)據(jù)并更新到獲取數(shù)據(jù)的頁面中去,這樣便實(shí)現(xiàn)了數(shù)據(jù)的監(jiān)聽。但這樣未免也太耗費(fèi)性能了,為了少耗費(fèi)性能而拉長時間間隔,但數(shù)據(jù)又總是更新不及時。這樣這個方式就被待定了。
這時了解到有一個專門用來監(jiān)聽本地存儲的數(shù)據(jù)變化的事件為Storage事件:Web Storage API內(nèi)建了一套事件通知機(jī)制,當(dāng)存儲區(qū)域的內(nèi)容發(fā)生改變(包括增加、修改、刪除數(shù)據(jù))時,就會自動觸發(fā) storage 事件,并把它發(fā)送給所有感興趣的監(jiān)聽者。所有支持 localStorage 的瀏覽器都支持 storage 事件,包括 IE8。但I(xiàn)E 8不支持 W3C 標(biāo)準(zhǔn)的 addEventListener。因此,為了監(jiān)聽 storage 事件,還需要檢測瀏覽器支持哪種事件機(jī)制:
if (window.addEventListener) {
window.addEventListener("storage", handleStorage, false);
} else {
window.attachEvent("onstorage", handleStorage);
}
有了這個storage事件,跨頁面通信就變得很容易了:
<!--發(fā)送數(shù)據(jù)頁面-->
<template>
<div class="home">
<h1>發(fā)送數(shù)據(jù)頁面</h1>
<input type="text" @input="input" v-model="value"/>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
value: 'test'
}
},
methods: {
input () {
localStorage.setItem("test", this.value)
}
},
created () {
localStorage.setItem("test", this.value)
}
}
</script>
<!--接收數(shù)據(jù)頁面-->
<template>
<div class="about">
<h1>接收數(shù)據(jù)頁面</h1>
獲取到的值:{{value}}
</div>
</template>
<script>
export default {
name: 'about',
data () {
return {
value: ''
}
},
created () {
window.addEventListener("storage", e => {
if (e.key === "test") {
this.value = e.newValue
}
})
}
}
</script>