Vue provide跨層級資料傳遞
通常,當我們需要將數據從父組件傳遞給子組件時,我們會使用props
,但當是一個大型組件樹時,要將父組件資料傳遞給比較深層的組件時,如果僅使用 props
,我們將不得不在整個父鏈中傳遞相同的 props
。
所以我們可以使用Provide
(提供) / Inject
(注入)來解決問題
假設我們有一個三層的組件樹,要將資料從父組件傳遞至user
組件,使用Provide
傳遞資料
Provide
Options API
非響應式:
export default { provide:{ user:{ name: '小明', uuid: 78163 } }, }
|
響應式:
export default { data() { return { user: { name: '小明', uuid: 78163 } } }, provide(){ return { user: this.user } }, }
|
Composition API
非響應式:
<script setup> import { ref, provide } from 'vue'
provide('foo', 'bar') </script>
|
響應式:
<script setup> import { ref, provide } from 'vue'
const count = ref(0) provide('count', count) </script>
|
Inject
Options API
再使用Inject
注入
export default { inject: ['user'], created() { console.log(this.user) } }
|
Composition API
<script setup> import { inject } from 'vue'
const foo = inject('foo')
const count = inject('count')
</script>
|
注入資料更改名稱
export default { inject: { localMessage: { from: 'user' } }, created() { console.log(this.user); } }
|
更改
範例
Options API
非響應式範例:
以下範例更改inject
接收的資料,會發現資料不是響應式的,在card
元件中的名子還是父組件傳遞的資料
<html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.2/vue.global.js"></script> </head> <body class="bg-lighter">
<div id="app"> <card></card> </div>
<script> const user = { template: `<div> user 元件:<br /> 姓名: {{ user.name }}, <br /> uuid: {{ user.uuid }} </div>`, inject: ['user'], created() { console.log(this.user);
this.user.name = '小美'; } }
const app = Vue.createApp({ data() { return { user: { name: '小明', uuid: 78163 } } }, provide:{ user:{ name: '小明', uuid: 78163 } }, })
app.component('card', { data() { return { title: '文件標題', content: '文件內文', toggle: false } }, components: { user }, inject: ['user'], template: ` <div class="card" style="width: 18rem;"> <div className="card-header">card 元件,姓名{{ user.name }}</div> <div class="card-body"> <user></user> </div> </div> `, });
app.mount('#app'); </script> </body> </html>
|
響應式範例:
可以看到更改的資料都被調整
<html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.2/vue.global.js"></script> </head> <body class="bg-lighter">
<div id="app"> <card></card> </div>
<script> const user = { template: `<div> user 元件:<br /> 姓名: {{ user.name }}, <br /> uuid: {{ user.uuid }} </div>`, inject: ['user'], created() { console.log(this.user);
this.user.name = '小美'; } }
const app = Vue.createApp({ data() { return { user: { name: '小明', uuid: 78163 } } }, provide(){ return { user: this.user } }, })
app.component('card', { data() { return { title: '文件標題', content: '文件內文', toggle: false } }, components: { user }, inject: ['user'], template: ` <div class="card" style="width: 18rem;"> <div className="card-header">card 元件,姓名{{ user.name }}</div> <div class="card-body"> <user></user> </div> </div> `, });
app.mount('#app'); </script> </body> </html>
|
Composition API
非響應式
<html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.2/vue.global.js"></script> </head> <body class="bg-lighter">
<div id="app"> <card > </card> </div> <script type="module"> const { createApp, ref, provide, inject } = Vue;
const card = { template: `<div class="card" style="width: 18rem;"> <div class="card-body"> <h5 class="card-title">{{ person.name }}</h5> <input type="text" v-model="person.name"> </div> </div>`, setup(props) {
const person = inject('person');
return { person } } }
const app = createApp({ components: { card, }, setup(props) { const person = { name: 'Joe' };
provide('person', person);
return { person, } }, });
app.mount('#app') </script> </body> </html>
|
響應式
<html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.2/vue.global.js"></script> </head> <body class="bg-lighter">
<div id="app"> <card > </card> </div> <script type="module"> const { createApp, ref, provide, inject } = Vue;
const card = { template: `<div class="card" style="width: 18rem;"> <div class="card-body"> <h5 class="card-title">{{ person.name }}</h5> <input type="text" v-model="person.name"> </div> </div>`, setup(props) {
const person = inject('person');
return { person } } }
const app = createApp({ components: { card, }, setup(props) { const person = ref({ name: 'Joe' });
provide('person', person);
return { person, } }, });
app.mount('#app') </script> </body> </html>
|