Vue v-model Chỉ thị
Ví dụ
Sử dụng lệnh v-model
để tạo liên kết hai chiều giữa phần tử <input>
và thuộc tính dữ liệu.
<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>
Chạy ví dụ »Xem thêm ví dụ dưới đây.
Định nghĩa và cách sử dụng
Lệnh v-model
được sử dụng để tạo liên kết hai chiều giữa phần tử đầu vào của biểu mẫu hoặc giữa thuộc tính phiên bản Vue và một thành phần.
Các phần tử đầu vào biểu mẫu với v-model
Các phần tử đầu vào của biểu mẫu có thể được sử dụng với v-model
là <input>
, <select>
và <textarea>
.
Liên kết hai chiều với v-model
trên các phần tử đầu vào của biểu mẫu hoạt động như sau:
- Khi Vue phát hiện sự thay đổi trong giá trị đầu vào, nó sẽ cập nhật thuộc tính dữ liệu tương ứng. (HTML -> JavaScript)
- Khi Vue phát hiện sự thay đổi trong thuộc tính phiên bản Vue, nó sẽ cập nhật giá trị đầu vào tương ứng. (JavaScript -> HTML)
(Xem Ví dụ ở trên và Ví dụ 1 bên dưới.)
Các thành phần có v-model
Khi v-model
được sử dụng trên một thành phần, giao diện thành phần phải được thiết lập đúng cách với props
và emits
để đạt được liên kết hai chiều.
Liên kết hai chiều với v-model
trên các thành phần hoạt động như sau:
- Khi Vue phát hiện sự thay đổi trong thuộc tính phiên bản gốc, giá trị mới sẽ được gửi dưới dạng chỗ dựa cho thành phần.
- Khi Vue phát hiện sự thay đổi trong thành phần con, giá trị mới sẽ được gửi tới thành phần mẹ dưới dạng sự kiện phát ra.
Khi v-model
được sử dụng trên một thành phần, tên prop mặc định là 'modelValue' và tên sự kiện phát ra mặc định là 'update:modelValue'. (Xem Ví dụ 2 và Ví dụ 3. )
Khi v-model
được sử dụng trên một thành phần, thay vì sử dụng thuộc tính dữ liệu phiên bản Vue, chúng ta có thể sử dụng thuộc tính được tính toán với các phương thức get()
và set()
. ( Xem ví dụ 4 )
Có thể đặt các tên khác nhau cho đạo cụ và phát ra ngoài 'modelValue' và 'update:modelValue' mặc định bằng cách sử dụng v-model:
. ( Xem ví dụ 5 )
Để có nhiều giá trị được kết nối dưới dạng liên kết hai chiều với một thành phần, chúng ta phải xác định từng giá trị đó bằng v-model
của chính nó. ( Xem ví dụ 6 )
sửa đổi
sửa đổi | Chi tiết |
---|---|
.lazy | Sự kiện change được Vue sử dụng thay vì sự kiện input để biết thời điểm đồng bộ hóa. Điều này có nghĩa là trước tiên người dùng phải sửa đổi đầu vào, sau đó chuyển tiêu điểm ra khỏi phần tử đầu vào trước khi giá trị thuộc tính phiên bản được cập nhật. ( Xem ví dụ 7 ) |
.number | Đánh máy dữ liệu đầu vào thành số. Việc này được thực hiện tự động khi sử dụng <input type="number"> . |
.trim | Loại bỏ khoảng trắng ở đầu và cuối dữ liệu nhập. ( Xem ví dụ 8 ) |
phong tục | Để tạo một công cụ sửa đổi tùy chỉnh cho v-model , trước tiên chúng ta cần xác định một prop 'modelModifiers' để lưu trữ công cụ sửa đổi mới. Chức năng sửa đổi được viết bằng một phương thức. Nếu công cụ sửa đổi được đặt, mã thích hợp sẽ chạy trong phương thức trước khi gửi giá trị sao lưu cho thành phần chính. ( Xem ví dụ 9 ) |
Thêm ví dụ
ví dụ 1
Sử dụng thanh trượt ( <input type="range">
) để thay đổi giá trị thuộc tính 'inputValue'. Phần tử <input type="text">
tự động cập nhật vì nó được liên kết với thuộc tính 'inputValue' với v-model
.
<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>
Chạy ví dụ »Ví dụ 2
Sử dụng v-model
trên thành phần có props
và emits
để những thay đổi trong phần tử <input>
sẽ cập nhật thuộc tính 'văn bản' của phần tử cha.
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>
Chạy ví dụ »Ví dụ 3
Sử dụng v-model
trên thành phần để thể hiện ràng buộc hai chiều rõ ràng hơn. Thành phần có thể cập nhật thuộc tính 'văn bản' gốc và thành phần được cập nhật khi thuộc tính 'văn bản' gốc thay đổi.
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>
Chạy ví dụ »Ví dụ 4
Sử dụng v-model
với giá trị được tính toán với các hàm get()
và set()
bên trong thành phần.
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>
Chạy ví dụ »Ví dụ 5
Sử dụng v-model:message
trên thành phần để đổi tên tên prop mặc định 'modelValue' thành '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>
Chạy ví dụ »Ví dụ 6
Sử dụng v-model
hai lần trên thành phần để tạo liên kết hai chiều với hai giá trị.
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>
Chạy ví dụ »Ví dụ 7
Sử dụng .lazy
để trước tiên người dùng phải sửa đổi phần tử đầu vào, sau đó thay đổi tiêu điểm khỏi phần tử đầu vào trước khi thuộc tính được cập nhật bằng 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>
Chạy ví dụ »Ví dụ 8
Sử dụng .lazy
để trước tiên người dùng phải sửa đổi phần tử đầu vào, sau đó thay đổi tiêu điểm khỏi phần tử đầu vào trước khi thuộc tính được cập nhật bằng 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>
Chạy ví dụ »Ví dụ 9
Sử dụng công cụ sửa đổi .allCapital
tùy chỉnh để chuyển đổi tất cả các ký tự trong đầu vào thành chữ hoa nếu công cụ sửa đổi .allCapital
được đặt.
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>
Chạy ví dụ »Trang liên quan
Hướng dẫn về Vue: Thành phần Vue
Hướng dẫn Vue: Đạo cụ Vue
Hướng dẫn về Vue: Phương thức Vue $emit()
Hướng dẫn về Vue: Thuộc tính được tính toán của Vue
Tham khảo Vue: Phương thức Vue $emit()
Tham khảo Vue: Đối tượng Vue $props
Hướng dẫn JavaScript: Trình truy cập đối tượng JavaScript