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>
相关推荐
掘金一周5 分钟前
你们觉得房贷多少,没有压力 | 沸点周刊 4.30
前端·人工智能·后端
大貔貅喝啤酒5 分钟前
接口测试_Postman(详细版)
javascript·测试工具·node.js·自动化·postman
小小码农Come on7 分钟前
QML访问子项内容
前端·javascript·html
桜吹雪20 分钟前
Langchain.js官方文档:构建具备按需加载技能的 SQL 助手
javascript·人工智能·node.js
han_26 分钟前
一篇看懂国内外主流大模型:GPT、Claude、Gemini、DeepSeek、通义千问有什么区别?
前端·人工智能·llm
一行代码一行诗++35 分钟前
注释是什么和注释该怎么写(C语言)
java·前端·javascript
涂兵兵_青石疏影42 分钟前
beginPath-vs-save详解
前端
陈振wx:zchen200843 分钟前
前端-面试题-JavaScript
javascript·前端面试题
Forever7_44 分钟前
Vue 全局监控用户行为,最强方案!
vue.js
泽_浪里白条1 小时前
我在 Superset 6.x 做自定义图表 + Embedded SDK 集成的实战复盘(附踩坑清单)
前端·数据可视化