Элементы input и textarea
Для работы с элементами ввода, в частности, с элементами input, select, textarea, применяется директива v-model, которая устанавливает двустороннюю привязку между элементом ввода и свойством объекта Vue. При этом v-model игнорирует значения атрибутов value, checked и selected, которые имеются у элементов ввода.
Например, используем ряд базовых элементов input:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> </head> <body> <div id="app"> <label>Логин</label> <input type="text" v-model="login" placeholder="Введите логин" class="form-control" /><br> <label>Пароль</label> <input type="password" v-model="password" placeholder="Введите пароль" class="form-control" /><br> <label>Возраст</label> <input type="number" v-model="age" min="18" placeholder="Введите возраст" class="form-control" /><br> <label>Дата регистрации</label><br> <input type="date" v-model="date" placeholder="Введите дату" class="form-control" /> <br> <div> <h3>Введенная информация</h3> <p>Логин: {{ login }}</p> <p>Пароль: {{ password }}</p> <p>Возраст: {{ age }}</p> <p>Дата регистрации: {{ date }}</p> </div> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { login: '', password: '', date: '', age: 22 } }) </script> </body> </html>
textarea
Элемент textarea позволяет вводить многострочный текст и также связывается со свойством во Vue через директиву v-model:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> </head> <body> <div id="app"> <label>Введите комментарий</label> <textarea v-model="comment" class="form-control"></textarea> <br> <div> <h3>Комментарий</h3> <p style="white-space: pre-line">{{ comment }}</p> </div> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { comment: 'Комментарий...' } }) </script> </body> </html>
В то же время есть некоторые особенности по работе с textarea. Прежде всего, если используется директива v-model, то внутри textarea мы не можем поместить текст с помощью интерполяции:
<textarea v-model="comment" class="form-control">{{ comment }}</textarea>
И кроме того, при вводе текста в textarea с помощью клавиши Enter мы можем переносить строки. Чтобы переносы строк сохранялись при выводе текста на страницу, необходимо применять соответствующие стили css:
<p style="white-space: pre-line">{{ comment }}</p>
Флажки (Checkbox)
Флажки представляют элементы управления, которые могут находиться в двух состояниях: отмеченном и неотмеченном.
Одиночный флажок может быть привязан к логическому значению true или false:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> </head> <body> <div id="app"> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { checked: true } }) </script> </body> </html>
По умолчанию для отмеченного состояния используется значение true, а для неотмеченного - false. Но вместо них можно определить свои собственные значения для обоих состояний и между этими значениями переключаться:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> </head> <body> <div id="app"> <input type="checkbox" v-model="light" v-bind:true-value="on" v-bind:false-value="off" /> <span v-if="light === on">Выключить</span> <span v-else>Включить</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { on: true, off: false, light: true } }) </script> </body> </html>
Вместо значений true и false флажок привязывается к одному из свойств on или off. С помощью атрибута v-bind:true-value="on" отмеченное состояние будет сопоставляться со свойством on. Соответственно в неотмеченном состоянии флажок приобретает значение off. А само выбранное значение попадает в свойство light.
Привязка к массиву
Также группа флажков может быть привязана к одному массиву. В этом случае при отметке флажка его значение попадает в массив:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> </head> <body> <div id="app"> <input type="checkbox" value="Tom" v-model="selectedUsers"> <label>Tom</label><br> <input type="checkbox" value="Bob" v-model="selectedUsers"> <label>Bob</label><br> <input type="checkbox" value="Sam" v-model="selectedUsers"> <label>Sam</label><br> <input type="checkbox" value="Alice" v-model="selectedUsers"> <label>Alice</label><br> <span>Выбрано: {{ selectedUsers }}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { selectedUsers: [] } }) </script> </body> </html>
В данном случае 4 флажка привязаны к массиву selectedUsers. Отметив определенный флажок, мы добавим его значение в массив.
Привязка к объекту
В примере выше значение каждого флажка представляло некоторую строку. Но также флажок может быть привязан к целому объекту. Для динамической привязки у элемента HTML применяется атрибут v-bind:value:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> </head> <body> <div id="app"> <template v-for="user in users"> <input type="checkbox" v-bind:value="user" v-model="selectedUsers"> <label>{{ user.name }}</label><br> </template> <ul> <li v-for="user in selectedUsers">{{ user.name }} - {{ user.age }}</li> </ul> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { users: [ { name: 'Tom', age: 22 }, { name: 'Bob', age: 25 }, { name: 'Sam', age: 28 }, { name: 'Alice', age: 26 } ], selectedUsers: [] } }) </script> </body> </html>
Здесь динамически для каждого объекта в массиве формируется флажок, а при выборе флажка объект попадет в массив selectedUsers.
Переключатели (radiobutton)
Переключатели или радиокнопки позволяют определить группу альтернативных вариантов, из которых одномоментно пользователь может выбрать только один. Переключатели привязываются к одному свойству. При выборе переключателя связанное свойство получает выбранное значение:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> </head> <body> <div id="app"> <input type="radio" value="Tom" v-model="user"> <label>Tom</label> <br> <input type="radio" value="Bob" v-model="user"> <label>Bob</label> <br> <input type="radio" value="Sam" v-model="user"> <label>Sam</label> <br> <span>Выбрано: {{ user }}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { user: '' } }) </script> </body> </html>
Привязка к объекту
Также каждый из переключателей может быть привязан к сложному объекту. В этом случае используется атрибут v-bind:value. Результатом выбора соответственно также будет сложный объект:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> </head> <body> <div id="app"> <input type="radio" v-bind:value="{name: 'Tom', age: 22}" v-model="user"> <label>Tom</label> <br> <input type="radio" v-bind:value="{name: 'Bob', age: 25}" v-model="user"> <label>Bob</label> <br> <input type="radio" v-bind:value="{name: 'Sam', age: 28}" v-model="user"> <label>Sam</label> <br> <span>Выбрано: {{ user.name }} - {{ user.age }}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { user: {} } }) </script> </body> </html>
Привязка к массиву объектов
В случае выше было бы более оптимально хранить данные в массиве и динамически создавать по элементам массива группу радиокнопок:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <template v-for="user in users"> <input type="radio" v-bind:value="user" v-model="selectedUser"> <label>{{ user.name }}</label><br> </template> <span v-if="selectedUser !== null">Выбрано: {{ selectedUser.name }} - {{ selectedUser.age }}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { users: [ { name: 'Tom', age: 22 }, { name: 'Bob', age: 25 }, { name: 'Sam', age: 28 }, { name: 'Alice', age: 26 } ], selectedUser: null } }) </script> </body> </html>
Список select
Элемент select позволяет создать список с возможностью одиночного и множественного выбора.
Список с одиночным выбором
Выпадающий список с одиночным выбором можно привязать к свойству Vue, которое хранит выбранный элемент:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <select v-model="user"> <option>Tom</option> <option>Bob</option> <option>Sam</option> </select> <span>Выбрано: {{ user }}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { user: '' } }) </script> </body> </html>
Список с множественным выбором
Список select с множественным выбором можно связать с массивом, в который попадут все выбранные значения:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <select v-model="users" multiple> <option>Tom</option> <option>Bob</option> <option>Sam</option> <option>Alice</option> </select> <span>Выбрано: {{ users }}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { users: [] } }) </script> </body> </html>
Привязка к массиву объектов
Нередко источником для элементов списка служит массив, элементы которого нередко представляют сложные объекты. Для динамического создания списка из массива применяется директива v-for, а для привязки значения к элементу списка - атрибут v-bind:value:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <select v-model="selectedUser"> <option v-for="user in users" v-bind:value="user.name">{{ user.name }}</option> </select> <span>Выбрано: {{ selectedUser }}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { users: [ { name: 'Tom', age: 22 }, { name: 'Bob', age: 25 }, { name: 'Sam', age: 28 }, { name: 'Alice', age: 26 } ], selectedUser: '' } }) </script> </body> </html>
В данном случае в списке отображается значение свойства name объекта из массива и это же свойство name будет использоваться в качестве значения при выборе элемента. Однако мы можем выбирать и весь объект в целом:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <select v-model="selectedUser"> <option v-for="user in users" v-bind:value="user">{{ user.name }}</option> </select> <span v-if="selectedUser !== null">Выбрано: {{ selectedUser.name }} - {{ selectedUser.age }}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { users: [ { name: 'Tom', age: 22 }, { name: 'Bob', age: 25 }, { name: 'Sam', age: 28 }, { name: 'Alice', age: 26 } ], selectedUser: null } }) </script> </body> </html>
В данном случае выбранный объект из массива будет попадать в свойство selection.
Привязка к объектам в списке с множественным выбором
Аналогично можно установить привязку к объектам в списке с множественным выбором. В этом случае выбранные элементы попадут в массив:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <select v-model="selectedUsers" multiple> <option v-for="user in users" v-bind:value="user">{{ user.name }}</option> </select> <h3>Выбранные объекты</h3> <ul> <li v-for="user in selectedUsers">{{ user.name }} - {{ user.age }}</li> </ul> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { users: [ { name: 'Tom', age: 22 }, { name: 'Bob', age: 25 }, { name: 'Sam', age: 28 }, { name: 'Alice', age: 26 } ], selectedUsers: null } }) </script> </body> </html>
Модификаторы
Для управленя вводом с элементов форм можно использовать модификаторы.
.lazy
По умолчанию директива v-model обновляет связанные с полем ввода данные при каждом вызове события input. То есть при вводе каждого символа в текстовое поле будут изменяться связанные данные. Но вместо этого мы также можем вызывать обновление не после события input, а после события change. То есть связанные данные будут обновляться только после того, как текстовое поле потеряет фокус. Для этого применяется модификатор .lazy:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <input type="text" v-model.lazy="name" /> <span>Введено: {{ name }}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { name: '' } }) </script> </body> </html>
.number
Модификатор .number позволяет автоматически конвертировать при вводе вводимое значение в число. Поскольку даже если мы установим у поля input атрибут type="number", то такое поле все равно будет возвращать строку:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <input v-model.number="age" type="number"> <span>Введено: {{ age }}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { age: 0 } }) </script> </body> </html>
.trim
Модификатор .trim автоматически обрезает начальные и концевые пробелы при вводе строки:
<!DOCTYPE html> <html> <head> <title>Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <input v-model.trim="message"> <span>Введено: {{message}}</span> </div> <script src="https://unpkg.com/vue"></script> <script> const app = new Vue({ el: '#app', data: { message: '' } }) </script> </body> </html>
Объединение модификаторов
Также можно объединять модификаторы:
<input v-model.lazy.trim="message"> <input v-model.lazy.number="age" type="number">