Vue v-model 指令
示例
使用 v-model
指令在 <input>
元素和数据属性之间创建双向绑定。
<template>
<h1>v-model Example</h1>
<p>写一些东西,然后会看到"inputValue"数据属性自动更新。</p>
<input type="text" v-model="inputValue">
<p>inputValue property: "{{ inputValue }}"</p>
</template>
运行示例 »
请参阅下面的更多示例。
定义和用法
v-model
指令用于在表单输入元素之间或 Vue 实例属性和组件之间创建双向绑定。
带有 v-model
的表单输入元素
可以与v-model
一起使用的表单输入元素是 <input>
, <select>
和 <textarea>
。
双向绑定 与 v-model
的工作原理如下:
- 当Vue检测到输入值发生变化时,它会相应地更新相应的数据属性。 (HTML -> JavaScript)
- 当 Vue 检测到 Vue 实例属性发生变化时,它会相应地更新相应的输入值。 (JavaScript -> HTML)
(参见上面的示例和下面的示例 1。)
带有v-model
的组件
在组件上使用v-model
时,必须正确设置组件接口 props
和 emits
才能实现双向绑定。
组件上的 双向绑定 与 v-model
的工作方式如下:
- 当 Vue 检测到父实例属性发生更改时,新值将作为 prop 发送到组件。
- 当 Vue 检测到子组件发生更改时,新值会作为发出事件发送到父组件。
当在组件上使用 v-model
时,默认 prop 名称为"modelValue",默认发出事件名称为"update:modelValue"。 (请参阅示例 2 和示例 3。)
当 v-model
用于组件时,我们可以使用 get()
和 set()
方法的计算属性,而不是使用 Vue 实例数据属性。 (参见示例 4)
可以使用 v-model:
设置与默认的"modelValue"和"update:modelValue"不同的 props 和 Emit 名称。 (参见示例 5)
要将多个值作为双向绑定连接到组件,我们必须使用其自己的 v-model
定义每个此类值。 (参见示例 6)
修饰符
修饰符 | 详细信息 |
---|---|
.lazy |
Vue 使用 change 事件而不是 input 事件来决定何时同步。 这意味着用户必须首先修改输入,然后在更新实例属性值之前将焦点从输入元素移开。 (参见示例 7) |
.number |
将输入类型转换为数字。 当使用 <input type="number"> 时,这是自动完成的。 |
.trim |
删除输入开头和结尾的空格。 (参见示例 8) |
custom | 要为v-model 创建自定义修饰符,我们首先需要定义一个属性"modelModifiers"来存储新修饰符。 修饰符功能写在方法中。 如果设置了修饰符,则在将值发送回父组件之前,会在方法中运行适当的代码。 (参见示例 9) |
更多示例
示例 1
使用滑块 (<input type="range">
) 更改"inputValue"属性值。 <input type="text">
元素会自动更新,因为它通过 v-model
绑定到"inputValue"属性。
<template>
<h1>v-model Example</h1>
<p>拖动滑块更改"inputValue"数据属性,并看到输入文本字段由于 v-model 的双向绑定而自动更新。</p>
<input type="range" min="-50" max="50" v-on:input="sliderChange" value="4">
<p>inputValue property: "{{ inputValue }}"</p>
<input type="text" v-model="inputValue">
</template>
<script>
export default {
data() {
return {
inputValue: null
};
},
methods: {
sliderChange(evt) {
this.inputValue = evt.target.value
}
}
}
</script>
运行示例 »
示例 2
在具有 props
和 emits
的组件上使用 v-model
,以便 <input>
元素中的更改更新父级的"text"属性。
App.vue
:
<template>
<h2>v-model 指令示例</h2>
<p>App.vue 'text' property: "{{ text }}"</p>
<comp-one v-model="text"/>
</template>
<script>
export default {
data() {
return {
text: 'Say Cheese'
}
}
}
</script>
CompOne.vue
:
<template>
<div>
<h3>组件</h3>
<p>在下面的文本输入字段中写入一些内容,以查看此处的更改是从组件发出的,并且父"text"属性通过使用 v-model 进行更新。</p>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</div>
</template>
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>
<style scoped>
div {
border: solid black 1px;
padding: 10px;
margin: 20px 0;
max-width: 500px;
}
</style>
运行示例 »
示例 3
在组件上使用v-model
可以更清楚地演示双向绑定。 组件可以更新父"text"属性,并且当父"text"属性更改时组件也会更新。
App.vue
:
<template>
<h2>v-model 指令示例</h2>
<p>App.vue 'text' property: "<pre>{{ text }}</pre>"</p>
<button v-on:click="this.text = 'Hello!'">text='Hello!'</button>
<comp-one v-model="text"/>
</template>
<script>
export default {
data() {
return {
text: 'Say Cheese'
}
}
}
</script>
<style>
pre {
display: inline;
background-color: yellow;
}
</style>
CompOne.vue
:
<template>
<div>
<h3>组件</h3>
<p>Two-way binding on component with v-model:</p>
<ol>
<li>该组件可以更新'text'属性(使用文本字段)。</li>
<li>当"text"属性更改(使用按钮)时,组件会更新。</li>
</ol>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</div>
</template>
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>
<style scoped>
div {
border: solid black 1px;
padding: 10px;
margin: 20px 0;
max-width: 600px;
}
</style>
运行示例 »
示例 4
通过组件内的 get()
和 set()
函数将 v-model
与计算值结合使用。
CompOne.vue
:
<template>
<div>
<h3>组件</h3>
<p>Two-way binding on component with v-model:</p>
<ol>
<li>The component can update the 'text' property (using text field).</li>
<li>The component gets updated when the 'text' property is changed (using button).</li>
</ol>
<input v-model="inpVal"/>
</div>
</template>
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
computed: {
inpVal: {
get() {
return this.modelValue;
},
set(inpVal) {
this.$emit('update:modelValue',inpVal)
}
}
}
}
</script>
<style scoped>
div {
border: solid black 1px;
padding: 10px;
margin: 20px 0;
max-width: 600px;
}
</style>
运行示例 »
示例 5
在组件上使用 v-model:message
将默认 props 名称"modelValue"重命名为"message"。
App.vue
:
<template>
<h2>v-model 指令示例</h2>
<p>App.vue 'text' property: "<pre>{{ text }}</pre>"</p>
<button v-on:click="this.text = 'Hello!'">text='Hello!'</button>
<comp-one v-model:message="text"/>
</template>
<script>
export default {
data() {
return {
text: 'Say Cheese'
}
}
}
</script>
<style>
pre {
display: inline;
background-color: yellow;
}
</style>
CompOne.vue
:
<template>
<div>
<h3>组件</h3>
<p>组件与 v-model 的双向绑定:</p>
<ol>
<li>该组件可以更新'text'属性(使用文本字段)。</li>
<li>当"text"属性更改(使用按钮)时,组件会更新。</li>
</ol>
<input
:value="message"
@input="$emit('update:message', $event.target.value)"
/>
</div>
</template>
<script>
export default {
props: ['message'],
emits: ['update:message']
}
</script>
<style scoped>
div {
border: solid black 1px;
padding: 10px;
margin: 20px 0;
max-width: 600px;
}
</style>
运行示例 »
示例 6
在组件上使用两次 v-model
来创建具有两个值的双向绑定。
App.vue
:
<template>
<h2>v-model 指令示例</h2>
<p>Name: "<pre>{{ name }}</pre>"</p>
<p>Height: <pre>{{ height }}</pre> cm</p>
<comp-one
v-model:name="name"
v-model:height="height"
/>
</template>
<script>
export default {
data() {
return {
name: 'Olaf',
height: 120
}
}
}
</script>
<style>
pre {
display: inline;
background-color: yellow;
}
</style>
CompOne.vue
:
<template>
<div>
<h3>组件</h3>
<p>两个输入通过 props 与 v-model 绑定到组件并发出。</p>
<p>
<label>
Name:
<input
type="text"
:value="name"
@input="$emit('update:name', $event.target.value)"
/>
</label>
</p>
<p>
<label>
Height:
<input
type="range"
:value="height"
@input="$emit('update:height', $event.target.value)"
min="50"
max="200"
/>
{{ this.$props.height }} cm
</label>
</p>
</div>
</template>
<script>
export default {
props: ['name','height'],
emits: ['update:name','update:height']
}
</script>
<style scoped>
div {
border: solid black 1px;
padding: 10px;
margin: 20px 0;
max-width: 300px;
}
</style>
运行示例 »
示例 7
使用 .lazy
,以便用户必须首先修改输入元素,然后将焦点从输入元素移开,然后再使用 v-model
更新属性。
<template>
<h1>v-model Example</h1>
<p>使用".lazy"修饰符,您必须先编写一些内容,然后单击其他位置,或者使用 Tab 键将焦点从输入元素上切换,然后才能更新属性。</p>
<input type="text" v-model.lazy="inputValue">
<p>inputValue property: "{{ inputValue }}"</p>
</template>
<script>
export default {
data() {
return {
inputValue: null
};
}
}
</script>
运行示例 »
示例 8
使用 .lazy
,以便用户必须首先修改输入元素,然后将焦点从输入元素移开,然后再使用 v-model
更新属性。
<template>
<h1>v-model Example</h1>
<p>Using the '.trim' modifier will remove any white spaces at the start and end of the input.</p>
<p>Add white spaces at the start and end in the input fields below to see the difference with or with out '.trim'.</p>
<p>No '.trim': <input type="text" v-model="inputVal1"> "<pre>{{ inputVal1 }}</pre>"</p>
<p>With '.trim': <input type="text" v-model.trim="inputVal2"> "<pre>{{ inputVal2 }}</pre>"</p>
</template>
<script>
export default {
data() {
return {
inputVal1: 'Hello',
inputVal2: 'Hi'
};
}
}
</script>
<style>
pre {
display: inline;
background-color: lightgreen;
}
</style>
运行示例 »
示例 9
如果设置了 .allCapital
修饰符,则使用自定义 .allCapital
修饰符将输入中的所有字符转换为大写。
App.vue
:
<template>
<h2>v-model 指令示例</h2>
<p>App.vue 'text' property: "{{ text }}"</p>
<comp-one v-model.allCapital="text"/>
</template>
<script>
export default {
data() {
return {
text: ''
}
}
}
</script>
CompOne.vue
:
<template>
<div>
<h3>组件</h3>
<p>在下面的文本输入字段中写一些内容。 单击其他位置或使用 Tab 键将焦点从输入元素移开,以查看自定义"allCapital"修饰符的效果。</p>
<input
:value="modelValue"
@change="this.emitVal"
/>
</div>
</template>
<script>
export default {
props: {
modelValue: String,
modelModifiers: {
// modelModifiers 最初是一个空对象。
// 组件上设置的修饰符将存储在这里。
default: () => ({})
}
},
emits: ['update:modelValue'],
methods: {
emitVal(e) {
let value = e.target.value
if (this.modelModifiers.allCapital) {
value = value.toUpperCase()
}
this.$emit('update:modelValue', value)
}
}
}
</script>
<style scoped>
div {
border: solid black 1px;
padding: 10px;
margin: 20px 0;
max-width: 500px;
}
</style>
运行示例 »
相关页面
Vue 教程:Vue 组件
Vue 教程:Vue Props 选项
Vue 教程:Vue $emit() 方法
Vue 教程:Vue Computed 计算属性
Vue 参考:Vue $emit() 方法
Vue 参考:Vue $props 对象
JavaScript 教程:JavaScript 对象访问器