vue3.3 版本新特性总结 defineOptions、defineModel、defineSlots、defineEmits

新特性主要围绕着父子组件之间的相关的功能更新。

本文主要以代码展示的风格来介绍功能。大家可以直接搞个父子组件,把对应代码复制粘贴进去,然后一个个试验即可。自己也动动手,加深理解。
除了标题的4个宏指令,还有 toRef 和 toValue,但让我挺无语的。。感觉没啥用,求指教。。


以下案例包含的vue3.3新内容:

defineOptions、defineModel、defineSlots、defineEmits、toRef、toValue

html 复制代码
<template>
  <div>
    <div>父组件</div>
    <div>vue3.3新特性</div>
    <div>
      <child @test1="test1" v-model:inputName.animation="data1">
        <template #default='{ msg, num }'>{{ msg }}---slot文本---{{ num }}</template>
      </child>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref,watch } from "vue";
import child from "./child.vue";
const data1 = ref(undefined)
// const data1 = ref('')
watch(data1,(val)=>{
  console.log(val,'监听是否变化');
})
setTimeout(() => {
  data1.value = '肥伦'
  console.log('变更数据',data1.value);
}, 1000);

function test1(val1, val2) {
  console.log(val1, val2);
}
</script>
<style lang="">
  
</style>
html 复制代码
<template>
  <div>
    <div>子组件</div>
    <div><input type="text" v-model="modelValue"></div>
    <button @click="c1">子组件测试按钮</button>
    <slot msg="传给父的信息" :num="1234">1</slot>
    <div>{{ dd1 }}</div>
    <div>{{ dd2 }}</div>
    <div>{{ dd3 }}</div>
  </div>
</template>
<script setup lang="ts">
import { ref, reactive, toRef, toValue, toRaw, unref,isReactive } from 'vue'
const state = reactive({
  foo: 1,
  bar: 2
})

const fooRef = toRef(() => state.foo) // 新特性: 创建一个只读的 ref; 仅限于不能修改 fooRef.value; 若 .value 是个对象,对象里面还是可以随便改的。

const dd2 = ref(1)
const dd1 = toRef(dd2) // // 按原样返回现有的 ref
// console.log(dd1===dd2); // true; 

const dd3 = toRef(1) // 等价于 ref(1)


// toValue; 跟 unref 、 toRaw 类似; 
// 首先 toValue 和 unref 都针对 ref 类型的响应式数据, toRaw 针对 reactive 类型的响应式数据; 
// 这3个用的时候,如果传的数据不符合,则直接返回所传的数据;
// 这个就懒得写示例了。。因为觉得没啥用啊,求指教...


// defineOptions
// 这个宏可以用来直接在 <script setup> 中声明组件选项,而不必使用单独的 <script> 块:
// 在两年前我看官方文档对着各个API敲案例的时候,那会如果要用到 name、inheritAttrs 还得声明2个script,现在都不用了,物是人非哈哈
defineOptions({
  name: 'thiscpmName', // 像递归组件要用到组件名的时候,就可以显示声明了
  inheritAttrs: true, // 涉及绑定属性的继承之类
  mounted() {
    console.log('牛头人啊。。真有用啊?');
  },
})


// defineModel 是 props + emit 的语法糖, defineModel就只建议用运行时声明的写法了!
// defineModel([name], [prop])的参数说明
/**
 * name 和 prop 选项都不是必填。
 */
/**
 * prop {} 参数详解
 * {
 *    type: String // 表示vmodel绑定的值类型,不符合控制台抛出警告。
 *    default: '芙莉莲' // 当父组件vmodel传入的是 undefine 将使用该默认值。
 *    set: function // 修改该 model 时触发
 *    get: function // 访问该 model 时触发
 * }
 */

// const modelValue = defineModel() // 写法1,子组件这里等价于props.modelValue + update:modelValue ;(由父组件通过 v-model 使用)
// const modelValue = defineModel({ type: String,default:'芙莉莲' }) // 写法1的基础上,设置model的功能选项。
// const modelValue = defineModel('inputName') // 写法2,子组件这里等价于props.inputName + update:inputName ;(由父组件通过 v-model:inputName 使用)
// const modelValue = defineModel('inputName', { type: String, default: '芙莉莲' }) // 写法2的基础上,声明 prop 选项
// ↓ 写法3,如果v-model声明了修饰符,则需要通过解构返回值的方式获取;
const [modelValue, modelModifiers] = defineModel('inputName', {
  type: String,
  default: '芙莉莲',
  set(val) {
    if (modelModifiers.animation) {
      return val.trim()
    }
    return val
  },
  // get(val){
  //   return val
  // }
})
console.log(modelValue.value, modelModifiers);
// modelValue 在被修改时,触发 "update:inputName" 事件; 不声明model的name时,则是默认的 update:modelValue
// 总结就是根本不用管他是 update:xxx 什么玩意,这部分不重要,因为defineModel写法下,你不需要自己去调用了!
setTimeout(() => {
  // emit('update:inputName','测试有用吗') 
  // 如果你非要自己手动调用,也是可以的!但会报TS错,因为emit没有声明该类型,解决方法就是你去声明一下就好了。
  // 但是最终还不如 modelValue.value = xx 的方式去修改更好! 
  modelValue.value = '测试更改有效的!'
}, 5000);



// 特别注意,使用对应版本的新特性时,如果遇到TS报错、实际能跑的情况下,请所有更新相关版本!(查了下官网里说的对应的版本信息)
// 不然就会像我,旧的VUE3练习项目是2年前的,看到报错还以为VUE有问题。。
const emit = defineEmits<{
  test1: [id: number, val?: string] // key是事件名,val是传输数据的数据类型、数量
  bar: [name: string, ...rest: number[]]
}>();
function c1() {
  emit('test1', 1)
}



// defineSlots() 只接受类型参数,没有运行时参数。
// 函数的第一个TS对象类型参数是插槽期望接收的 props 的TS类型
// 返回值类型目前被忽略,可以是 any,但官方说将来可能会利用它来检查插槽内容。
const slots = defineSlots<{
  // key > default 是插槽名称
  // 值类型是插槽函数,props就是作用域插槽声明的传递的数据
  default(props: { msg: string, num: number }): any
}>()
</script>
<style lang="">
  
</style>
相关推荐
AI_零食32 分钟前
番茄钟鸿蒙PC Electron框架完成:状态机、定时器管理与专注力工具设计
前端·javascript·华为·electron·开源·鸿蒙·鸿蒙系统
提子拌饭13333 分钟前
逛三园游戏——基于鸿蒙PC Electron框架实现
前端·javascript·游戏·华为·electron·鸿蒙
llz_11235 分钟前
web-第三次课后作业
前端·后端·web
遗憾随她而去.1 小时前
Web地图全体系深度梳理:引擎、数据源、图层、投影核心知识
前端
爱因斯坦乐1 小时前
Vue项目整合
前端·javascript·vue.js
FlyWIHTSKY1 小时前
TS、TSX、JS、JSX 文件扩展名详解
开发语言·javascript·ecmascript
无风听海1 小时前
IndexedDB 深度指南 浏览器中的事务型对象数据库
前端·数据库
ct9782 小时前
组件间的通信
前端·javascript·vue.js
左手吻左脸。3 小时前
Vue 全栈面试题大全(2026 最新版最详细)
前端·javascript·vue.js
Aphasia3113 小时前
手写KeepAlive组件
前端·react.js·面试