所谓父子元件传递资料,就是透过使用 props
和 emits
来完成。而 v-model
只是结合使用 props
和 emits
的语法糖。例如在 input 绑上 v-model
时,背後其实是监听 input 事件,当 input 事件触发,就更新你在 v-model
所指定的值。
套用以上原理,假设我要把子元件里的 input 与父元件的资料实现双向绑定。做法就是:
v-model="你要更新的值"
。在第二步提到的 props,Vue 3 会使用 modelValue
,Vue 2 则需要我们在子元件建立 model
属性来完成。
另外,非常建议大家参考这部分的官方文件,它简单说明了 Vue 2 和 Vue 3的做法。
以下会再详细解说。
我们可以在 input、textarea、select 这些元素上使用 v-model
,双向绑定资料和用户输入的内容。以 input 为例:
<input v-model="text">
data () {
return {
text: 'v-model 绑定的资料'
}
}
仔细想想,这个写法背後的原理就是:
text
里。所以,v-model
其实是由监听 input 事件,以及绑定与更新数值来实现:
<input :value="text" @input="text = $event.target.value"/>
v-model
可以用在父子元件资料传递?神奇的是,以上的写法也可以应用在父子元件,实现双向绑定资料。
假设目前有两个元件,父子关系如下:
App.vue
Child.vue
App.vue(父元件):
data() {
return {
msg: "父层 msg",
};
}
Child.vue (子元件):
<input />
我们想要把父元件的 msg 与 Child
的 input 实现双向绑定。即是说,只要使用者在 Child
子元件里的 input 一输入内容,父元件的 msg
也会随之而更新。
如果你不知道原来 v-model
可以实现这功能,那麽你最快想到的方法可能就是,使用 props
和 emit
,做法像下面这样:
App.vue:
<template>
{{ msg }}
<Child :childProps="msg" @input-sth="msg = $event"/>
</template>
<script>
import Child from "./components/Child.vue";
export default {
name: "App",
components: {
Child
},
data() {
return {
msg: "父层 msg",
};
},
};
</script>
Child.vue
<template>
<input type="text" :value="childProps" @input="$emit('input-sth', $event.target.value)">
</template>
<script>
export default {
props: ['childProps']
}
</script>
以上就是直接使用 props
和 emit
的方法来完成。透过触发 input 事件来更新在父元件的资料。
v-model
双向绑定父子元件的资料然而,用 v-model
来写就会更简洁。但要注意的是,props 必须是 modelValue
,emit 事件的名称必须是 update:modelValue
。
以下先示范 v-model
的写法,得出的结果是一样:
App.vue
<template>
{{ msg }}
<Child v-model="msg"/>
</template>
Child.vue
<template>
<input
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
<script>
export default {
props: ["modelValue"],
};
</script>
先看看 Child 的部分,你会发现这里做的事,跟再前一个例子所做的事是相同。只不过是改了 props 和 emit 事件的名字。
之後,按以上写法,这里的 v-model
:
<Child v-model="msg"/>
等於:
<Child :modelValue="msg" @update:modelValue="msg = $event" />
如果想自定义 props 名称,不用 modelValue
的话,就直接在 v-model
後面定义:
<Child v-model:customProps="msg" />
https://codesandbox.io/s/vue-3-shi-yong-props-emit-shi-xian-v-model-ekk42?file=/src/App.vue
v-model
的做法在 Vue 2 同样可以使用 v-model
来完成父子元件的双向绑定。但在子元件的 data 里,需要加入 model
属性来指定 v-model
所绑定的 props。
App(父元件):
<Child v-model="msg" />
data() {
return {
msg: "这是父层 Msg",
};
}
Child (子元件):
<div>
<input
:value="childMsg"
@input="$emit('input', $event.target.value)"
/>
</div>
export default {
model: {
prop: "childMsg",
},
props: {
value: String,
childMsg: {
type: String,
default: "default msg",
},
},
};
Vue 3 只需绑定 modelValue
即可。但在 Vue 2,以上示范了要自行加入 model
属性来指定父层 v-model
所绑定的 props。
v-model
,Vue 2 还可以用 .sync
和 v-bind
除了以上提到的 v-model
方法,.sync
结合 v-bind
做法也能实现同样效果。还记得以上提到,v-model
其实只是由触发事件、绑定与更新组成吗?而 .sync
就是实现这两个效果的缩写。
试试用这语法来实现同样的效果:
Child(子元件):
<div>
<!-- 官方建议 update:myPropName 这格式的写法 -->
<input
:value="childMsg"
@input="$emit('update:childMsg', $event.target.value)"
/>
</div>
export default {
props: ["childMsg"],
};
App(父元件):
<Child :childMsg.sync="parentMsg" />
data() {
return {
parentMsg: "这是父层 msg"
};
},
注意,这里的写法:
<Child :childMsg.sync="parentMsg" />
即等於:
<Child :childMsg="parentMsg" @update:childMsg="parentMsg = $event" />
但谨记:Vue 3 已移除 .sync
语法,只能在 Vue 2 使用。
https://codesandbox.io/s/vue-2-sync-yong-fa-xp4fk?file=/src/App.vue
v-model
来实现父子元件双向绑定。modelValue
来指定父元件 v-model
所绑定的 props。相反,Vue 2 里需要在子元件建立 model
属性来指定 v-model
要绑定的props
。.sync
和 v-bind
来完成 v-model
所实现的效果。重新认识 Vue.js - 2-2 元件之间的沟通传递
Vue Component 也可以用 v-model
Vue.js v-model overview
古语有云:「岁有凶穰;故谷有贵贱;令有缓急;故物有轻重。」旨在告诉後人,做任何事情,一定要先搞清楚状...
在上一篇中介绍了什麽是 Angular CLI 与他可以提供许多方便功能,不过只是大概介绍他的用法与...
kind指令介绍 在上一章我们介绍了如何安装kind,既然安装完了,那就该知道kind支援哪些指令。...
前言 我们经常会说换位思考,也就是说,身为工程师,如果能清楚知道管理阶级的想法,就能聪明有效率的做事...
自订函式(User Definded Function) 自己定义函式有几个优点: 增加程序码的可读...