最近在试图绑定一套自己的组件库,在实现input
上出了点问题,查了一下实现似乎和以前不一样了。
Vue3 v-model 的变化
根据 官方文档 的说法:
- 非兼容:用于自定义组件时,
v-model
prop 和事件默认名称已更改:- prop:
value
->modelValue
; - event:
input
->update:modelValue
;
- prop:
- 非兼容:
v-bind
的.sync
修饰符和组件的model
选项已移除,可用v-model
作为代替; - 新增:现在可以在同一个组件上使用多个
v-model
进行双向绑定; - 新增:现在可以自定义
v-model
修饰符。
v-model
实际上是一个语法糖,在vue3
中:
<ChildComponent v-model="pageTitle" />
<!-- 其实是 -->
<ChildComponent
:modelValue="pageTitle"
@update:modelValue="pageTitle = $event"
/>
现在我们可以在v-model
上添加参数来改变作响应的变量名。比如说
<ChildComponent v-model:title="pageTitle" />
<!-- 将内部绑定的变量名指向 title -->
<ChildComponent
:title="pageTitle"
@update:title="pageTitle = $event"
/>
这样也可以在同一个组件上使用多个v-model
。
绑定组件
回到开头,那么如何给 input 组件绑定呢?继续 抄答案:
这个组件内的 <input>
必须:
- 将其
value
attribute 绑定到一个名叫modelValue
的 prop 上 - 在其
input
事件被触发时,将新的值通过自定义的update:modelValue
事件抛出
app.component("custom-input", {
props: ["modelValue"],
emits: ["update:modelValue"],
template: `
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
`,
});
一个完整的测试:
const App = {
setup() {
const customValue = Vue.ref("");
return { customValue };
},
};
var app = Vue.createApp(App);
app.component("CustomInput", {
props: ["modelValue"],
emits: ["update:modelValue"],
template: `
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
`,
});
app.mount("#app");
利用原有v-model
的套娃方法:
<!DOCTYPE html>
<html lang="en">
<body>
<div id="app">
<custom-input v-model="customValue"></custom-input>
<div>{{customValue}}</div>
</div>
</body>
<script src="https://unpkg.com/vue@next"></script>
<script>
const App = {
setup() {
const customValue = Vue.ref("Test");
return { customValue };
},
};
var app = Vue.createApp(App);
app.component("CustomInput", {
props: ["modelValue"],
computed: {
model: {
get() {
return this.modelValue;
},
set(val) {
this.$emit("update:modelValue", val);
},
},
},
template: `<input v-model="model">`,
});
app.mount("#app");
</script>
</html>