Skip to content

Xử lý form

Khi làm việc với biểu mẫu trên phía frontend, chúng ta thường cần đồng bộ hóa trạng thái của các phần tử nhập biểu mẫu với trạng thái tương ứng trong JavaScript. Việc kết nối thủ công giữa giá trị và lắng nghe sự kiện thay đổi có thể khá phức tạp:

template
<input
  :value="text"
  @input="event => text = event.target.value">

Chỉ thị v-model giúp chúng ta đơn giản hóa ví dụ trên thành:

template
<input v-model="text">

Ngoài ra, v-model có thể được sử dụng trên các phần tử nhập của các loại khác nhau, các phần tử <textarea>, và <select>. Nó tự động mở rộng thành các cặp thuộc tính DOM và sự kiện khác nhau dựa trên phần tử mà nó được sử dụng:

  • <input> với các loại văn bản và phần tử <textarea> sử dụng thuộc tính value và sự kiện input;
  • <input type="checkbox"><input type="radio"> sử dụng thuộc tính checked và sự kiện change;
  • <select> sử dụng value như là một prop và change như là một sự kiện.

Ghi chú

v-model sẽ bỏ qua các thuộc tính ban đầu value, checked hoặc selected được tìm thấy trên bất kỳ phần tử biểu mẫu nào. Nó sẽ luôn coi trạng thái JavaScript được liên kết hiện tại như là nguồn sự thật. Bạn nên khai báo giá trị ban đầu từ phía JavaScript, sử dụng tùy chọn dataAPI Reactivity.

Sử dụng cơ bản

Text

template
<p>Thông điệp là: {{ message }}</p>
<input v-model="message" placeholder="chỉnh sửa tôi" />

Thông điệp là:

Ghi chú

Đối với các ngôn ngữ yêu cầu sử dụng IME (Tiếng Trung, Tiếng Nhật, Tiếng Hàn, v.v.), bạn sẽ nhận thấy rằng v-model không cập nhật trong quá trình sáng tác IME. Nếu bạn muốn phản ứng với những cập nhật này, hãy sử dụng lắng nghe sự kiện input và ràng buộc giá trị của bạn thay vì sử dụng v-model.

Multiline text

template
<span>Thông điệp đa dòng là:</span>
<p style="white-space: pre-line;">{{ multilineText }}</p>
<textarea v-model="multilineText" placeholder="thêm nhiều dòng"></textarea>
Thông điệp đa dòng là:

Lưu ý rằng việc nội suy bên trong <textarea> sẽ không hoạt động. Sử dụng v-model thay thế.

template
<!-- không tốt -->
<textarea>{{ text }}</textarea>

<!-- tốt -->
<textarea v-model="text"></textarea>

Checkbox

template
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>

Chúng ta cũng có thể kết nối nhiều ô chọn (checkbox) với cùng một mảng hoặc Set giá trị:

template
<div>Checked names: {{ checkedNames }}</div>

<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>

<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>

<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
Checked names: []

Trong trường hợp này, mảng checkedNames sẽ luôn chứa các giá trị từ các ô chọn hiện tại.

Radio

template
<div>Picked: {{ picked }}</div>

<input type="radio" id="one" value="One" v-model="picked" />
<label for="one">One</label>

<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Two</label>
Picked:
```

Select

template
<div>Selected: {{ selected }}</div>

<select v-model="selected">
  <option disabled value="">Please select one</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
Selected:

Note

If the initial value of your v-model expression does not match any of the options, the <select> element will render in an "unselected" state. On iOS this will cause the user not being able to select the first item because iOS does not fire a change event in this case. It is therefore recommended to provide a disabled option with an empty value, as demonstrated in the example above.

Multiple select (bound to array):

template
<div>Selected: {{ selected }}</div>

<select v-model="selected" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
Selected: []

Select options can be dynamically rendered with v-for:

js
const selected = ref('A')

const options = ref([
  { text: 'One', value: 'A' },
  { text: 'Two', value: 'B' },
  { text: 'Three', value: 'C' }
])
js
export default {
  data() {
    return {
      selected: 'A',
      options: [
        { text: 'One', value: 'A' },
        { text: 'Two', value: 'B' },
        { text: 'Three', value: 'C' }
      ]
    }
  }
}
template
<select v-model="selected">
  <option v-for="option in options" :value="option.value">
    {{ option.text }}
  </option>
</select>

<div>Selected:

 {{ selected }}</div>
```

