v-model一些理解

用过vue同学,都知道v-model可以实现双向绑定,方便我们的赋值和获取。

<input v-model="value"/>

使用v-model可以轻松的获取我们输入的值。下面我们就来研究下其中的原理:

通常我们写一个组件,子组件要获取父组件的值,通过props传值,父组件要获取子组件要通过$emit绑定一个方法,通过调用这个方法获取相应的值。

子组件:zInput

<template>
  <input type="text" @input="changValue" />
</template>

<script>
export default {
  props: {
    value: { type: String, default: '' }
  },
  methods: {
    changValue(e) {
      this.$emit('input', e.target.value)
    }
  }
}
</script>

父组件:

<template>
  <div class="test">
    <zInput :value="value" @input="getInput" />
  </div>
</template>
<script>
import zInput from './zInput'
export default {
  components: { zInput },
  data() {
    return {
      value: ''
    }
  },  
  methods: {
    // 获取子组件的值
    getInput(val) {
      console.log(val)
    }
  }
}
</script>

这是一般的写法,我们该怎么用v-model实现数据的双向绑定呢,首先我们要弄清楚model的原理:

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件

v-model 相当于 :value="value" @input="getInput" 那我我们就可以这样写父组件了:

<template>
  <div class="test">
    <zInput v-model="value"/>
  </div>
</template>
<script>
import zInput from './zInput'
export default {
  components: { zInput },
  data() {
    return {
      value: ''
    }
  },  
  watch:{ 
    value(val){
      console.log(val)
    }
  }
}
</script>

现在是不是清晰了很多,v-model就是父组件默认传一个默认为value的值给子组件,并且默认获取input事件。如果你理解了就可以动手改造我们的代码,就可以解决之前的来回传值和获取的烦恼了。

如果你还是觉得这样满足不了你的需求,你可以尝试下自定义v-model:

vue2.2.0+ 新增

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。model 选项可以用来避免这样的冲突:

先看下官网的例子:

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

我们可以自定义prpo传入的值和$emit的事件,这样我们可以更加灵活的使用v-model,实现我们的需求。

我们可以用computed中的get和set更好的实现的我们的自定义的双向绑定,如果不是太了解,可以看下:计算属性 vs 侦听属性

下面我们用elment-ui中的单选框举例:

子组件zRadio

<template>
  <div>
    <el-radio-group v-model="radioValue">
      <el-radio-button label="上海"></el-radio-button>
      <el-radio-button label="北京"></el-radio-button>
      <el-radio-button label="广州"></el-radio-button>
      <el-radio-button label="深圳"></el-radio-button>
    </el-radio-group>
  </div>
</template>

<script>
export default {
  props: {
    radio: { type: String, default: '' }
  },
  model: {
    props: 'radio',// 自定义传入的值
    event: 'change'// 自定义我们的事件
  },
  computed: {
    radioValue: {
      get() {
        return this.radio // 接收传进来的值
      },
      set(value) {
        // 设置radio的值并通过model的change的事件传出改变的值
        this.$emit('change', value) 
      }
    }
  }
}
</script>

父组件:我们可以直接获取radio的绑定的值,也可以用chang获取事件

<template>
  <div class="test">
    <zRadio v-model="value" :radio="value" @change="getValue" />
  </div>
</template>
<script>
import zRadio from './zRadio'
export default {
  components: { zRadio },
  data() {
    return {
      value: ''
    }
  },
  watch: {
    value(val) {
      console.log(val)
    }
  },
  methods: {
    getValue(val) {
      console.log(val)
    }
  }
}
</script>

这样我们精简了我们的代码,也简化了我们的复杂的传值,自己动手改造下自己的代码吧。

了解更多,可以去我的博客,让我们共同学习进步!

posted @ 2020-06-30 16:10  童心虫鸣  阅读(611)  评论(0编辑  收藏  举报