1. 程式人生 > >v-model語法糖介紹,實現一個自定義input元件

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">