Vue3【Set Up】语法糖 + TS快速上手

文章目录

  • script setup
  • 基本语法
  • 顶层的绑定会被暴露给模板
  • 响应式
  • 监听与计算
  • 使用组件
  • 父子组件传参(变化较大)
    • 父 -> 子 defineProps()
    • 子 -> 父 defineEmits()
    • 子组件暴露给父组件内部属性 defineExpose()
  • defineOptions() 【很少用】

script setup

<script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。当同时使用 SFC 与组合式 API 时该语法是默认推荐。相比于普通的 <script> 语法,它具有更多优势:

  • 更少的样板内容,更简洁的代码。
  • 能够使用纯 TypeScript 声明 props 和自定义事件。
  • 更好的运行时性能 (其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)。
  • 更好的 IDE 类型推导性能 (减少了语言服务器从代码中抽取类型的工作)。

基本语法

要启用该语法,需要在<script> 代码块上添加 setup attribute:

<script setup>
console.log('hello script setup')
</script>

里面的代码会被编译成组件 setup() 函数的内容。这意味着与普通的 <script>只在组件被首次引入的时候执行一次不同,<script setup> 中的代码会在每次组件实例被创建的时候执行。

顶层的绑定会被暴露给模板

当使用 <script setup> 的时候,任何在 <script setup> 声明的顶层的绑定 (包括变量,函数声明,以及 import 导入的内容) 都能在模板中直接使用

<script setup>
// 变量
const msg = 'Hello!'// 函数
function log() {console.log(msg)
}
</script><template><button @click="log">{{ msg }}</button>
</template>

import 导入的内容也会以同样的方式暴露。这意味着我们可以在模板表达式中直接使用导入的 helper 函数,而不需要通过 methods 选项来暴露它:

<script setup>
import { capitalize } from './helpers'
</script><template><div>{{ capitalize('hello') }}</div>
</template>

响应式

比较常用的ref和reactive在这个语法糖中用法不变:

  • ref定义一个基本类型的响应数据
    • 操作数据: xxx.value
    • 读取数据: 不需要.value,直接:<div>{{xxx}}</div>
  • reactive定义一个复杂类型的响应数据
    • 操作数据与读取数据:均不需要.value

这里我们还可以使用ts中的泛型来进行约束:

let person = reactive<Person>({list:[]
})interface Ref<T> {value: T
}

还有toRef、toRefs等函数用法没有什么大变化

监听与计算

computed与watch的使用方法在该语法糖中也没有什么变化,但是我们需要弄清楚一个问题:在vue3中watch、computed、watchEffect使用场景有什么不同?

在vue3中,watch、computed、watchEffect都是用来监听响应式数据的变化,并执行相应的回调函数。但是它们的使用场景和区别有以下几点:

  • computed是用来计算一个派生值,它接受一个getter函数,并返回一个只读的ref对象。computed的回调函数只有在依赖的响应式数据变化时才会重新计算,否则会缓存上一次的结果。computed适合用在需要根据一些数据计算出另一个数据的场景,例如根据姓名拼接全名,或者根据购物车的商品计算总价。

  • watch是用来观察一个或多个响应式数据的变化,并执行相应的回调函数。watch接受一个响应式数据源(可以是ref、reactive、getter函数或者数组)和一个回调函数,返回一个用于停止观察的函数。watch的回调函数会在响应式数据源变化时触发,同时会传入新值和旧值作为参数。watch可以指定一些选项,例如immediate(是否立即执行回调函数)、deep(是否深度观察对象的嵌套属性)等。watch适合用在需要根据数据的变化执行一些副作用的场景,例如发送请求、操作DOM、改变其他状态等。

  • watchEffect是用来自动收集响应式数据的依赖,并执行相应的回调函数。watchEffect接受一个回调函数,返回一个用于停止观察的函数。watchEffect的回调函数会在首次执行时收集依赖,并在任何依赖变化时重新执行。watchEffect不会传入新值和旧值作为参数,也不能指定immediate或deep选项。watchEffect适合用在不需要知道具体哪个数据变化,只需要在数据变化时执行一些逻辑的场景,例如根据数据的变化更新标题、打印日志、触发自定义事件等。

