web前端现代前端指南!

v-model的实现原理

2020-08-21  本文已影响0人  姜治宇

vue中的v-model很好用,我们经常用它做双向绑定:

<template>
  <div id="app">
    {{username}} <br/>
    <input type="text" v-model="username">
  </div>
</template>

<script>
export default {
  name: 'App',
  data(){
    return {
      username:''
    }
  }

}
</script>

v-model其实是个语法糖,它实际上是做了两步动作:
1、绑定数据value
2、触发输入事件input
也就是说,v-model等同于:

<template>
  <div id="app">
    {{username}} <br/>
    <input type="text" :value="username" @input="username=$event.target.value">
  </div>
</template>

<script>
export default {
  name: 'App',
  data(){
    return {
      username:''
    }
  }

}
</script>

明白了这一点非常有用,我们可以在自定义的input组件中使用它:

<template>
  <div id="app">
    {{username}} <br/>
    <my-input type="text" v-model="username"></my-input>
  </div>
</template>

<script>
import myinput from './components/myinput'
export default {
  name: 'App',
  components:{'my-input': myinput},
  data(){
    return {
      username:''
    }
  }

}
</script>

myinput.vue:

<template>
    <div class="my-input">
        <input type="text" class="my-input__inner" @input="handleInput"/>
    </div>
</template>

<script>
    export default {
        name: "myinput",
        props:{
            value:{ //获取父组件的数据value
                type:String,
                default:''
            }
        },
        methods:{
            handleInput(e){
                this.$emit('input',e.target.value) //触发父组件的input事件
            }
        }
    }
</script>

<style lang="scss" scoped>
    .my-input {
        width: 180px;
        position: relative;
        font-size: 14px;
        display: inline-block;
    .my-input__inner {
        -webkit-appearance: none;
        background-color: #fff;
        background-image: none;
        border-radius: 4px;
        border: 1px solid #dcdfe6;
        box-sizing: border-box;
        color: #606266;
        display: inline-block;
        font-size: inherit;
        height: 40px;
        line-height: 40px;
        outline: none;
        padding: 0 15px;
        transition: border-color .2s cubic-bezier(.645,.045,.355,1);
        width: 100%;

    &:focus {
         outline: none;
         border-color: #409eff;
     }
    }
    }
</style>

上一篇下一篇

猜你喜欢

热点阅读