2023 Vue直播班筆記 - 跨層級資料傳遞 provide(含是否有響應式及雷區)

更新於 發佈於 閱讀時間約 14 分鐘
此筆記僅以個人理解方式記錄

前言

VUE為單向資料流的框架,在鄰近層級之間我們可以依靠 props 由父層向子層來傳遞需要的資料,然而遇到跨層級的架構時,雖然也是可以一層層傳進去,只是這會造成多餘的處理及凌亂的程式碼,因此才有了 "provide" 來解決我們跨層級的需求。


層級展示圖

raw-image
raw-image


程式碼區塊(非響應寫法)

先準備範例

<div id="app"> //根元件
<div class="container my-5 py-3">
<div class="btn-group d-block text-center" role="group" aria-label="Basic example">
<button type="button" class="btn btn-primary">Left</button>
<button type="button" class="btn btn-success">Middle</button>
<button type="button" class="btn btn-danger">Right</button>
<button type="button" class="btn btn-dark">{{text}}</button>
</div>
<card></card>
</div>
</div>
<script type="module" src="./index.js"></script>
//index.js
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
import { card } from "./templates.js";

const app = createApp({
data() {
return {
text: '我是最外層的text,我要被傳入最內層'
}
},
components: {
card
}
})
app.mount('#app')
//templates.js
const listGroups = {
template: `
<ul class="list-group ps-0">
<li class="list-group-item" aria-current="true">An active item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
<li class="list-group-item">A fourth item</li>
<li class="list-group-item">And a fifth one</li>
</ul>
`
}

const card = {
template: `
<div class="card my-3">
<div class="row">
<div class="col-md-4">
<img src="https://fluv.com/blog/wp-content/uploads/sites/2/2023/08/%E6%9C%AA%E5%91%BD%E5%90%8D%E8%A8%AD%E8%A8%88-9.png" class="img-fluid rounded-start" alt="貓咪">
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<listGroups></listGroups>
</div>
</div>
</div>
`,
components: {
listGroups
}
}

export { card }


架好後就開始展現跨層級用法

1.在外層加入 provide

raw-image


2.內層元件補上 inject

raw-image


3.這樣就實現了跨層級功能了,如下圖。

raw-image


響應式寫法僅差別在於provide寫法,而這裡面也有個地方要注意

-非響應寫法,很直接能看出要傳入甚麼資訊

//非響應
provide:{
text: '我是最外層的text,我要被傳入最內層'
},

//題外話(雷點分享)
//剛接觸響應時以為只要改成return function就會響應
//這樣其實也只會單純傳入而已哦
provide(){
return {
text: '我是最外層的text,我要被傳入最內層'
}
},


-再來說說響應,對我來說有兩種意思

1.外層provide更動時,連帶內層注入的inject一同更動
2.內層利用"物件傳參考特性",來達到修改內層進而影響外層

我們稍微調整下程式碼方便展示

利用computed

<div id="app">
<div class="container my-5 py-3">
<div class="btn-group d-block text-center" role="group" aria-label="Basic example">
<button type="button" class="btn btn-primary">Left</button>
<button type="button" class="btn btn-success">Middle</button>
<input type="text"class="btn btn-light" v-model="text" placeholder="請輸入文字">
<button type="button" class="btn btn-dark">{{text}}</button>
</div>
<card></card>
</div>
</div>
<script type="module" src="./index.js"></script>
//index.js
import {createApp,computed} from "https://unpkg.com/vue@3/dist/vue.esm-browser.js";
import {card} from "./templates.js";
const app = createApp({
data() {
return {
text: "測試響應",
};
},
//響應
provide() {
return {
text: computed(() => this.text),
};
},
components: {
card,
},
});
app.mount("#app");
//templates.js
const listGroups = {
template: `
<ul class="list-group ps-0">
<li class="list-group-item" aria-current="true">An active item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
<li class="list-group-item">A fourth item</li>
<li class="list-group-item">顯示inject => {{text}}</li>
</ul>
`,
inject:['text'],
}

const card = {
template: `
<div class="card my-3">
<div class="row">
<div class="col-md-4">
<img src="https://fluv.com/blog/wp-content/uploads/sites/2/2023/08/%E6%9C%AA%E5%91%BD%E5%90%8D%E8%A8%AD%E8%A8%88-9.png" class="img-fluid rounded-start" alt="貓咪">
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<listGroups></listGroups>
</div>
</div>
</div>
`,
components: {
listGroups
}
}

export { card }


raw-image


利用物件傳參考特性

<div id="app">
<div class="container my-5 py-3">
<div class="btn-group d-block text-center" role="group" aria-label="Basic example">
<button type="button" class="btn btn-primary">Left</button>
<button type="button" class="btn btn-success">Middle</button>
<button type="button" class="btn btn-danger">{{obj}}</button>
<button type="button" class="btn btn-dark">{{text}}</button>
</div>
<card></card>
</div>
</div>
<script type="module" src="./index.js"></script>
//index.js
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
import { card } from './templates.js'
const app = createApp({
data() {
return {
text: '我是最外層的text,我要被傳入最內層',
obj:{
name:'小明',
age:18
}
}
},
//響應
provide() {
return {
text: this.text,
obj:this.obj
}
},
components: {
card
}
})
app.mount('#app')
//templates.js
const listGroups = {
template: `
<ul class="list-group ps-0">
<li class="list-group-item" aria-current="true">An active item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
<li class="list-group-item">A fourth item</li>
<li class="list-group-item">顯示inject => {{text}}</li>
<li class="list-group-item">顯示inject => {{obj}}</li>
</ul>
`,
inject:['text','obj'],
//更改
created(){
this.text = '我是text,我被更改了'
this.obj.age = 20
}
}

