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() 的双向绑定:

父组件:

c 复制代码
<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>

子组件

c 复制代码
<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

如图:

父组件:

c 复制代码
<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>

子组件:

c 复制代码
  <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() 设置额外参数如类型、默认值

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

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

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

如:

父组件:

c 复制代码
<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>

子组件:

c 复制代码
<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>
相关推荐
LabVIEW开发21 分钟前
LabVIEW 前面板装饰图形的格式选择与自定义选板添加
前端·labview·labview知识·labview功能·labview程序
掘金者阿豪28 分钟前
GPT-6 Astra 来了,GPT-5.6 Sol 还值得用吗?聊聊 Coding、百万上下文、价格和 Plus/Pro
前端·后端
code 小楊29 分钟前
腾讯开源 WeKnora 深度解析:RAG 问答 + ReAct Agent 推理 + 自动 Wiki 图谱,三位一体的企业级知识中台
前端·人工智能·开源·知识图谱
roamingcode34 分钟前
让 AI 的回答「逐段说话」:react-streaming 的顺序流式渲染实践
前端·人工智能·react.js·codex
BioRunYiXue36 分钟前
科研干货 | IC50全面解读:概念解析、实验设计与数据分析要点
java·开发语言·javascript·人工智能·算法·数据挖掘·数据分析
cidy_9842 分钟前
Main 正式环境合并说明
前端
万物智能1 小时前
开源鸿蒙内核配置与驱动三条路径—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
前端·后端
每天吃饭的羊1 小时前
WebAssembly
开发语言·javascript·wasm
hunterandroid1 小时前
Android 多渠道打包与 Gradle 构建优化实战
android·前端·kotlin
cidy_981 小时前
Develop 测试环境合并说明
前端