vue3学习教程第二十节(新增编译宏defineModel)

为什么会需要使用defineModel()

注意:defineModel() 需要在3.4及以上版本才可使用;

组件之间通讯,通过 props 和 emits 进行通讯,是单向数据流,比如:props是自上而下的(父组件数据修改导致子组件更新,而自己不能修改父组件传入的 props属性),而emits是自下而上的(子组件通过事件触发父组件事件);

defineModel() 返回的值是一个 ref
它可以像其他 ref 一样被访问以及修改,不过它能起到在父组件和当前变量之间的双向绑定的作用:
defineModel() 实现原理defineModel() 的双向绑定是在编译之后,创建了一个modelref变量以及一个modelValue的props,并且watchprops中的modelValue;当子组件中的modelValue更新时,会触发update:modelValue事件,当父组件接收到这个事件时候,同时更新父组件的变量;
它的 .value 和父组件的 v-model 的值同步;
当它被子组件变更了,会触发父组件绑定的值一起更新

1、defineModel() 的双向绑定:

父组件:

<template>
  <div class="my-define-module">
    This is a defineModel text page.
    // 使用v-model 绑定person对象
    <ChildMy v-model="person"/>
    <hr>
    {{ person.name  }}---{{ person.age }}
  </div>
  </template>
  <script setup>
  import ChildMy from './child.vue'
  import { ref } from 'vue' 
  const person = ref({
    name: 'Andy',
    age: 11
  })
  </script>

子组件

<template>
<div class="my-define-module">
  child -- {{person.name}} // 第一次打印的是父组件传递过来的 Andy
  <el-button type="primary" @click="updatedName">child btn</el-button>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
// defineModel() 返回的是一个ref对象
const person = defineModel({
  name: 'child',
  age: 18
})
console.log('==person==child=', person.value)
const updatedName = () => {
  // 子组中更新person 属性,会同时更新父组件的person属性
  person.value.name = `${person.value.name}+$`
  person.value.age = person.value.age + 1
}
</script>

2、defineModel() 创建多个v-model

注意:需要都是基本类型,不能是引用类型,否子组件读到的是undefined
如图:
父组件:

<template>
  <div class="my-define-module">
    This is a defineModel text page.
    <!-- <ChildMy  v-model="person"/> -->
    // 传入多个v-model时的person是Object,导致子组件中person无法通过defineModel获取
    <ChildMy v-model:person="person" v-model:job="job" v-model:num="num"/>
    <hr>
    {{ person.name  }}---{{ person.age }} 
  </div>
  </template>
  <script setup>
  import ChildMy from './child.vue'
  import { ref } from 'vue' 
  const person = ref({
    name: 'Andy',
    age: 11
  })
  // 初始化定义时,当父组件没有传入默认值时候,子组件中的job值不父组件的值不同步,子组件展示的是子组件初始化的值--前端
  const job = ref()
  const num = ref(3)
  </script>

子组件:

  <template>
<div class="my-define-module">
  child -- {{person.name}}
  <hr>
  --job--{{ job }}
  <hr>
  num---{{num}}
  <el-button type="primary" @click="updatedName">child btn</el-button>
  <el-button type="primary" @click="updatedJob">child job</el-button>
  <el-button type="primary" @click="updatednum">child num</el-button>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
// defineModel() 返回的是一个ref对象
const person = defineModel({
  name: 'child',
  age: 18,
})
const num = defineModel('num', 2)
const job = defineModel('job', '前端')
console.log('--job---', job) // value => 前端
console.log('--num---', num) // value => 3
console.log('==person==child=', person) // value => undefined
</script>

如图:
请添加图片描述

3、defineModel() 设置额外参数如类型、默认值

const job = defineModel('job', {default: '', type: String, required: true})
编译后的 
props:{
  job:{
    default: '',
    type: String,
    required: true
  }
}

4、defineModel() 添加自定义修饰符:

需要使用数组解构方法获取 model 和 modifiersmodel即为ref对象,modifiers即为修饰符对象
如:
父组件:

<template>
  <div class="my-define-module">
    This is a defineModel text page.
    <ChildMy  v-model.upLow="job"/>
    <hr>
    parents--s{{ job }} // 初始化 5
  </div>
  </template>
  <script setup>
  import ChildMy from './child.vue'
  import { ref } from 'vue' 
  const job = ref(5)
  </script>

子组件:

<template>
<div class="my-define-module">
  <hr>
  --job--{{ model }}
  <hr>
  <el-button type="primary" @click="updatedJob">child job</el-button>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const [model, modifiers] = defineModel({
  get(value) {
    console.log('-get-job---', value)
    return value
  },
  set(value) {
    if (modifiers.upLow) { // 有upLow修饰符的v-model 会将值累加 22
      return value + 22 
    }
    return value
  }
})
console.log('--job-model--', model)
console.log('--job-modifiers--', modifiers)
const updatedJob = () => {
  model.value = model.value + 10 // 更新model.value的值
}
</script>
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刺客-Andy

努力将爱好变成更有价值的事物

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值