const card = {
template: `
<div class="card my-3">
<div class="row">
<div class="col-md-4">
<img src="https://fluv.com/blog/wp-content/uploads/sites/2/2023/08/%E6%9C%AA%E5%91%BD%E5%90%8D%E8%A8%AD%E8%A8%88-9.png" class="img-fluid rounded-start" alt="貓咪">
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<listGroups></listGroups>
</div>
</div>
</div>
`,
components: {
listGroups
}
}

export { card }


我們可以看到如果是 "利用物件傳參考" 的方式跟 "一般傳值" 的方式的差別,text 雖然也有在子組件做修改的動作,但影響範圍也只侷限在該組件上。

raw-image


最後感謝卡斯伯老師的指點,才能順利釐清。
raw-image


  • joker
  • 2024/03/20
留言
avatar-img
留言分享你的想法!
avatar-img
Joker Cat
3會員
21內容數
是一隻喜愛前端勇往直前的霹靂酷樂貓
Joker Cat的其他內容
2024/06/04
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
2024/06/04
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
2024/06/03
我們在實作中,難免會遇到在不同組件中,卻有需求相同的資料格式,因此 mixins 可以達到我們的需求,除了 data 以外也包含了 methods 可以共用,舉例來說,學生資料可能會在,班級跟社團內被使用,當我們要撰寫元件時,就可以省略多餘的 data 定義。
Thumbnail
2024/06/03
我們在實作中,難免會遇到在不同組件中,卻有需求相同的資料格式,因此 mixins 可以達到我們的需求,除了 data 以外也包含了 methods 可以共用,舉例來說,學生資料可能會在,班級跟社團內被使用,當我們要撰寫元件時,就可以省略多餘的 data 定義。
Thumbnail
2024/05/30
自訂元件生成位置顧名思義就是可以指定部分HTML區塊渲染在特定的畫面上,即使在不同組件也能把A組件內的部分畫面,展現在B組件上,以下方程式舉例。
Thumbnail
2024/05/30
自訂元件生成位置顧名思義就是可以指定部分HTML區塊渲染在特定的畫面上,即使在不同組件也能把A組件內的部分畫面,展現在B組件上,以下方程式舉例。
Thumbnail
看更多
你可能也想看
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
先前提到 Quasar 的 Dialog Plugin 很好用,再讓我補充一個用法。
Thumbnail
先前提到 Quasar 的 Dialog Plugin 很好用,再讓我補充一個用法。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
VUE為單向資料流的框架,在鄰近層級之間我們可以依靠 props 由父層向子層來傳遞需要的資料,然而遇到跨層級的架構時,雖然也是可以一層層傳進去,只是這會造成多餘的處理及凌亂的程式碼,因此才有了 "provide" 來解決我們跨層級的需求。 層級展示圖
Thumbnail
VUE為單向資料流的框架,在鄰近層級之間我們可以依靠 props 由父層向子層來傳遞需要的資料,然而遇到跨層級的架構時,雖然也是可以一層層傳進去,只是這會造成多餘的處理及凌亂的程式碼,因此才有了 "provide" 來解決我們跨層級的需求。 層級展示圖
Thumbnail
自訂元件生成位置顧名思義就是可以指定部分HTML區塊渲染在特定的畫面上,即使在不同組件也能把A組件內的部分畫面,展現在B組件上,以下方程式舉例。
Thumbnail
自訂元件生成位置顧名思義就是可以指定部分HTML區塊渲染在特定的畫面上,即使在不同組件也能把A組件內的部分畫面,展現在B組件上,以下方程式舉例。
Thumbnail
Vue.js是一種基於MVVM的前端JavaScript框架,類似的框架有React、Angular等。 架設環境 安裝Visual Studio Code(https://code.visualstudio.com/) 安裝Node.js(https://nodejs.org/en/
Thumbnail
Vue.js是一種基於MVVM的前端JavaScript框架,類似的框架有React、Angular等。 架設環境 安裝Visual Studio Code(https://code.visualstudio.com/) 安裝Node.js(https://nodejs.org/en/
Thumbnail
2023 Vue直播班筆記 - 動態路由Props,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
Thumbnail
2023 Vue直播班筆記 - 動態路由Props,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
Thumbnail
Vue Router 動態路由,假設有一個賣場,裡面有 100 個商品,我們不可能針對它們創 100 對應的路由,因此我們需要一個動態路由,利用"路徑帶參數"的方式來撈取商品的資訊。
Thumbnail
Vue Router 動態路由,假設有一個賣場,裡面有 100 個商品,我們不可能針對它們創 100 對應的路由,因此我們需要一個動態路由,利用"路徑帶參數"的方式來撈取商品的資訊。
Thumbnail
Vue Router 及 具名視圖,擺脫以往切換依賴 CSS display:none 跟 display:block 互相配合,有時還得搭配 z-index 來調整層級跟 opacity 透明度的麻煩,而 Vue Router 完美的解決了這棘手的問題,且能客製頁面想要呈現的擺飾。
Thumbnail
Vue Router 及 具名視圖,擺脫以往切換依賴 CSS display:none 跟 display:block 互相配合,有時還得搭配 z-index 來調整層級跟 opacity 透明度的麻煩,而 Vue Router 完美的解決了這棘手的問題,且能客製頁面想要呈現的擺飾。
Thumbnail
這系列是我在 2023 六角學院 Vue作品實戰班的筆記,筆記以本人理解的方式記錄。此篇主題為 Slot Props 進階應用 ,其中包含單筆資料、多筆資料。
Thumbnail
這系列是我在 2023 六角學院 Vue作品實戰班的筆記,筆記以本人理解的方式記錄。此篇主題為 Slot Props 進階應用 ,其中包含單筆資料、多筆資料。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News