Vue中實現(xiàn)父子組件雙向數(shù)據(jù)流的三種方案分享
1. 背景
通常情況下,父子組件的通信都是單向的,或父組件使用props
向子組件傳遞數(shù)據(jù),或子組件使用emit
函數(shù)向父組件傳遞數(shù)據(jù)。
但在有些場景下,免不了需要父子組件之間進行雙向數(shù)據(jù)流,從而讓我們的業(yè)務(wù)代碼更加簡潔。很常見的場景之一:父組件引入了一個子組件,子組件是個dialog
彈窗,在父組件可以點擊某個按鈕顯示dialog
,但是dialog
組件的關(guān)閉操作是在組件里面的。這個時候使用雙向數(shù)據(jù)流管理dialog
組件的顯隱狀態(tài),不僅讓代碼顯得優(yōu)雅,還能少寫不少業(yè)務(wù)。
那我們能不能直接在子組件修改props
來實現(xiàn)上述功能呢?當(dāng)然是不行的,因為在Vue
中props
屬性是只讀的。官方文檔給出的解釋如下:
所有的 props 都遵循著單向綁定原則,props 因父組件的更新而變化,自然地將新的狀態(tài)向下流往子組件,而不會逆向傳遞。這避免了子組件意外修改父組件的狀態(tài)的情況,不然應(yīng)用的數(shù)據(jù)流將很容易變得混亂而難以理解。本文將嘗試講解Vue中常用的幾種雙向數(shù)據(jù)流的使用。
2. 雙向數(shù)據(jù)流
2.1. 什么是雙向數(shù)據(jù)流
簡而言之,雙向數(shù)據(jù)流就是model
的更新會觸發(fā)view
的更新,view
的更新會觸發(fā)model
的更新,它們的作用是相互的。
tips: 這里只討論父子組件傳值時的雙向數(shù)據(jù)流,對框架數(shù)據(jù)的雙向數(shù)據(jù)流不做展開。
2.2. Vue提供的解決方案
2.2.1. 方案一:v-model
父組件代碼如下:
<template> <div class="container"> <a-button type="primary" @click="handleClick">改變子組件的狀態(tài)</a-button> <p>父組件狀態(tài):{{ message }}</p> <!-- 子組件 --> <child-view v-model="message"></child-view> <!-- 也可以使用多個v-model,子組件里面用props正常接收就可以了 --> <!-- <child-view v-model:message="message" v-model:msg="msg"></child-view> --> </div> </template> <script> import ChildView from '@/components/ChildView.vue' export default { name: 'HomeView', components: { ChildView }, data () { return { message: '' } }, methods: { handleClick () { this.message = '我是用v-model修改的狀態(tài)' } } } </script>
子組件代碼如下:
<template> <div> <a-button type="primary" @click="handleClick">改變父組件的狀態(tài)</a-button> <p>子組件狀態(tài):{{ value }}</p> </div> </template> <script> export default { props: { // 這里框架默認屬性名就是value value: { type: String, default: '' }, // 接收多個props message: { type: String, default: '' }, msg: { type: String, default: '' } }, methods: { handleClick () { // 這里框架默認事件名就是input // 發(fā)送的數(shù)據(jù)會被父級v-model="message"接收到,再被value=message傳回來 this.$emit('input', '我是在子組件里面修改父組件v-model的值') } } } </script>
自定義v-model
的props
屬性:
Vue 允許一個自定義組件在使用 v-model 時定制 prop 和 event。默認情況下,一個組件上的 v-model 會把 value 用作 prop 且把 input 用作 event,但是一些輸入類型比如單選框和復(fù)選框按鈕可能想使用 value prop 來達到不同的目的。使用 model 選項可以回避這些情況產(chǎn)生的沖突。
<template> <div> <a-button type="primary" @click="handleClick">改變父組件的狀態(tài)</a-button> <p>子組件狀態(tài):{{ msg }}</p> </div> </template> <script> export default { // 自定義prop名稱和事件 model: { prop: 'msg', event: 'update' }, props: { msg: { type: String, default: '' } }, methods: { handleClick () { this.$emit('update', '我是在子組件里面修改父組件v-model的值') } } } </script>
瀏覽器運行效果:
2.2.2. 方案二:sync修飾符
父組件代碼如下:
<template> <div class="container"> <a-button type="primary" @click="handleClick">改變子組件的狀態(tài)</a-button> <p>父組件狀態(tài):{{ message }}</p> <child-view :msg.sync="message"></child-view> </div> </template> <script> import ChildView from '@/components/ChildView.vue' export default { name: 'HomeView', components: { ChildView }, data () { return { message: '' } }, methods: { handleClick () { this.message = '十里平湖霜滿天' } } } </script>
子組件代碼如下:
<template> <div> <a-button type="primary" @click="handleClick">改變父組件的狀態(tài)</a-button> <p>子組件狀態(tài):{{ msg }}</p> </div> </template> <script> export default { props: { msg: String }, methods: { handleClick () { this.$emit('update:msg', '寸寸青絲愁華年') } } } </script>
瀏覽器運行效果:
2.2.3. 方案三:通過JS引用類型特性繞過props
父組件代碼如下:
<template> <div class="container"> <a-button type="primary" @click="handleClick">改變子組件的狀態(tài)</a-button> <p>父組件狀態(tài):{{ config.message }}</p> <child-view :config="config"></child-view> </div> </template> <script> import ChildView from '@/components/ChildView.vue' export default { name: 'HomeView', components: { ChildView }, data () { return { config: { message: '' } } }, methods: { handleClick () { this.config.message = '我是用v-model修改的狀態(tài)' } } } </script>
子組件代碼如下:
通過JS引用類型特性繞過props
運行效果和v-model
一樣,這里就不貼圖了。
3. 總結(jié)
Vue
父子組件通信,都是單向的,在需要雙向通信的時候,我們有三種方式達到目的:
- 使用
v-model
- 使用
sync
修飾符 - 通過JS引用類型特性繞過
props
單向數(shù)據(jù)流
以上就是Vue中實現(xiàn)父子組件雙向數(shù)據(jù)流的三種方案分享的詳細內(nèi)容,更多關(guān)于Vue實現(xiàn)父子組件雙向數(shù)據(jù)流的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue全局使用less樣式,組件使用全局樣式文件中定義的變量操作
這篇文章主要介紹了Vue全局使用less樣式,組件使用全局樣式文件中定義的變量操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10elementui時間/日期選擇器選擇禁用當(dāng)前之前(之后)時間代碼實例
當(dāng)我們在進行網(wǎng)頁開發(fā)時,通常需要用到一些日期組件來方便用戶選擇時間,其中element日期組件是一個非常好用的工具,這篇文章主要給大家介紹了關(guān)于elementui時間/日期選擇器選擇禁用當(dāng)前之前(之后)時間的相關(guān)資料,需要的朋友可以參考下2024-02-02vue移動端html5頁面根據(jù)屏幕適配的四種解決方法
在vue移動端h5頁面當(dāng)中,其中適配是經(jīng)常會遇到的問題,這塊主要有四個方法可以適用。這篇文章主要介紹了vue移動端h5頁面根據(jù)屏幕適配的四種方案 ,需要的朋友可以參考下2018-10-10el-table實現(xiàn)轉(zhuǎn)置表格的示例代碼(行列互換)
這篇文章主要介紹了el-table實現(xiàn)轉(zhuǎn)置表格的示例代碼(行列互換),本文結(jié)合示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-02-02vue2和elementUI?實現(xiàn)落日余暉登錄頁和滑塊校驗功能
這篇文章主要介紹了vue2和elementUI打造落日余暉登錄頁和滑塊校驗,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2023-06-06Vue實現(xiàn)路由跳轉(zhuǎn)的3種方式超詳細分解
Vue.js是一款流行的前端JavaScript框架,它提供了多種方式來實現(xiàn)路由跳轉(zhuǎn),下面這篇文章主要給大家介紹了關(guān)于Vue實現(xiàn)路由跳轉(zhuǎn)的3種方式,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2023-12-12