使用组件

<script setup> 范围里的值也能被直接作为自定义组件的标签名使用,也就是说我们import组件之后不需要注册,可以直接使用:

<script setup>
import MyComponent from './MyComponent.vue'
</script><template><MyComponent />
</template>

这里 MyComponent 应当被理解为像是在引用一个变量。这就有点类似于JSX了。

父子组件传参(变化较大)

父 -> 子 defineProps()

父组件直接使用v-bind在子组件的标签中传递数据:

<Menu :data="data"  title="我是标题"></Menu>
<template><div class="menu">菜单区域 {{ title }}<div>{{ data }}</div></div>
</template><script setup lang="ts">
defineProps<{title:string,data:number[]
}>()
</script>

设置默认值:

type Props = {title?: string,data?: number[]
}
withDefaults(defineProps<Props>(), {title: "张三",data: () => [1, 2, 3]
})

为什么这里的data的值,要写成函数的返回值的形式?

这里的data要通过函数的形式返回的原因是为了避免多个组件实例共享同一个数组对象,导致数据混乱和污染。

如果我们不使用函数的形式返回data的默认值,而是直接写成data: [1, 2, 3],那么所有使用这个组件的地方都会使用同一个数组对象,如果其中一个组件实例修改了数组的内容,那么其他的组件实例也会受到影响,这会导致数据不一致和难以预测的行为。

因此,为了保证数据的独立性和安全性,我们需要使用函数的形式返回data的默认值,这样每个组件实例都会得到一个新的数组对象,而不会相互干扰。

子 -> 父 defineEmits()

具体过程:

  • 在子组件中,使用defineEmits函数来定义一个分发器(emitter),它接受一个字符串数组或者一个对象作为参数,用来指定要分发的事件名称和类型。
  • 在子组件中,使用emit方法来触发指定的事件,并传递相应的数据。emit方法的第一个参数是事件名称,后面的参数是要传递的数据。
  • 在父组件中,使用@或者v-on指令来监听子组件发射的事件,并定义一个回调函数来处理接收到的数据。回调函数的参数是子组件传递的数据。

父组件:

<template><div class="layout"><Menu @on-click="getList"></Menu></div>
</template><script setup lang="ts">
import { reactive } from 'vue';const getList = (list: number[]) => {console.log(list,'父组件接受子组件');
}
</script>

我们在子组件中去触发这个事件:

<template><div class="menu"><button @click="clickTap">派发给父组件</button></div>
</template><script setup lang="ts">
import { reactive } from 'vue'const emit = defineEmits(['on-click'])//如果用了ts可以这样两种方式
// const emit = defineEmits<{
//     (e: "on-click", name: string): void
// }>()
const clickTap = () => {emit('on-click', '123')
}</script>

在vue3.3中对这个语法进行了加强:

const emit = defineEmits<{'on-click':[name:string]
}>()

子组件暴露给父组件内部属性 defineExpose()

首先在子组件中定义要暴露的属性:

const list = reactive<number[]>([4, 5, 6])defineExpose({list
})

然后我们在父组件中通过ref来读:

 <Menu ref="refMenu"></Menu>
//这样获取是有代码提示的
<script setup lang="ts">
import MenuCom from '../xxxxxxx.vue'
//注意这儿的typeof里面放的是组件名字(MenuCom)不是ref的名字 ref的名字对应开头的变量名(refMenu)
const refMenu = ref<InstanceType<typeof MenuCom>>()
console.log(refMenu.value.list                                      )
</script>

defineOptions() 【很少用】

vue3中的defineOptions()是一个用于在

实际使用中一般来定义name

使用defineOptions()的一个例子是:

