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

更新於 2024/06/24閱讀時間約 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
3會員
21內容數
是一隻喜愛前端勇往直前的霹靂酷樂貓
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
Joker Cat 的其他內容
自訂元件生成位置顧名思義就是可以指定部分HTML區塊渲染在特定的畫面上,即使在不同組件也能把A組件內的部分畫面,展現在B組件上,以下方程式舉例。
這次要講的是 $route 及 $router 的區別,看似相似的兩個東西,其實應用時機也大不相同,以下以簡單的幾個例子舉例。
2023 Vue直播班筆記 - 動態路由Props,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
Vue Router 動態路由,假設有一個賣場,裡面有 100 個商品,我們不可能針對它們創 100 對應的路由,因此我們需要一個動態路由,利用"路徑帶參數"的方式來撈取商品的資訊。
Vue Router 及 具名視圖,擺脫以往切換依賴 CSS display:none 跟 display:block 互相配合,有時還得搭配 z-index 來調整層級跟 opacity 透明度的麻煩,而 Vue Router 完美的解決了這棘手的問題,且能客製頁面想要呈現的擺飾。
這系列是我在 2023 六角學院 Vue作品實戰班的筆記,筆記以本人理解的方式記錄。此篇主題為 Slot Props 進階應用 ,其中包含單筆資料、多筆資料。
自訂元件生成位置顧名思義就是可以指定部分HTML區塊渲染在特定的畫面上,即使在不同組件也能把A組件內的部分畫面,展現在B組件上,以下方程式舉例。
這次要講的是 $route 及 $router 的區別,看似相似的兩個東西,其實應用時機也大不相同,以下以簡單的幾個例子舉例。
2023 Vue直播班筆記 - 動態路由Props,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
Vue Router 動態路由,假設有一個賣場,裡面有 100 個商品,我們不可能針對它們創 100 對應的路由,因此我們需要一個動態路由,利用"路徑帶參數"的方式來撈取商品的資訊。
Vue Router 及 具名視圖,擺脫以往切換依賴 CSS display:none 跟 display:block 互相配合,有時還得搭配 z-index 來調整層級跟 opacity 透明度的麻煩,而 Vue Router 完美的解決了這棘手的問題,且能客製頁面想要呈現的擺飾。
這系列是我在 2023 六角學院 Vue作品實戰班的筆記,筆記以本人理解的方式記錄。此篇主題為 Slot Props 進階應用 ,其中包含單筆資料、多筆資料。
你可能也想看
Google News 追蹤
Thumbnail
徵的就是你 🫵 超ㄅㄧㄤˋ 獎品搭配超瞎趴的四大主題,等你踹共啦!還有機會獲得經典的「偉士牌樂高」喔!馬上來參加本次的活動吧!
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
Vue.js是一種基於MVVM的前端JavaScript框架,類似的框架有React、Angular等。 架設環境 安裝Visual Studio Code(https://code.visualstudio.com/) 安裝Node.js(https://nodejs.org/en/
一般而言,組件之間的資料傳遞,可以使用 props 來達成,不過一旦層級過多的時候,props 就要逐層向下傳遞,會越來越麻煩且複雜。 而 provide、inject 可以解決這個問題,它可以提供一個「源頭」,子組件們可以藉由同一個源頭取得對應的資料,且沒有層級分別,都可以取得,就不用逐層傳遞資
當 父組件 有數據想傳送到 子組件 就可以使用props 1​. 父層傳遞設置 可以在父組件的屬性給予一個值,當作要傳送到子組件的資料。 父層組件​ : <!-- App.vue (父組件) --> <template> <div> <ChildComponent greetin
Thumbnail
在 Vue 專案中使用 Apollo Graphql Client 從 API 獲取資料,由於資料結構較為複雜,筆者便跟著網路教學使用 codegen 工具自動化產生 TypeScript 型別定義。在某個元件中,需要使用 defineProps 來撰寫型別定義,結果⋯⋯
Thumbnail
組件之間的通信是 Vue 應用開發中的一個重要方面。Vue 提供了一種名為事件發射(emit)的機制,讓子組件能夠向父組件發送消息。本文將介紹 Vue 中的事件發射(emit)機制,並通過實際範例演示其用法。
Thumbnail
在 Vue 中,組件是構建應用程式的基本單位,而 props 是組件間傳遞資料的主要方式之一,本文將介紹 Vue 中的 props,並通過實際範例展示如何使用 props 實現組件間的資料傳遞。
Thumbnail
在Vue中,v-for指令是用於渲染列表數據。本文將介紹v-for指令的用法,並提供簡單的範例來幫助你理解如何在你的 Vue 應用中有效地使用v-for指令。
Thumbnail
Vue 是尤雨溪所開發的一個前端框架,Vue 提供了響應式數據綁定和組件化的開發模式,能方便開發者構建出具有良好交互性的前端應用。而 Vite 則是一個前端構建工具,用途是提供更快的開發體驗。然後,本文將介紹如何使用 Vite 建立一個 Vue 專案的開發環境,這是你學習 Vue 的第一步。
Thumbnail
徵的就是你 🫵 超ㄅㄧㄤˋ 獎品搭配超瞎趴的四大主題,等你踹共啦!還有機會獲得經典的「偉士牌樂高」喔!馬上來參加本次的活動吧!
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
Vue.js是一種基於MVVM的前端JavaScript框架,類似的框架有React、Angular等。 架設環境 安裝Visual Studio Code(https://code.visualstudio.com/) 安裝Node.js(https://nodejs.org/en/
一般而言,組件之間的資料傳遞,可以使用 props 來達成,不過一旦層級過多的時候,props 就要逐層向下傳遞,會越來越麻煩且複雜。 而 provide、inject 可以解決這個問題,它可以提供一個「源頭」,子組件們可以藉由同一個源頭取得對應的資料,且沒有層級分別,都可以取得,就不用逐層傳遞資
當 父組件 有數據想傳送到 子組件 就可以使用props 1​. 父層傳遞設置 可以在父組件的屬性給予一個值,當作要傳送到子組件的資料。 父層組件​ : <!-- App.vue (父組件) --> <template> <div> <ChildComponent greetin
Thumbnail
在 Vue 專案中使用 Apollo Graphql Client 從 API 獲取資料,由於資料結構較為複雜,筆者便跟著網路教學使用 codegen 工具自動化產生 TypeScript 型別定義。在某個元件中,需要使用 defineProps 來撰寫型別定義,結果⋯⋯
Thumbnail
組件之間的通信是 Vue 應用開發中的一個重要方面。Vue 提供了一種名為事件發射(emit)的機制,讓子組件能夠向父組件發送消息。本文將介紹 Vue 中的事件發射(emit)機制,並通過實際範例演示其用法。
Thumbnail
在 Vue 中,組件是構建應用程式的基本單位,而 props 是組件間傳遞資料的主要方式之一,本文將介紹 Vue 中的 props,並通過實際範例展示如何使用 props 實現組件間的資料傳遞。
Thumbnail
在Vue中,v-for指令是用於渲染列表數據。本文將介紹v-for指令的用法,並提供簡單的範例來幫助你理解如何在你的 Vue 應用中有效地使用v-for指令。
Thumbnail
Vue 是尤雨溪所開發的一個前端框架,Vue 提供了響應式數據綁定和組件化的開發模式,能方便開發者構建出具有良好交互性的前端應用。而 Vite 則是一個前端構建工具,用途是提供更快的開發體驗。然後,本文將介紹如何使用 Vite 建立一個 Vue 專案的開發環境,這是你學習 Vue 的第一步。