vue 之 在自定义组件上使用v-model

154 阅读1分钟

v-model: 用于在表单输入元素应用状态之间 创建双向数据绑定

  • 既可以 支持 原生表单元素(input select textarea )
  • 也可以支持自定义组件(v2.2.0+新增)

如果你想自己实现类似 v-model 的功能,你需要理解 Vue 的自定义指令和事件处理机制。

创建一个自定义指令

// 自定义指令 'v-custom-model'
Vue.directive('custom-model', { 
   bind(el, binding, vnode) { 
        // 1.绑定时设置初始值
        el.value = binding.value; 
        // 2.添加事件监听器来更新数据 
        el.addEventListener('input', 
        () => { vnode.context[binding.arg] = el.value; }); 
    }, 
    update(el, binding) { 
    // 当绑定值更新时,更新 DOM 元素的值 
        el.value = binding.value; 
    } 
});

在组件中使用自定义指令:

<input v-custom-model="message" />

(但这种方法并不完全符合 v-model 的使用习惯,因为 v-model 通常是一个语法糖,它结合了 v-bind 和事件监听)

更推荐的方案:

  • 默认使用 :value="value"(props) 和 @input 事件
  • 可以使用 model 属性 配置 prop 和event
<template>
  <input :value="value" @input="$emit('input', $event.target.value)" />
</template>

<script>
export default {
  props: ['value']
};
</script>

父组件的使用

<template>
  <div>
    <MyInput v-model="message" />
    <p>{{ message }}</p>
  </div>
</template>
  • 父组件使用v-model="xxx"
  • 子组件定义value是"switchStatus", 在子组件里使用的都是switchStatus
<span
      class="switch-button"
      :class="{ open: switchStatus }"
      @click.stop="toggleButton"
    ></span>
//...
 name: "BasicSwitchButton",
  props: {
    switchText: {
      type: String,
      default: "",
    },
    switchStatus: {
      type: Boolean,
      default: false,
    },
  },
  model: {
    prop: "switchStatus",
    event: "change",
  },
  methods: {
    toggleButton() {
      this.$emit("change", !this.switchStatus);
    },
  },
//...