Vue中實現父子組件雙向數據流的三種方案分享
1. 背景
通常情況下,父子組件的通信都是單向的,或父組件使用props向子組件傳遞數據,或子組件使用emit函數向父組件傳遞數據。
但在有些場景下,免不了需要父子組件之間進行雙向數據流,從而讓我們的業(yè)務代碼更加簡潔。很常見的場景之一:父組件引入了一個子組件,子組件是個dialog彈窗,在父組件可以點擊某個按鈕顯示dialog,但是dialog組件的關閉操作是在組件里面的。這個時候使用雙向數據流管理dialog組件的顯隱狀態(tài),不僅讓代碼顯得優(yōu)雅,還能少寫不少業(yè)務。
那我們能不能直接在子組件修改props來實現上述功能呢?當然是不行的,因為在Vue中props屬性是只讀的。官方文檔給出的解釋如下:
所有的 props 都遵循著單向綁定原則,props 因父組件的更新而變化,自然地將新的狀態(tài)向下流往子組件,而不會逆向傳遞。這避免了子組件意外修改父組件的狀態(tài)的情況,不然應用的數據流將很容易變得混亂而難以理解。本文將嘗試講解Vue中常用的幾種雙向數據流的使用。
2. 雙向數據流
2.1. 什么是雙向數據流
簡而言之,雙向數據流就是model的更新會觸發(fā)view的更新,view的更新會觸發(fā)model的更新,它們的作用是相互的。
tips: 這里只討論父子組件傳值時的雙向數據流,對框架數據的雙向數據流不做展開。
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ā)送的數據會被父級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,但是一些輸入類型比如單選框和復選框按鈕可能想使用 value prop 來達到不同的目的。使用 model 選項可以回避這些情況產生的沖突。
<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. 總結
Vue父子組件通信,都是單向的,在需要雙向通信的時候,我們有三種方式達到目的:
- 使用
v-model - 使用
sync修飾符 - 通過JS引用類型特性繞過
props單向數據流
以上就是Vue中實現父子組件雙向數據流的三種方案分享的詳細內容,更多關于Vue實現父子組件雙向數據流的資料請關注腳本之家其它相關文章!
相關文章
Vue全局使用less樣式,組件使用全局樣式文件中定義的變量操作
這篇文章主要介紹了Vue全局使用less樣式,組件使用全局樣式文件中定義的變量操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10
elementui時間/日期選擇器選擇禁用當前之前(之后)時間代碼實例
當我們在進行網頁開發(fā)時,通常需要用到一些日期組件來方便用戶選擇時間,其中element日期組件是一個非常好用的工具,這篇文章主要給大家介紹了關于elementui時間/日期選擇器選擇禁用當前之前(之后)時間的相關資料,需要的朋友可以參考下2024-02-02
vue2和elementUI?實現落日余暉登錄頁和滑塊校驗功能
這篇文章主要介紹了vue2和elementUI打造落日余暉登錄頁和滑塊校驗,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2023-06-06

