vue3的v-model

回顾v2版v-model双向绑定

<!-- ./components/CustomComponent.vue -->
<template>
  <button @click="change">use 100</button>
</template>

<script>
export default {
  props: {
    value: {
      type: Number,
      default: 0,
    },
  },
  methods: {
    change() {
      this.$emit("input", this.value - 100);
    },
  },
};
</script>

外部使用:

<!-- money = $event 不能省略为只有 money -->
<Custom :value="money" @input="money = $event" />

v-model就是默认value+@input的语法糖:

<Custom v-model="money" />

修改v-model的默认绑定

v2.2起,新增了组件内的model选项,以支持硬编码的绑定value+input改为其他名字,这样做的好处是将value释放出来移作他用:

<script>
export default {
  model: {
    prop: 'money',
    event: 'change'
  },
  props: {
    // 这将允许 `value` 属性用于其他用途
    value: String,
    // 使用 `money` 代替 `value` 作为 model 的 prop
    money: {
      type: Number,
      default: 0
    }
  },
  methods: {
    change() {
      // 触发model绑定的新的名为 change 的事件
      this.$emit("change", this.money - 100)
    }
  }
}
</script>


 
 
 
 












 




外部使用:

<!-- money = $event 不能省略为只有 money -->
<Custom :money="money" @change="money = $event" />

此时的v-model就是默认money+@change的语法糖:

<Custom v-model="money" />

多props的双向绑定(.sync)

由于v2版对v-model的硬编码性,无法做到使用v-model来对多个props实现双向数据绑定。因此在v2.0时加入了.sync修饰符来辅助达到同样(双向绑定)的效果!

<template>
  <div>
    <button @click="changeMoney">use 100</button>
    <button @click="changeAge">age + 1</button>
  </div>
</template>

<script>
export default {
  model: {
    prop: "money",
    event: "change",
  },
  props: {
    value: {
      type: Number,
      default: 0,
    },
    money: {
      type: Number,
      default: 0,
    },
    age: {
      type: Number,
      default: 0,
    },
  },
  methods: {
    changeMoney() {
      this.$emit("change", this.money - 100);
    },
    changeAge() {
      // 若期望使用 .sync 来优化外部用法,这里的 changeAge 需要改为和 props 名 age 一致
      // 即为 update:age (要双向绑定谁 就 update: 谁)
      this.$emit("update:changeAge", this.age + 1);
    },
  },
};
</script>

外部使用:

<Custom v-model="money" :age="age" @update:changeAge="age = $event" />

使用.sync简化代码:

<Custom v-model="money" :age.sync="age" />

它是下列语法的语法糖:

<Custom v-model="money" :age="age" @update:age="age = $event" />

破坏性更新

默认value和input名称更改

默认的props和事件名更改:

value => modelValue;

input => update: modelValue;

这番调整等于是把v2中的valueinput的硬绑定取消了,并将默认v-model的绑定方式以类似.sync的需求格式进行绑定。这样做的好处是默认的modelValue和其余自定义props是同级的了,只是v3中直接使用v-model所表示的就是v-model:modelValue

提示

原生控件input的属性和事件绑定方式没有发生改变:

注意:原生控件值的绑定是$event.target.value而自定义组件只用$event

<input :value="searchText" @input="searchText = $event.target.value" />
<!-- 简化后 -->
<input v-model="searchText" />

移除了.sync修饰符和model组件选项

v3中的v-model支持多个props的绑定,且书写和阅读更为友好。因此,这两项(.sync、model)被淘汰了。

v3新增的内容

支持多个v-model

是的,现在支持在自定义组件上写多个v-model了,这主要是为了优化曾经实现相同功能v-bind.sync的解决方案。

之前v2时默认使用value属性+input事件来实现的v-model,现在它们改名为:modelValue+update:modelValue;

<!-- ./components/Custom.vue -->
<template>
  <div>
    <button @click="changeModelValue">use 100</button>
    <button @click="changeAge">age + 1</button>
  </div>
</template>

<script>
export default {
  props: {
    // 注意:现在的默认值都必须被显式声明!
    modelValue: {
      type: Number,
      default: 0,
    },
    age: {
      type: Number,
      default: 0,
    },
  },
  methods: {
    changeModelValue() {
      this.$emit("update:modelValue", this.modelValue - 100);
    },
    changeAge() {
      this.$emit("update:age", this.age + 1);
    },
  },
};
</script>











 



 






 


 





外部使用:

<template>
  <div>
    <Custom
      :modelValue="money"
      @update:modelValue="money = $event"
      :age="age"
      @update:age="age = $event"
    />
    <p>father have {{ money }}</p>
    <p>father age {{ age }}</p>
  </div>
</template>

<script>
import Custom from "./components/Custom.vue";
export default {
  components: {
    Custom,
  },
  data() {
    return {
      money: 1000,
      age: 30,
    };
  },
};
</script>



 
 
 
 




















v-model语法糖写法:

<Custom v-model="money" v-model:age="age" />

自定义修饰符

v3开放了v-model修饰符自定义的能力,因此可以做到更多个性化内容定制。

自定义修饰符的方法非常简单:

  1. 在自定义组件内部的props内定义一个预获得修饰符的props name + Modifiersprops。注意:
    • 被修饰的props本身是双向绑定的,普通props不行;
    • 默认的modelValue不用写成modelValueModifiers,这样即可:modelModifiers
  2. 在外部使用时,对v-model的值后加.xxxxxx表示自己自定义的修饰符名称。自定义组件内部会在created生命周期以后尝试获取并存入xxxModifiers内,其值被设置时为true,未设置时为undefined。内部则可根据xxxModifiersbool状态执行处理逻辑。
<script>
export default {
  props: {
    modelValue: {
      type: Number,
      default: 0,
    },
    age: {
      type: Number,
      default: 0,
    },
    modelModifiers: { default: () => ({}) },
    ageModifiers: { default: () => ({}) },
  },
  created() {
    console.log(this.modelModifiers.yyy);
    console.log(this.ageModifiers.xxx);
  },
};
</script>











 
 


 
 



使用方式:

<Custom v-model="money" v-model:age.xxx="age" />
<!-- 
此时created中的结果:
created() {
  console.log(this.modelModifiers.yyy);  // false
  console.log(this.ageModifiers.xxx);    // true
},
-->

参考资料:v3 v-modelopen in new windowv-model自定义修饰符open in new window

最近更新:
Contributors: untilthecore