您好,登錄后才能下訂單哦!
這篇文章主要介紹了vue中如何實現非父子組件的通信,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
Provide
和Inject
用于非父子組件之間共享數據,比如有一些深度嵌套的組件,子組件想要獲取父組件的數據,如果不存在Provide和Inject選項,我們可以通過props進行一次傳遞數據,但是這樣做太過于繁瑣。
對于上述情況,我們可以使用Provide
和Inject
無論組件結構嵌套有多深,父組件都可以作為子組件數據的提供者。
父組件存在Provide
來提供數據。
子組件存在Inject
來獲取數據。
在實際過程中,父組件不知道哪個子組件使用其數據,子組件也不知道使用的是哪個父組件的數據。
Provide和Inject的基本使用
//父組件 <template> <div> <Content></Content> </div> </template> <script> import Content from "./components/Content.vue"; export default { data() { return {}; }, provide:{ name:"張三", age:20 }, components: { Content } }; </script> <style scoped></style>
//子組件 <template> <div> <h2>這里是Content組件</h2> <h2>{{ name }} -- {{age}}</h2> <ContentBase></ContentBase> </div> </template> <script> import ContentBase from "./ContentBase.vue"; export default { data() { return {}; }, components: { ContentBase }, inject:["name", "age"] }; </script> <style scoped></style>
//孫組件 <template> <div> <h2>這里是contentBase組件</h2> <h2>{{name}} -- {{age}}</h2> </div> </template> <script> export default { data() { return {}; }, inject: ["name", "age"] }; </script> <style scoped> </style>
最終顯示結果為:
我們思考一種情況,如果Provide
拿到的數據,是從data
拿到的數據,此時如果獲取? 此時this
可以使用嗎?
<template> <div> <Content></Content> </div> </template> <script> import Content from "./components/Content.vue"; export default { data() { return { source: ["111","222", "333"] }; }, provide:{ name:"張三", age:20, res: this.source.length //我們在此時增加res,想要通過this.source.length拿到數組的長度 }, components: { Content } }; </script> <style scoped></style>
該結果是錯誤的。
報錯信息顯示,我們從undefined上讀取屬性,此時this為undefined。原因:從上面代碼我們可以看出,this指向的是undefiend(因為this執行最外層)。
解決方法
我們將Provide設置為一個函數,并且返回一個對象,如下代碼所示:
<template> <div> <Content></Content> </div> </template> <script> import Content from "./components/Content.vue"; export default { data() { return { source: ["111", "222", "333"], }; }, provide() { return { name: "張三", age: 20, res: this.source.length, }; }, components: { Content, }, }; </script> <style scoped></style>
顯示結果:
此時我們再思考一個問題,如果我們向data數組中新增一個元素,在其他地方獲取的數組長度會跟隨變化嗎?
<template> <div> <Content></Content> <button @click="addOneItem">點擊</button> </div> </template> <script> import Content from "./components/Content.vue"; export default { data() { return { source: ["111", "222", "333"], }; }, provide() { return { name: "張三", age: 20, res: this.source.length, }; }, components: { Content, }, methods:{ //在這里添加點擊事件 addOneItem() { this.source.push("nnn") console.log(this.source) } } }; </script> <style scoped></style>
結果如上圖所示,可以看到數據是被添加進去的,但是子組件并沒有檢測到數據的變化。
此時我們可以使用computed
來檢測this.source.length
的變化,使用代碼如下所示。
<template> <div> <Content></Content> <button @click="addOneItem">點擊</button> </div> </template> <script> import Content from "./components/Content.vue"; import { computed } from "vue" //從vue中引入computed export default { data() { return { source: ["111", "222", "333"], }; }, provide() { return { name: "張三", age: 20, res: computed(() => this.source.length), //在這里添加computed }; }, components: { Content, }, methods:{ addOneItem() { this.source.push("nnn") console.log(this.source) } } }; </script> <style scoped></style>
因為我們通過computed
獲取的是一個對象,此時我們通過value
屬性拿到值。
在vue2時,如果我們使用事件總線可以使用this.$bus = new Vue()也就是實例化一個vue對象。但是我們在vue3中不能這樣用。所以我們采用第三方庫來實現組件之間的通信。這個第三方庫為mitt
一、安裝
npm install mitt
在文件中引入并且進行初始化導出。
import mitt from "mitt"; const emitter = new mitt() export default emitter
監聽事件,第一個參數是事件名,第二個參數是回調函數。
emitter.on("why", (data) => { console.log(data) }) //*表示可以監聽全部的事件。 emitter.on("*", (type, data) => { console.log(type, data) })
取消事件
//取消emitter中所有的監聽 emitter.all.clear() //或者 //定義一個函數 function onFoo(){} emitter.on("foo", onFoo) emitter.on("foo", onFoo)
感謝你能夠認真閱讀完這篇文章,希望小編分享的“vue中如何實現非父子組件的通信”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。