搜索框封装组件如何也实现v-model同步data中的数据?

面试的时候遇见过这个问题,在项目中也经常遇到。今天来做一下记录,搜索框封装组件如何也实现v-model同步data中的数据?

先来理解一下这个问题,首先看看普通的input搜索框的v-model的表现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<div>
<h1>测试专用demo</h1>
<input type="text" @input="test" v-model="q" />
</div>
</template>

<script>
export default {
data() {
return {
q: ""
};
},
methods: {
test(e) {
// console.log(e.target.value); // 其值实际上和q的值一样
console.log(this.q);
}
}
};
</script>

<style scoped>
</style>

上面这段代码执行的时候,当我们在input搜索框中进行输入的时候,都会随之修改data中的数据q,这就是v-model双向数据绑定的结果,非常方便。

那么当我将input封装进一个组件中,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// src/components/inputdemo.vue
<template>
<div>
<input type="text" />
</div>
</template>

<script>
export default {
data() {
return {};
}
};
</script>

<style scoped>
</style>

然后引用这个组件,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
<div>
<h1>测试专用demo</h1>
<!-- 这样子inputdemo的@input是触发不了的,我额外写了一个button来点击查看q的值 -->
<inputdemo v-model="q" @input="test"></inputdemo>
<button @click="test">点击查看q的值</button>
</div>
</template>

<script>
import inputdemo from "../components/inputdemo";
export default {
data() {
return {
q: ""
};
},
components: {
inputdemo
},
methods: {
test() {
console.log(this.q);
}
}
};
</script>

<style scoped>
</style>

像这样直接就在组件标签<inputdemo>中使用v-model='q'企图像原生input那样做到双向数据绑定是不可以的。

那么应该怎么做才对?

  1. 在inputdemo组件中的props里记录value,必须是value。
  2. 在inputdemo组件的input标签中绑定:value="value"
  3. 在inputdemo组件的input标签中添加事件@input="$emit('input', $event.target.value)",向调用者emit一个事件称为input,同时将$event.target.value作为参数传过去。

这样就可以直接在组件标签<inputdemo>中使用v-model='q'像原生input那样做到双向数据绑定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/components/inputdemo.vue
<template>
<div>
<input type="text" :value="value" @input="$emit('input', $event.target.value)" />
</div>
</template>

<script>
export default {
props: ["value"],
data() {
return {};
}
};
</script>

<style scoped>
</style>

参考文档:https://cn.vuejs.org/v2/guide/components-custom-events.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E7%9A%84-v-model