Vue v-model 指令
实例
使用 v-model
指令在 <input>
元素和数据属性之间创建双向绑定。
<template>
<h1>v-model Example</h1>
<p>Write something, and see the 'inputValue' data property update automatically.</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
双向绑定 的工作方式如下:组件与 v-model
当在组件上使用 v-model
时,必须使用 props
和 emits
正确设置组件接口,以实现双向绑定。
v-model
进行 双向绑定 的工作方式如下:在组件上使用 v-model
时,默认 prop 名称为 'modelValue',默认 emit 事件名称为 'update:modelValue'。
当在组件上使用 v-model
时,我们可以将计算属性与 get()
和 set()
方法一起使用,而不是使用 Vue 实例数据属性。
可以使用 v-model:
为 prop 和 emit 设置不同于默认 'modelValue' 和 'update:modelValue' 的名称。要使多个值作为双向绑定连接到组件,我们必须用自己的 v-model
定义每个这样的值。
修饰符
修饰符 | 详情 |
---|---|
.lazy | Vue 使用更改事件而不是输入事件来确定何时同步这意味着用户必须首先修改输入,然后在更新实例属性值之前将焦点从输入元素切换开。 |
.number | 将输入类型转换为数字当使用 <input type="number"> 时,这是自动完成的。 |
.trim | 删除输入开始和结束处的空白。 |
custom | 要为 v-model 创建自定义修饰符,我们首先需要定义一个 props 'modelModifiers' 来存储新的修饰符修饰符功能是在一个方法中编写的如果设置了修饰符,则在将值 emits 回父组件之前,将在方法中运行相应的代码。 |
更多实例
实例 1
使用滑块(<input type="range">
)更改 'inputValue' 属性值。<input type="text">
元素会自动更新,因为它绑定到 v-model
的 'inputValue' 属性。
<template>
<h1>v-model Example</h1>
<p>Drag the slider to change the 'inputValue' data property, and see the input text field update automatically because of the two-way binding from 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>Example v-model Directive</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>Component</h3>
<p>Write something in the text input field below to see that changes here are emitted from the component, and the parent 'text' property gets updated by the use of 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>Example v-model Directive</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>Component</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
: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
在组件内部使用具有计算值的 v-model
以及 get()
和 set()
函数。
CompOne.vue:
<template>
<div>
<h3>Component</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
将默认 prop 名称 'modelValue' 重命名为 'message' 。
App.vue:
<template>
<h2>Example v-model Directive</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>Component</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
: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>Example v-model Directive</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>Component</h3>
<p>Two inputs are bound to the component with v-model through props and emits.</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>Using the '.lazy' modifier, you must first write something, then click somewhere else, or use the tab key to switch focus away from the input element, before the property get updated.</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>Example v-model Directive</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>Component</h3>
<p>Write something in the text input field below. Click somewhere else or use the tab key to shift focus away from the input element to see the effect of the custom 'allCapital' modifier.</p>
<input
:value="modelValue"
@change="this.emitVal"
/>
</div>
</template>
<script>
export default {
props: {
modelValue: String,
modelModifiers: {
// modelModifiers is an empty object initially.
// Modifiers set on the component will be stored here.
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>