v-model語法糖介紹,實現一個自定義input元件
html:
<template>
<div class="jsInput">
<div class="jsInput-content">
<input class="my-input" :type="type" @focus="handlerFocus" @blur="handlerBlur" @input="handlerChange" v-bind="$attrs" ref="input" v-model="currentValue" :placeholder="placeholder">
<div class="append">
<slot name="append"></slot>
</div>
<div class="error-message" v-show="isError">
<i class="iconfont icon-gantanhao"></i>{{errorMessage}}
</div>
</div>
</div>
</template>
js:
export default {
props:{
errorMessage:{
type:String,
default:''
},
placeholder:{
type:String,
default:''
},
value:{
type:String,
default:''
},
isError:{
type:Boolean,
default:true
},
type:{
type:String,
default:'text'
}
},
methods:{
handlerChange(event){
this.$emit('change', event.target.value);
},
handlerBlur(event){
this.$emit('blur', event.target.value);
},
handlerFocus(event){
this.$emit('focus', event.target.value);
}
},
computed:{
currentValue: {
// 動態計算currentValue的值
get:function() {
return this.value; // 將props中的value賦值給currentValue
},
set:function(val) {
this.$emit('input', val); // 通過$emit觸發父元件
},
}
}
}
css:
<style lang="less" scoped>
.jsInput .jsInput-content{
position: relative;
padding-bottom: 24px;
}
.jsInput .jsInput-content input{
-webkit-appearance: none;
background-color: #fff;
background-image: none;
border: none;
border-bottom: 1px solid #dcdfe6;
box-sizing: border-box;
display: inline-block;
font-size: inherit;
height: 40px;
line-height: 35px;
padding-top: 5px;
outline: none;
transition: border-color .2s cubic-bezier(.645,.045,.355,1);
width: 100%;
font-family: PingFangSC-Regular;
font-size: 14px;
color: #5C6466;
}
.jsInput .jsInput-content input:focus{
outline: none;
border-color: #409eff;
}
.jsInput .jsInput-content .append{
position: absolute;
right: 0;
top: 0;
height: 40px;
line-height: 40px;
font-size: 12px;
}
.jsInput .jsInput-content .error-message{
position: absolute;
bottom:0;
left: 0;
height: 24px;
line-height: 24px;
font-family: PingFangSC-Regular;
font-size: 12px;
color: #EC2525;
}
.jsInput .jsInput-content .error-message i{
font-size: 12px;
margin-right: 4px;
}
</style>
通過上述實現父子雙向繫結的關鍵在於=》this.$emit('input', val),這就設計了v-model的語法糖:
<input v-model="something">
即可以理解為:
<input v-bind:value="something" v-on:input="something = $event.target.value">