一、介绍
在vue项目中,我们会用到很多类型的框架,例如:ElementUI等等。
此时如果我们要二次封装UI框架中的输入框组件时,你会想用v-model的方式进行绑定来实现。那么这篇博客可能能帮到你。
二、封装组件
numberInput.vue子组件文件:
<template>
<div class="flex">
<el-input class="input" :value="value" placeholder="填数字" @input="inputChange($event)"></el-input>
<div class="btn-group input-border-color">
<div class="btn" @click="onClickChangeBtn('add')">+</div>
<div class="btn input-border-color" @click="onClickChangeBtn('sub')">-</div>
</div>
</div>
</template>
<script>
export default {
name: "NumberInputComponent",
props: {
value: String | Number // 这里接收父组件v-model绑定的变量
},
data() {
return {
}
},
methods: {
inputChange(val) {
if (["", undefined].includes(val)) {
val = "" }
// 在这里就修改了父组件中,用v-model绑定的变量的值。父组件的变量修改后,numberInput.vue中props中的value值就跟着改变了。
this.$emit("input", val)
},
onClickChangeBtn(type) {
var num = parseInt(this.value)
if (isNaN(num)) {
num = 0 }
if (type === "add") {
num++
} else {
num--
}
if (num < 0) {
num = 0 }
this.$emit("input", num)
}
}
}
</script>
<style lang="scss" scoped>
.input {
width: 70px !important;
& ::v-deep .el-input__inner {
padding: 0 10px !important;
}
}
.btn-group {
display: flex;
flex-direction: column;
width: 30px;
height: 40px;
box-sizing: border-box;
border-top: 1px solid;
border-right: 1px solid;
border-bottom: 1px solid;
background-color: #fff;
user-select:none;
.btn {
display: flex;
justify-content: center;
align-items: center;
height: 50%;
box-sizing: border-box;
}
.btn:active {
opacity: .5; }
.btn + .btn {
border-top: 1px solid;
}
}
.input-border-color {
border-color: #dcdfe6 !important;
}
</style>
使用:
<p>被检精子数:<span class="reportSpanSort">{
{ obj.number }} 个</span></p>
<div>
被检精子数:
<div class="flex items-center">
<NumberInput v-model="obj.number" />个
</div>
</div>
<script>
import NumberInput from "@/components/numberInput.vue"
export default {
...
components: {
NumberInput },
}
</script>
三、分析
想要封装的input组件实现v-model的方式,来绑定属性,就要先了解v-model大概的原理。
<input v-model="obj.number">
相当于
<input v-bind:value="obj.number" v-on:input="obj.number= $event.target.value">
<NumberInput v-model="obj.number"></NumberInput>
相当于
<NumberInput v-bind:value="obj.number" v-on:input="obj.number= argument[0]"></NumberInput>
这个时候,obj.number接收的值就是input监听事件的回调函数的第一个参数,所以在自定义组件中,要实现数据绑定,还需要$emit去触发input的事件。
this.$emit('input', value)
四、效果图
可以看到,我们二次封装的输入框组件就已经生效了。