表单输入绑定
基础用法
你可以用 v-model 指令在表单 <input>
、<textarea>
及 <select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理。
提示
v-model 会忽略所有表单元素的 value、checked、selected attribute 的初始值而总是将当前活动实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
text 和 textarea 元素使用 value property
和 input
事件;
checkbox 和 radio 使用 checked property
和 change
事件;
select 字段将 value 作为 prop 并将 change 作为事件。
提示
对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model 不会在输入法组织文字过程中得到更新。如果你也想响应这些更新,请使用 input 事件监听器和 value 绑定,而不是使用 v-model。
文本 (Text)
<template>
<div id="app">
<input v-model="message" placeholder="edit me" />
<p>Message is: {{ message }}</p>
<button @click="message = 'jingxi'">set message to jingxi</button>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
data() {
return {
message: "su",
};
},
components: {},
};
</script>
多行文本 (Textarea)
<template>
<div id="app">
<textarea v-model="message" placeholder="edit me" />
<p>Message is: {{ message }}</p>
<button @click="message = 'jingxi'">set message to jingxi</button>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
data() {
return {
message: "su",
};
},
components: {},
};
</script>
在文本区域插值不起作用,应该使用 v-model 来代替。
<!-- bad -->
<textarea>{{ text }}</textarea>
<!-- good -->
<textarea v-model="text"></textarea>
复选框 (Checkbox)
单个复选框,绑定到布尔值:
<template>
<div id="app">
<label>
<input type="checkbox" v-model="x" />
<span>抽烟:{{x}}</span>
</label>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
12;
export default {
name: "App",
data() {
return {
x: true,
};
},
components: {},
};
</script>
多个复选框,绑定到同一个数组:
<template>
<div id="app">
爱好:{{x}}
<label>
<input type="checkbox" v-model="x" value="抽烟" />
<span>抽烟</span>
</label>
<label>
<input type="checkbox" v-model="x" :value="2"/>
<span>喝酒</span>
</label>
<label>
<input type="checkbox" v-model="x" value="3"/>
<span>烫头</span>
</label>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
12;
export default {
name: "App",
data() {
return {
x: [],
};
},
components: {},
};
</script>
单选框 (Radio)
<template>
<div id="app">
爱好:{{x}}
<label>
<input name="want(可以不加name)" type="radio" v-model="x" value="抽烟" />
<span>抽烟</span>
</label>
<label>
<input name="want(可以不加name)" type="radio" v-model="x" value="喝酒"/>
<span>喝酒</span>
</label>
<label>
<input name="want(可以不加name)" type="radio" v-model="x" value="烫头"/>
<span>烫头</span>
</label>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
12;
export default {
name: "App",
data() {
return {
x: '',
};
},
components: {},
};
</script>
选择框 (Select)
单选时:
<template>
<div id="app">
你想要:{{ x }}
<select v-model="x">
<option value="">Please select one</option>
<option v-for="item in array" :value="item.value" :key="item.value">
{{ item.text }}
</option>
</select>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
array: [
{ text: "抽烟", value: 1 },
{ text: "喝酒", value: 2 },
{ text: "烫头", value: 3 },
],
x: "",
};
},
components: {},
};
</script>
注意
如果 v-model 表达式的初始值未能匹配任何选项,
<select>
元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发 change 事件。因此,更推荐像<option disabled value="">Please select one</option>
这样提供一个值为空的禁用选项。
多选时 (绑定到一个数组,用的少):
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br />
<span>Selected: {{ selected }}</span>
form(表单)
<template>
<div id="app">
登录
<form @submit.prevent="onSubmit">
<label>
<span>用户名</span>
<input type="text" v-model="user.username" />
</label>
<label>
<span>密码</span>
<input type="password" v-model="user.password" />
</label>
<button type="submit">登录</button>
</form>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
user: {
username: "",
password: "",
},
x: "",
};
},
methods: {
onSubmit() {
console.log(this.user);
},
},
components: {},
};
</script>
修饰符
.lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步 (除了上述输入法组织文字时)。你可以添加 lazy
修饰符,从而转为在 change
事件_之后_进行同步:
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" />
- input事件,键盘、鼠标、任何输入设备的输入
- change事件,只在input失去焦点时触发
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符:
<input v-model.number="age" type="number" />
这通常很有用,因为即使在 type="number"
时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat()
解析,则会返回原始的值。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model
添加 trim
修饰符:
<input v-model.trim="msg" />
v-model
v-model
本质上是一个语法糖。如下代码<input v-model="test">
本质上是<input :value="test" @input="test = $event.target.value">
,其中@input
是对<input>
输入事件的一个监听:value="test"
是将监听事件中的数据放入到input
。在这边需要强调一点,v-model
不仅可以给input
赋值还可以获取input
中的数据,而且数据的获取是实时的,因为语法糖中是用@input
对输入框进行监听的。
本质:
<input type="text" v-model="user.username" />
<input type="text" :value="user.username" @input="user.username=$event.target.value" />
总结
面试问如何实现Vue 的双向绑定,就说v-model
的用法。
- 双向绑定
v-model
可以实现绑定一个数据,在这个数据变化的时候,UI会变化。- 在用户改变UI的时候,数据也会变化。
- 深入
v-model
是v-bind:value
和v-on:input
的语法糖。v-on:input="xxx=$event.target.value"
ant-design-vue
引入 ant-design-vue
- 安装脚手架工具
vue-cli
$ npm install -g @vue/cli
# OR
$ yarn global add @vue/cli
- 创建一个项目
使用命令行进行初始化。
$ vue create antd-demo
并配置项目。
- 使用组件
$ npm i --save ant-design-vue
$ yarn add ant-design-vue
完整引入
import Vue from 'vue';
import Antd from 'ant-design-vue';
import App from './App';
import 'ant-design-vue/dist/antd.css';
Vue.config.productionTip = false;
Vue.use(Antd);
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>',
});
以上代码便完成了 Antd 的引入。需要注意的是,样式文件需要单独引入。
- 进入项目并启动。
$ cd antd-demo
$ npm run serve
此时浏览器会访问 http://localhost:8080/
,看到 Welcome to Your Vue.js App
的界面就算成功了。
input-输入框
-
通过鼠标或键盘输入内容,是最基础的表单域的包装。
-
何时使用
- 需要用户输入表单域内容时。
- 提供组合型输入框,带搜索的输入框,还可以进行大小选择。
<template>
<div id="app">
<a-input placeholder="Basic usage" />
</div>
</template>
Form-表单
具有数据收集、校验和提交功能的表单,包含复选框、单选框、输入框、下拉选择框等元素。
如需要使用 v-model
双向绑定式的校验功能可使用新的表单 a-form-model
。
-
何时使用
- 用于创建一个实体或收集信息。
- 需要对输入的数据类型进行校验时。
-
表单 我们为 form 提供了以下三种排列方式:
- 水平排列:标签和表单控件水平排列;(默认)
- 垂直排列:标签和表单控件上下垂直排列;
- 行内排列:表单项水平行内排列。
-
表单域 表单一定会包含表单域,表单域可以是输入控件,标准表单域,标签,下拉菜单,文本域等。
这里我们封装了表单域
<Form.Item />
。
注意:
- 如果使用
Form.create
处理表单使其具有自动收集数据并校验的功能,建议使用jsx。 - 如果不是使用
Vue.use(Form)
形式注册的Form组件,你需要自行将$form
挂载到Vue原型上。Vue.prototype.$form = Form
//.vue
<template>
<a-form :form="form" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }" @submit="handleSubmit">
<a-form-item label="Note">
<a-input
v-decorator="['note', { rules: [{ required: true, message: 'Please input your note!' }] }]"
/>
</a-form-item>
<a-form-item label="Gender">
<a-select
v-decorator="[
'gender',
{ rules: [{ required: true, message: 'Please select your gender!' }] },
]"
placeholder="Select a option and change input text above"
@change="handleSelectChange"
>
<a-select-option value="male">
male
</a-select-option>
<a-select-option value="female">
female
</a-select-option>
</a-select>
</a-form-item>
<a-form-item :wrapper-col="{ span: 12, offset: 5 }">
<a-button type="primary" html-type="submit">
Submit
</a-button>
</a-form-item>
</a-form>
</template>
<script>
export default {
data() {
return {
formLayout: 'horizontal',
form: this.$form.createForm(this, { name: 'coordinated' }),
};
},
methods: {
handleSubmit(e) {
e.preventDefault();
this.form.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
},
handleSelectChange(value) {
console.log(value);
this.form.setFieldsValue({
note: `Hi, ${value === 'male' ? 'man' : 'lady'}!`,
});
},
},
};
</script>