您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“Vue中不通過v-model怎么實現(xiàn)雙向綁定”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Vue中不通過v-model怎么實現(xiàn)雙向綁定”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。
先來看解答:
<template> <div class="test-v-model"> <p>使用v-model</p> <input v-model="msg" placeholder="edit me" /> <p>{{ msg }}</p> <p>不使用v-model</p> <input :value="msg1" @input="handleInput" placeholder="edit me" /> <p>{{ msg1 }}</p> </div> </template> <script> export default { name: 'test-v-model', data() { return { msg: '', msg1: '' } }, methods: { handleInput(e) { this.msg1 = e.target.value } } } </script>
不使用 v-model,就需要通過 value 屬性綁定值和 input 事件改變綁定值來實現(xiàn)雙向綁定。
換句話說,v-model只是一種簡寫形式而已
事實上,v-model 的本質(zhì)就是語法糖,它負(fù)責(zé)監(jiān)聽用戶的輸入事件以更新數(shù)據(jù),并對一些極端場景進行一些特殊處理。 -- 官方文檔
v-model 在內(nèi)部為不同的輸入元素使用不同的 property 并拋出不同的事件:
text 和 textarea 元素使用
value
property 和input
事件;checkbox 和 radio 使用
checked
property 和change
事件;select 字段將
value
作為 prop 并將change
作為事件。
雙向綁定
單向數(shù)據(jù)綁定
vue 組件之間交互的單向數(shù)據(jù)流
問:什么是雙向綁定?
雙向綁定就是當(dāng)數(shù)據(jù)變化之后,視圖同步更新,當(dāng)視圖變化之后,數(shù)據(jù)也會更新。
問:什么是單向數(shù)據(jù)綁定?
單向數(shù)據(jù)綁定就是當(dāng)數(shù)據(jù)變化之后,視圖同步更新,當(dāng)視圖變化之后,數(shù)據(jù)不會更新。
在vue中是通過指令 v-model 來實現(xiàn)雙向綁定,通過 v-bind
來實現(xiàn)單向數(shù)據(jù)綁定
看完下面這段代碼和這段代碼運行的gif演示,你就能明白他們的區(qū)別了。
<template> <div> <p>雙向綁定</p> <input v-model="msg" placeholder="edit me" /> <p>{{ msg }}</p> <p>單向數(shù)據(jù)綁定</p> <input v-bind:value="msg1" placeholder="edit me" /> <p>{{ msg1 }}</p> </div> </template> <script> export default { name: 'test-v-model', data() { return { msg: '', msg1: '' } } } </script>
從gif圖中可以看出,使用 v-model,當(dāng)數(shù)據(jù)變化之后,視圖同步更新,當(dāng)視圖變化之后,數(shù)據(jù)也會更新,這就是雙向綁定。
使用 v-bind,當(dāng)數(shù)據(jù)變化之后,視圖同步更新,當(dāng)視圖變化之后,數(shù)據(jù)不會更新,這就是單向數(shù)據(jù)綁定。
問:什么是 vue 單向數(shù)據(jù)流?
子組件不能改變父組件傳遞給它的 prop 屬性,推薦的做法是它拋出事件,通知父組件自行改變綁定的值。
總結(jié)起來就是數(shù)據(jù)向下,事件向上。
vue 文檔在介紹 Prop 時就提出了單向數(shù)據(jù)流的概念,點擊此處 查看 vue 文檔對單向數(shù)據(jù)流的說明。
所有的 prop 都使得其父子 prop 之間形成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,但是反過來則不行。這樣會防止從子組件意外變更父級組件的狀態(tài),從而導(dǎo)致你的應(yīng)用的數(shù)據(jù)流向難以理解。
額外的,每次父級組件發(fā)生變更時,子組件中所有的 prop 都將會刷新為最新的值。這意味著你不應(yīng)該在一個子組件內(nèi)部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制臺中發(fā)出警告。
我們看下面這個例子:
子組件直接對 prop 值做雙向綁定,會發(fā)生什么?
父組件代碼:
<template> <child-component :value="fatherValue" /> </template> <script> import ChildComponent from './child.vue' export default { name: 'father-component', components: { ChildComponent }, data() { return { fatherValue: '' } } } </script>
子組件代碼:
<template> <div class="child-component"> <input v-model="value" placeholder="edit me" /> <p>{{ value }}</p> </div> </template> <script> export default { name: 'child-component', props: { value: { type: String, default: '' } } } </script>
可以看到,childComponent中的 prop 值可以實現(xiàn)雙向綁定,但是 FatherComponent 中的 data 值并未發(fā)生改變,而且控制臺拋出了警告:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"
翻譯一下:避免直接改變 prop 值,因為每當(dāng)父組件重新渲染時,該值將被覆蓋。相反,使用基于 prop 值的 data 或 computed。
很顯然,直接改變子組件的 prop 值的這種行為被 vue 禁止了。
如何操作傳入子組件的 prop 值
但是很多時候,我們確實要操作傳入子組件的 prop 值,該怎么辦呢?
正如上面的警告所說,有兩種辦法:
這個 prop 用來傳遞一個初始值,定義一個本地的 data property 并將這個 prop 用作其初始值
props: { initialCounter: { type: Number, default: 0 }, }, data() { return { counter: this.initialCounter } }
這個 prop 以一種原始的值傳入且需要進行轉(zhuǎn)換,用這個 prop 的值來定義一個計算屬性
props: { size: { type: String, default: '' } }, computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
這樣不管怎么操作數(shù)據(jù)都是操作的子組件數(shù)據(jù)了,不會影響到父組件數(shù)據(jù)。
所以,我們想用 prop 傳入的數(shù)據(jù)實現(xiàn)雙向綁定,可以這么寫:
父組件代碼不變
子組件里用 innerValue 來接收傳入的 value :
<template> <div class="child-component"> <input v-model="innerValue" placeholder="edit me" /> <p>{{ innerValue }}</p> </div> </template> <script> export default { name: 'child-component', props: { value: { type: String, default: '' } }, data() { return { innerValue: this.value } } } </script>
這里要注意一個問題
在 JavaScript 中對象和數(shù)組是通過引用傳入的,所以對于一個數(shù)組或?qū)ο箢愋偷?prop 來說,在子組件中改變變更這個對象或數(shù)組本身將會影響到父組件的狀態(tài)。
還是上面的例子,我們將傳入的值改為對象:
父組件代碼:
<template> <child-component :obj="fatherObj" /> </template> <script> import ChildComponent from './child.vue' export default { name: 'father-component', components: { ChildComponent }, data() { return { fatherObj: { name: 'lin' } } } } </script>
子組件代碼:
<template> <div class="child-component"> <input v-model="innerObj.name" placeholder="edit me" /> <p>{{ innerObj.name }}</p> </div> </template> <script> export default { name: 'child-component', props: { obj: { type: Object, default: () => {} } }, data() { return { innerObj: this.obj } } } </script>
這里的 this.obj
是引用類型,賦值給了 innerObj
,所以 innerObj
實際上還是指向了父組件的數(shù)據(jù),對 innerObj.name
的修改依然會影響到父組件
所以,處理這種引用類型數(shù)據(jù)的時候,需要深拷貝一下
import { clone } from 'xe-utils' export default { name: 'child-component', props: { obj: { type: Object, default: () => {} } }, data() { return { innerObj: clone(this.obj, true) } } }
如上圖所示,這樣子組件和父組件之間的數(shù)據(jù)就不會互相影響了。
讀到這里,這篇“Vue中不通過v-model怎么實現(xiàn)雙向綁定”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。