Vue中如果不透過v-model實現雙向綁定?以下這篇文章跟大家介紹一下不使用v-model,實現雙向綁定的方法,希望對大家有幫助!
不使用v-model,如何實現雙向綁定?
有人說,這種小白問題,也好意思問?
你別說,我初學vue的時候,可是被這些問題折磨得死去活來的,硬著頭皮照著官網文檔demo寫,會用之後,日常開發也寫出過很多跟v-model相關的bug,後來下定決心仔細研究一下之後,才發現這裡面的門道還有點多,且聽我細細講來。 【相關推薦:vue.js影片教學】
先來看解答:
<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 事件改變綁定值來實現雙向綁定。
換句話說,v-model只是一種簡寫形式而已
事實上,v-model 的本質就是語法糖,它負責監聽用戶的輸入事件以更新數據,並對一些極端場景進行一些特殊處理。 -- 官方文件
v-model 在內部為不同的輸入元素使用不同的property 並拋出不同的事件:
- text 和textarea 元素使用
value
property 和input
事件;- checkbox 和radio 使用
checked
property 和change
事件;- select 欄位將
value
作為prop 並將change
作為事件。
與本題相關聯的知識延伸
- 雙向綁定
- 單向資料綁定
- vue 元件之間互動的單向資料流
問:什麼是雙向綁定?
雙向綁定就是當資料變更之後,視圖同步更新,當視圖變更之後,資料也會更新。
問:什麼是單向資料綁定?
#單向資料綁定就是當資料變更之後,視圖同步更新,當視圖變更之後,資料不會更新。
在vue中是透過指令v-model 來實現雙向綁定,透過v-bind
來實作單向資料綁定
#看完下面這段程式碼和這段程式碼運行的gif演示,你就能明白他們的差別了。
<template> <div> <p>双向绑定</p> <input v-model="msg" placeholder="edit me" /> <p>{{ msg }}</p> <p>单向数据绑定</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,當資料變更之後,視圖同步更新,當視圖變更之後,資料也會更新,這就是雙向綁定。
使用 v-bind,當資料變更之後,視圖同步更新,當視圖變更之後,資料不會更新,這就是單向資料綁定。
問:什麼是 vue 單向資料流?
子元件不能改變父元件傳遞給它的 prop 屬性,建議的做法是它拋出事件,通知父元件自行改變綁定的值。
總結起來就是資料向下,事件向上。
vue 文件在介紹 Prop 時就提出了單向資料流的概念,點擊此處 查看 vue 文件對單向資料流的說明。
所有的prop 都使得其父子prop 之間形成了一個單向下行綁定:父級prop 的更新會向下流動到子元件中,但反過來則不行。這樣會防止從子元件意外變更父級元件的狀態,從而導致你的應用的資料流向難以理解。
額外的,每次父級元件發生變更時,子元件中所有的 prop 都會刷新為最新的值。這表示你不應該在一個子元件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制台中發出警告。
我們看下面這個範例:
子元件直接對 prop 值做雙向綁定,會發生什麼事?
父元件程式碼:
<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 值可以实现双向绑定,但是 FatherComponent 中的 data 值并未发生改变,而且控制台抛出了警告:
[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 值,因为每当父组件重新渲染时,该值将被覆盖。相反,使用基于 prop 值的 data 或 computed。
很显然,直接改变子组件的 prop 值的这种行为被 vue 禁止了。
如何操作传入子组件的 prop 值
但是很多时候,我们确实要操作传入子组件的 prop 值,该怎么办呢?
正如上面的警告所说,有两种办法:
- 这个 prop 用来传递一个初始值,定义一个本地的 data property 并将这个 prop 用作其初始值
props: { initialCounter: { type: Number, default: 0 }, }, data() { return { counter: this.initialCounter } }
- 这个 prop 以一种原始的值传入且需要进行转换,用这个 prop 的值来定义一个计算属性
props: { size: { type: String, default: '' } }, computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
这样不管怎么操作数据都是操作的子组件数据了,不会影响到父组件数据。
所以,我们想用 prop 传入的数据实现双向绑定,可以这么写:
父组件代码不变
子组件里用 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 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。
还是上面的例子,我们将传入的值改为对象:
父组件代码:
<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
实际上还是指向了父组件的数据,对 innerObj.name
的修改依然会影响到父组件
所以,处理这种引用类型数据的时候,需要深拷贝一下
import { clone } from 'xe-utils' export default { name: 'child-component', props: { obj: { type: Object, default: () => {} } }, data() { return { innerObj: clone(this.obj, true) } } }
如上图所示,这样子组件和父组件之间的数据就不会互相影响了。
总结
至此,终于把双向绑定和单向数据流讲清楚了,真的没想到,平时开发时都懂的概念,想讲清楚居然花了这么多篇幅,确实不容易,不过,这也是对自己的一种锻炼吧。
问:v-model是双向绑定吗?
是,但只是语法糖
问:v-model是单向数据流吗?
是,数据向下,事件向上
本题还有一些其他问法,比如:
- vue 的双向绑定和单向数据流有什么区别?
- 为什么说 vue 的双向绑定和单向数据流不冲突?
看完本篇文章,相信不管怎么问,你都能对这两个概念理解透彻了。
更多编程相关知识,请访问:编程入门!!
以上是聊聊Vue中如果不透過v-model實現雙向綁定?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

vue中props可以传递函数;vue中可以将字符串、数组、数字和对象作为props传递,props主要用于组件的传值,目的为了接收外面传过来的数据,语法为“export default {methods: {myFunction() {// ...}}};”。

本篇文章带大家聊聊vue指令中的修饰符,对比一下vue中的指令修饰符和dom事件中的event对象,介绍一下常用的事件修饰符,希望对大家有所帮助!

如何覆盖组件库样式?下面本篇文章给大家介绍一下React和Vue项目中优雅地覆盖组件库样式的方法,希望对大家有所帮助!

react与vue的虚拟dom没有区别;react和vue的虚拟dom都是用js对象来模拟真实DOM,用虚拟DOM的diff来最小化更新真实DOM,可以减小不必要的性能损耗,按颗粒度分为不同的类型比较同层级dom节点,进行增、删、移的操作。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

記事本++7.3.1
好用且免費的程式碼編輯器

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。