Ràng Buộc Giá Trị

Đối với radio, checkbox và select options, giá trị ràng buộc của v-model thường là chuỗi tĩnh (hoặc booleans đối với checkbox):

template
<!-- `picked` là chuỗi "a" khi được chọn -->
<input type="radio" v-model="picked" value="a" />

<!-- `toggle` có thể là true hoặc false -->
<input type="checkbox" v-model="toggle" />

<!-- `selected` là chuỗi "abc" khi lựa chọn option đầu tiên -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

Tuy nhiên, đôi khi chúng ta muốn ràng buộc giá trị vào một thuộc tính động trên instance hiện tại. Chúng ta có thể sử dụng v-bind để làm điều đó. Ngoài ra, việc sử dụng v-bind cho phép ràng buộc giá trị đầu vào với các giá trị không phải là chuỗi.

Checkbox

template
<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no" />

true-valuefalse-value là các thuộc tính đặc biệt của Vue chỉ hoạt động với v-model. Ở đây, giá trị của thuộc tính toggle sẽ được đặt thành 'yes' khi ô được chọn và đặt thành 'no' khi không được chọn. Bạn cũng có thể ràng buộc chúng với các giá trị động bằng cách sử dụng v-bind:

template
<input
  type="checkbox"
  v-model="toggle"
  :true-value="dynamicTrueValue"
  :false-value="dynamicFalseValue" />

Ghi chú

Các thuộc tính true-valuefalse-value không ảnh hưởng đến thuộc tính value của đầu vào, vì các trình duyệt không bao gồm các ô chọn không được chọn trong việc gửi biểu mẫu. Để đảm bảo một trong hai giá trị được gửi trong một biểu mẫu (ví dụ: "yes" hoặc "no"), hãy sử dụng các đầu vào radio thay thế.

Radio

template
<input type="radio" v-model="pick" :value="first" />
<input type="radio" v-model="pick" :value="second" />

pick sẽ được đặt thành giá trị của first khi radio đầu tiên được chọn và đặt thành giá trị của second khi radio thứ hai được chọn.

Lựa Chọn Của Select

template
<select v-model="selected">
  <!-- đối tượng literal trực tiếp -->
  <option :value="{ number: 123 }">123</option>
</select>

v-model hỗ trợ ràng buộc giá trị không phải là chuỗi! Trong ví dụ trên, khi option được chọn, selected sẽ được đặt thành giá trị đối tượng literal { number: 123 }.

Modifiers

.lazy

Mặc định, v-model đồng bộ hóa đầu vào với dữ liệu sau mỗi sự kiện input (ngoại trừ trường hợp sử dụng IME như đã nói ở trên). Bạn có thể thêm bộ điều chỉnh lazy để thay thế việc đồng bộ hóa sau các sự kiện change:

template
<!-- đồng bộ hóa sau sự kiện "change" thay vì "input" -->
<input v-model.lazy="msg" />

.number

Nếu bạn muốn đầu vào của người dùng tự động được chuyển đổi kiểu sang số, bạn có thể thêm bộ điều chỉnh number vào đầu vào được quản lý bởi v-model:

template
<input v-model.number="age" />

Nếu giá trị không thể được phân tích với parseFloat(), thì giá trị gốc sẽ được sử dụng thay vào đó.

Bộ điều chỉnh number sẽ được áp dụng tự động nếu đầu vào có type="number".

.trim

Nếu bạn muốn khoảng trắng từ đầu vào của người dùng được cắt tự động, bạn có thể thêm bộ điều chỉnh trim vào đầu vào được quản lý bởi v-model:

template
<input v-model.trim="msg" />

v-model với Components

Nếu bạn chưa quen với các thành phần Vue, bạn có thể bỏ qua phần này tạm thời.

Các loại đầu vào tích hợp sẵn của HTML không luôn đáp ứng được nhu cầu của bạn. May mắn thay, các thành phần Vue cho phép bạn xây dựng đầu vào có thể tái sử dụng với hành vi tùy chỉnh hoàn toàn. Những đầu vào này thậm chí còn hoạt động với v-model! Để biết thêm thông tin, đọc về Sử Dụng với v-model trong hướng dẫn về Components.

Xử lý form has loaded