<script setup lang="ts">
import { defineOptions } from 'vue'// 使用defineOptions()来定义Options API的选项
defineOptions({name: 'MyComponent', // 组件的名称data() { // 组件的数据return {count: 0}},methods: { // 组件的方法increment() {this.count++}},computed: { // 组件的计算属性doubleCount() {return this.count * 2}},watch: { // 组件的侦听器count(newValue, oldValue) {console.log(`count changed from ${oldValue} to ${newValue}`)}},mounted() { // 组件的生命周期钩子console.log('component mounted')}
})
</script><template><div><p>count: {{ count }}</p><p>doubleCount: {{ doubleCount }}</p><button @click="increment">+1</button></div>
</template>

这样,我们就可以在<script setup>中使用Options API的选项,而不需要使用export default的方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/190894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能时代:AIGC的横空出世

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 什么是AIGC?二. AIGC的主要特征2.1 文本生成2.2 图像生成2.3 语音生成2.4 视…

蓝桥杯第198题 人物相关性分析 C++ 模拟 字符串 双指针

题目 思路和解题方法 程序首先定义了一个函数check&#xff0c;用于判断一个字符是否为字母。接下来&#xff0c;程序读取输入的整数k和一行字符串str。定义了两个空的向量a和b&#xff0c;用于存储满足条件的子串的起始位置。使用for循环遍历字符串str的每个字符&#xff0c;检…

string的模拟

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能手撕模拟string类 > 毒鸡汤&#xff1a;时间…

MySQL-视图

一、&#xff1f;看一个需求 emp表的列信息很多&#xff0c;有些信息是个人重要信息(比如 sal,comm,mgr,hiredate),如果我们希望某个用户只能查询emp表的(empno、ename,job和deptno)信息,有什么办法? 》视图 二、基本概念 视图 视图是一个虚拟表&#xff0c;其内容由查…

complex rsa

复数rsa&#xff0c;没遇到过这种类型的题&#xff0c;可以记录一下相关知识 先来看一段 from gmpy2 import invert,lcm,is_prime import sys sys.setrecursionlimit(2047)f (3781223486422146909054116838073773962793625267340680342971864932558735632642532480951976591…

IDEA常用快捷键

快捷键功能tab接受选择–选择的名称将覆盖带插入符号右侧的其它名称–而如果按shift或者enter&#xff0c;光标右边的内容会保留Ctrlshift空格智能匹配–查找当前上下文的方法和变量Ctrld对比文件–选中需要对比的文件shift滚动水平滚动Ctrlaltl格式化Ctrlk提交Ctrlaltz回滚类C…

Linux基础项目开发1:量产工具——UI系统(五)

前言&#xff1a; 前面我们已经把显示系统、输入系统、文字系统搭建好了&#xff0c;现在我们就要给它实现按钮操作了&#xff0c;也就是搭建UI系统&#xff0c;下面让我们一起实现UI系统的搭建吧 目录 一、按钮数据结构抽象 ui.h 二、按键编程 1.button.c 2.disp_manager…

YUM 问题解决步骤

YUM 问题解决步骤 当使用 yum 进行安装软件包或者更新时&#xff0c;如果遇到卡在加载插件阶段或其他相关问题&#xff0c;如下 [rootVM-12-2-centos ~]# sudo yum update Loaded plugins: fastestmirror, langpacks Repository epel is listed more than once in the config…

linux shell编程

Linux shell编程 一、常用功能1. 比较图片差异2. 截屏2.1 起X情况下&#xff08;X window起桌面&#xff09;2.2 没有起X或没有X系统环境下 3. 自动输入密码 一、常用功能 1. 比较图片差异 if compare -metric AE p1.png p2.png null: 2>&1 | grep -v "0$";…

查找算法及哈希表

1 二分查找 1.1 重要概念 拟解决的问题&#xff1a;判断某个区间是否包含某个元素&#xff0c;无法确定区间中包含重复元素的具体位置&#xff1b;使用条件&#xff1a;查找的区间必须符合单调性&#xff1b;本质&#xff1a;采用分治思想&#xff0c;将某个单调区间一分为二…

12.2_黑马Redis实战篇附近商铺用户签到UV统计

实战篇11 实战篇12 要先用test的方式把商铺的数据导入到idea当中&#xff0c;才可以进行查询噢。 代码&#xff1a; 实战篇13 thinking&#xff1a;插件mavenhelper&#xff1f; 方便处理pom文件。 实战篇15 实战篇16 thinking&#xff1a;XX.format(DateTimeFormatter.ofP…

【网络安全技术】实体认证技术Kerberos

一、什么是Kerberos Kerberos解决的是客户端与服务器通信场景中&#xff0c;确保客户端服务器双方的身份可信&#xff0c;并提供对称密钥的分发来加密传输。是一个应用层的协议。 二、一个简单的模型 1.看这个基础的模型&#xff0c;客户端要和服务器通信&#xff0c;他先将自…

《堆》的模拟实现

目录 前言&#xff1a; 模拟实现《堆》&#xff1a; 1.自定义数据类型 2.初始化“堆” 3.销毁“堆” 4.进“堆” 关于AdjustUp() 5.删除堆顶元素 关于AdjustDown() 6.判断“堆”是否为空 7.求“堆”中的数据个数 8.求“堆”顶元素 总结&#xff1a; 前言&#xf…

「LeetCode Hot 100 题」详解

前言 前言&#xff1a;LeetCode Hot 100 题详解 文章目录 前言1. 两数之和2. 字母异位词分组3. 最长连续序列4. 移动零 1. 两数之和 原题链接&#xff1a;两数之和 知识点&#xff1a;哈希表 题解 class Solution {public int[] twoSum(int[] nums, int target) {Map<Inte…

mysql原理--重新认识MySQL

1.MySQL请求处理 1.1.查询缓存 MySQL 服务器程序处理查询请求时&#xff0c;会把刚刚处理过的查询请求和结果缓存起来&#xff0c;如果下一次有一模一样的请求过来&#xff0c;直接从缓存中查找结果就好了&#xff0c;就不用再傻呵呵的去底层的表中查找了。这个查询缓存可以在不…

DOM 事件的传播机制

前端面试大全DOM 事件的传播机制 &#x1f31f;经典真题 &#x1f31f;事件与事件流 事件流 事件冒泡流 事件捕获流 标准 DOM 事件流 &#x1f31f;事件委托 &#x1f31f;真题解答 &#x1f31f;总结 &#x1f31f;经典真题 谈一谈事件委托以及冒泡原理 &#x1f3…

SmartSoftHelp8数据库连接字符串强优化,高并发配置

1.设置数据库是否异步连接 2.数据库连接是否复用 3.最大链接数 4.最小连接数 5.等待时间 6.生命周期 下载地址&#xff1a; 百度网盘 请输入提取码

24、蜂鸣器

蜂鸣器介绍 蜂鸣器是一种将电信号转换为声音信号的器件&#xff0c;常用来产生设备的按键音、报警音等提示信号 蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器 有源蜂鸣器&#xff1a;内部自带振荡源&#xff0c;将正负极接上直流电压即可持续发声&#xff0c;频率固定 无源蜂…

【linux】信号——信号保存+信号处理

信号保存信号处理 1.信号保存1.1信号其他相关概念1.2信号在内核中的表示 2.信号处理2.1信号的捕捉流程2.2sigset_t2.3信号集操作函数2.4实操2.5捕捉信号的方法 3.可重入函数4.volatile5.SIGCHLD信号 自我名言&#xff1a;只有努力&#xff0c;才能追逐梦想&#xff0c;只有努力…

Vue2中响应式的原理

Vue2中实现响应式的原理 vue2实现原理Vue2响应式存在的问题 vue2实现原理 使用Object.defineProperty()的get()与set()来实现响应式 <script>let p {}let person {name: "张三",sex:"男",hobby: ["吃饭","睡觉"]}Object.def…