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
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
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,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News