vue2 中
我们知道在 vue2 中有 3 个硬编码的修饰符:lazy
、number
和trim
,他们的作用分别如下:
- lazy:将触发
input
事件转为触发change
事件,在某些场景下来降低数据同步频率提升性能。
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" />
- number:自动将用户的输入值转为数值类型。
<input v-model.number="age" type="number" />
- trim:自动过滤用户输入的首尾空白字符
<input v-model.trim="msg" />
示例效果:
vue3 中
不同于 vue2 的硬编码,在 vue3 中支持自定义修饰符:
<my-component v-model.capitalize="bar"></my-component>
组件接收自定义修饰符:
app.component('my-component', {
props: {
modelValue: String,
// 组件接收属性modelModifiers对象,对象里面包含多个修饰符,这里默认给个空对象:{}
modelModifiers: {
default: () => ({}),
},
},
template: `
<input type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)">
`,
created() {
console.log(this.modelModifiers); // { capitalize: true }
},
});
我们看到组件会接收一个属性为modelModifiers
的对象,上面示例给出了默认值{}
,然后在生命周期函数created
中拿到了修饰符capitalize的值为true
(因为在上面组件使用时绑定了v-model.capitalize="bar"
)。
接下来,我们实现修饰符capitalize
,即将 v-model 绑定的值首字母大写:
app.component('my-component', {
props: {
modelValue: String,
modelModifiers: {
default: () => ({}),
},
},
template: `
<input type="text"
:value="modelValue"
@input="emitValue">
`,
methods: {
emitValue(e) {
let v = e.target.value;
if (this.modelModifiers.capitalize) {
v = v.charAt(0).toUpperCase() + v.slice(1);
}
this.emit('update:modelValue', v);
},
},
});
我们来看看效果:
由于 vue3 支持组件同时绑定多个带参数的 v-model(不带参数的话只有第一个 v-model 是有效的),所以在带参数的情况下,修饰符属性命名就变成了参数名 + "Modifiers"
,我们看下面代码:
<my-component
v-model:first-name.capitalize="firstName"
v-model:last-name.upper="lastName"
></my-component>
组件实现:
app.component('my-component', {
props: ['firstName', 'firstNameModifiers', 'lastName', 'lastNameModifiers'],
template: `
<input type="text"
:value="firstName"
@input="$emit('update:firstName', $event.target.value)"> -
<input type="text"
:value="lastName"
@input="$emit('update:lastName', $event.target.value)">
`,
created() {
console.log(this.firstNameModifiers); // { capitalize: true }
console.log(this.lastNameModifiers); // { upper: true }
},
});
上面代码中,我们的参数名是firstName
和lastName
,所以自定义组件接收到的修饰符属性由原来的modelModifiers
修改为firstNameModifiers
和lastNameModifiers
。
下面我们来看完整的实现:
// 创建APP
const app = Vue.createApp({
data() {
return {
firstName: '',
lastName: '',
};
},
});
// 自定义组件
app.component('my-component', {
props: ['firstName', 'firstNameModifiers', 'lastName', 'lastNameModifiers'],
template: `
<p>firstName: <input type="text" :value="firstName" @input="emitCapitalize"></p>
<p>lastName: <input type="text" :value="lastName" @input="emitReverse"></p>
`,
methods: {
emitCapitalize(e) {
let v = e.target.value;
if (this.firstNameModifiers.capitalize) {
v = v.charAt(0).toUpperCase() + v.slice(1);
}
this.$emit('update:firstName', v);
},
emitReverse(e) {
let v = e.target.value;
if (this.lastNameModifiers.upper) {
v = v.toUpperCase();
}
this.$emit('update:lastName', v);
},
},
});
// 挂载
app.mount('#app');
实现效果:
至此,v-model 在 vue2 和 vue3 中的应用就基本讲完了,欢迎大家留言或加微信(cleam_lee)讨论!
汇总: