Vue3.0新特性----v-model指令

model选项和v-bind:value.sync修饰符被移除,统一为v-model的参数形式
  • 这里说一下v-model的一个隐蔽特性,当我们组件的props只有一个属性时,默认会被当作modelValue传入,所以我们父组件中使用:v-model="xxx",子组件:props:{modelValue:String}直接接收就可以。
//父组件
<template>
  <v-model-test v-model="counter"></v-model-test>
  //相当于
  <v-model-test :modelValue="counter" @update="counter = $event"></v-model-test>
</template>
<script lang="ts">
import {defineComponent} from "vue";
import VModelTest from "@/components/VModelTest.vue";
export default defineComponent({
  components: {
    VModelTest,
  },
  data() {
    return {counter:20};
  },
});
</script>



//子组件
<template>
  <p>{{modelValue}}</p> //modelValue:20
  <button @click="handleClick">修改<button>
</template>
<script lang="ts">
import {defineComponent} from "vue";
export default defineComponent({
  props:{
    modelValue:Number
  },
  methods:{
    handleClick(){
      this.$emit("update:modelValue",100)
    }
  }
});
</script>

下面是我对vue2.0中model选项.sync操作符的示例,大家可以回顾一下,方便对比上面vue3.0的v-model

vue2.0 model选项

//子组件VModel.vue
我们可以自定义组件的v-model
<template>
  <div>VModel值:{{ text }} <button @click="updateValue">修改值</button></div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
  props: {
    text: {
      type: String,
      default: "初始值",
    },
  },
  model: {
    prop: "text",
    event: "setText",
  },
  data() {
    return {};
  },
  methods: {
    updateValue() {
      this.$emit("setText", "456");
    },
  },
});
</script>


//父组件Home.vue
<template>
  <div class="about">
    <VModel v-model="text"></VModel>
  </div>
</template>
<script lang="ts">
import Vue from "vue";
import VModel from "../components/VModel.vue";
export default Vue.extend({
  components: {
    VModel,
  },
  data() {
    return {
      text: "123",
    };
  },
});
</script>

vue2.3.0 新增.sync修饰符

背景:在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以变更父组件,且在父组件和子组件都没有明显的变更来源。
这也是为什么我们推荐以 update:myPropName 的模式触发事件取而代之。举个例子,在一个包含 title prop 的假设的组件中,我们可以用以下方法表达对其赋新值的意图:

//子组件VUpdate.vue中
<template>
  <div>VModel值:{{ text }} <button @click="updateValue">修改值</button></div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
  props: {
    text: {
      type: String,
      default: "初始值",
    },
  },

  data() {
    return {};
  },
  methods: {
    updateValue() {
      this.$emit("update:text", "456");
    },
  },
});
</script>

//父组件Home.vue中
<template>
  <div class="about">
    <VUpdate :text.sync="text" />
  </div>
</template>
<script lang="ts">
import Vue from "vue";
import VModel from "../components/VModel.vue";
import VUpdate from "../components/VUpdate.vue";
export default Vue.extend({
  components: {
    VUpdate,
  },
  data() {
    return {
      text: "123",
    };
  },
});
</script>

拓展

  • vue3.0装饰器的简单应用,自定义装饰器,多个v-model同时绑定,
  • 官方文档传送门我这边只是进行一个总结,想看详细文档的同学可以点击这个链接跳转
先看下基本用法
//子组件test.vue中
<template>
  <div>{{ name }}属性</div>
  <button @click="update">修改</button>
</template>
<script lang="ts">
import Vue, {defineComponent} from "vue";
export default defineComponent({
  props: {name},
  methods: {
    update() {
      this.$emit("update:name", "李四");
    },
  },
});
</script>


//父组件Home.vue中
<template>
   <Text v-model:name="propsText"></Text>
</template>
<script lang="ts">
import {defineComponent, ref} from "vue";
import Text from "@/components/test.vue";
export default defineComponent({
  components: {
    Text,
  },

  data() {
    return {
      propsText: "张三"
    };
  },
});
</script>

自定义装饰器

  • vue3.0之前v-model有三个装饰器lazy,number,trim,这三个装饰器的用法在这里不多做描述,官方文档自己可以查一下,很详细。现在我们看一下在vue3.0中的装饰器的用法

看一个例子,比如我们设计了一个组件,这个组件里面v-model只绑定了一个prop,并且没有明确指定名字,这个值那么这个值会当成modelValue Prop传给子组件,同样,装饰器也一样,如果父组件是v-model.customModifier="text",子组件就可以用this.modelModifiers来接收,看不懂这句话不要紧,下面有示例:

//子组件
<template>
  <div>
    propValue:{{ modelValue }} <button @click="updateValue">修改</button>
  </div>
</template>
<script lang="ts">
import Vue, {defineComponent} from "vue";
export default defineComponent({
  props: ["modelValue", "modelModifiers"],
  created() {
    console.log("modelValue-------------", this.modelValue);
    console.log("modelModifiers-------------", this.modelModifiers);
  },
  methods: {
    updateValue() {
      let value;
      if (this.modelModifiers.customModifier) {
        value = "更改为" + this.modelValue;
      } else {
        value = this.modelValue;
      }
      this.$emit("update:modelValue", value);
    },
  },
});
</script>



//父组件
<template>
  <div class="register-page">
    <Component1 v-model.customModifier="oneProp" />
  </div>
</template>
<script lang="ts">
import Vue, {defineComponent} from "vue";
import Component1 from "@/components/component1.vue";
export default defineComponent({
  components: {
    Component1,
  },
  data() {
    return {
      oneProp: "one string",
    };
  },
});
</script>

看一下输出


image.png

总结:当你使用v-model时,没有明确指定prop的名字时,在子组件内部可以使用modelValue接收,自定义装饰器也一样,所以当this.modelModifiers[your Modifiers Name]为true或者false时,你可以决定是否处理这个数据,整个过程就是自定义装饰器。

多个自定义装饰器

那么问题来了,实际开发中一个组件可能有好几个prop,每个prop都有各自的自定义装饰器,那么又该怎么写呢,别急,上代码!!

v-model:name.formatName会变成attr+Modifiers这样的prop传给子组件,也就是nameModifiers
v-model.customModifier会变成modelModifiers

//子组件
<template>
  <div>name:{{ name }}</div>
  <div>sex:{{ sex }}</div>
</template>

<script lang="ts">
import Vue, {defineComponent} from "vue";
export default defineComponent({
  props: ["name", "sex", "nameModifiers", "sexModifiers"],
  created() {
    console.log("name------------", this.name);
    console.log("nameModifiers----------", this.nameModifiers);
    console.log("sex-------------", this.sex);
    console.log("sexModifiers-----------", this.sexModifiers);
  },
});
</script>

//父组件
<template>
  <div class="register-page">
    <Component2 v-model:name.formatName="name" v-model:sex.formatSex="sex" />
  </div>
</template>
<script lang="ts">
import Vue, {defineComponent} from "vue";
import Component2 from "@/components/component2.vue";
export default defineComponent({
  components: {
    Component2,
  },
  data() {
    return {
      name: "杨志强",
      sex: "23",
    };
  },
});
</script>

看一下结果


image.png

总结:子组件共接受俩个prop,name 和 sex,这俩个prop分别带有自定义的装饰器,在vue3.0中,绑定的值和自定义装饰器都存在时,在子组件里面接受装饰器的名字规则就是[attr] + Modifiers,所以我们子组件里面用nameModifiers和sexModifiers来接收,之后进行相应的逻辑处理

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容