学习Vue3的第五天

server/2025/1/16 2:31:58/

目录

API对比

shallowRef 与 shallowReactive

对比总结

使用场景

总结

readonly 与 shallowReadonly

对比总结

使用场景

总结

toRaw 与 markRaw

对比总结

使用场景

总结

customRef

应用场景

总结

示例:异步数据获取

Vue3新组件

Teleport

Suspense

全局API转移到应用对象

其他


API对比

shallowRef 与 shallowReactive

shallowRef

作用:创建一个响应式数据,但只对顶层属性进行响应式处理。

用法:

import { shallowRef } from 'vue';let myVar = shallowRef(initialValue);

特点:

  • 只跟踪引用值的变化,不关心值内部的属性变化。
  • 适用于只需要对顶层属性进行响应式处理的场景,特别是当嵌套对象较大或不需要响应式时。

shallowReactive

作用:创建一个浅层响应式对象,只会使对象的最顶层属性变成响应式的,对象内部的嵌套属性则不会变成响应式的。

用法:

import { shallowReactive } from 'vue';const myObj = shallowReactive({ ... });

特点:

  • 对象的顶层属性是响应式的,但嵌套对象的属性不是。
  • 适用于只需要对顶层属性进行响应式处理的场景,特别是当嵌套对象较大或不需要响应式时。

总结

通过使用 shallowRef() 和 shallowReactive(),可以绕开深度响应。浅层式 API 创建的状态只在其顶层是响应式的,对所有深层的对象不会做任何处理,避免了对每一个内部属性做响应式所带来的性能成本。这使得属性的访问变得更快,可提升性能。

对比总结

特性shallowRefshallowReactive
创建方式shallowRef(initialValue)shallowReactive(initialValue)
响应式处理只对顶层属性进行响应式处理只对顶层属性进行响应式处理
嵌套对象的响应式嵌套对象不是响应式的嵌套对象不是响应式的
访问方式通过 .value 访问直接访问
适用场景需要浅层响应式的简单对象需要浅层响应式的简单对象

使用场景

  • shallowRef:适用于只需要对顶层属性进行响应式处理的场景,特别是当嵌套对象较大或不需要响应式时。

  • shallowReactive:适用于只需要对顶层属性进行响应式处理的场景,特别是当嵌套对象较大或不需要响应式时。

总结

  • shallowRef 和 shallowReactive 都是浅层响应式工具,只对对象的顶层属性进行响应式处理。
  • 它们都不会递归地对嵌套对象进行响应式处理。
  • shallowRef 需要通过 .value 访问属性,而 shallowReactive 可以直接访问属性。

readonly 与 shallowReadonly

readonly

作用:用于创建一个对象的深只读副本。

用法:

import { readonly, reactive } from 'vue';const original = reactive({ ... });
const readOnlyCopy = readonly(original);

特点:

  • 对象的所有嵌套属性都将变为只读。
  • 任何尝试修改这个对象的操作都会被阻止(在开发模式下,还会在控制台中发出警告)。

应用场景:

  • 创建不可变的状态快照。
  • 保护全局状态或配置不被修改。

shallowReadonly

作用:与 readonly 类似,但只作用于对象的顶层属性。

用法:

import { shallowReadonly, reactive } from 'vue';const original = reactive({ ... });
const shallowReadOnlyCopy = shallowReadonly(original);

特点:

  • 只将对象的顶层属性设置为只读,对象内部的嵌套属性仍然是可变的。

  • 适用于只需保护对象顶层属性的场景。

对比总结

特性readonlyshallowReadonly
创建方式readonly(original)shallowReadonly(original)
只读处理递归地将所有属性(包括嵌套对象)变成只读只将顶层属性变成只读
嵌套对象的只读性嵌套对象的属性也是只读的嵌套对象的属性不是只读的
适用场景需要完全只读的对象只需要顶层属性只读的对象

使用场景

  • readonly:适用于需要完全只读的对象,确保对象及其所有嵌套属性都无法修改。
  • shallowReadonly:适用于只需要顶层属性只读的对象,允许修改嵌套对象的属性。

总结

  • readonly 和 shallowReadonly 都是用于创建只读对象的工具。
  • readonly 会递归地将对象的所有属性(包括嵌套对象)都变成只读的。
  • shallowReadonly 只会使对象的最顶层属性变成只读的,嵌套对象的属性不是只读的。

toRaw 与 markRaw

toRaw

作用:用于获取一个响应式对象的原始对象。toRaw 返回的对象不再是响应式的,不会触发视图更新。

官网描述:这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用,请谨慎使用。

何时使用? —— 在需要将响应式对象传递给非 Vue 的库或外部系统时,使用 toRaw 可以确保它们收到的是普通对象。

import { reactive, toRaw, markRaw, isReactive } from "vue";/* toRaw */
// 响应式对象
let person = reactive({ name: 'tony', age: 18 });
// 原始对象
let rawPerson = toRaw(person);console.log(isReactive(person)); // true
console.log(isReactive(rawPerson)); // false

markRaw

作用:标记一个对象,使其永远不会变成响应式的。

例如使用 mockjs 时,为了防止误把 mockjs 变为响应式对象,可以使用 markRaw 去标记 mockjs。

/* markRaw */
let citys = markRaw([{ id: 'asdda01', name: '北京' },{ id: 'asdda02', name: '上海' },{ id: 'asdda03', name: '天津' },{ id: 'asdda04', name: '重庆' }
]);// 根据原始对象 citys 去创建响应式对象 citys2 —— 创建失败,因为 citys 被 markRaw 标记了
let citys2 = reactive(citys);console.log(isReactive(citys)); // false
console.log(isReactive(citys2)); // false

对比总结

特性toRawmarkRaw
作用获取响应式对象的原始对象标记对象,使其永远不会变成响应式对象
返回值非响应式的原始对象标记后的对象
响应式处理返回的对象不会触发响应式更新标记的对象永远不会变成响应式对象
适用场景需要访问原始对象的场景需要确保对象永远不会变成响应式对象的场景

使用场景

  • toRaw:适用于需要访问原始对象的场景,避免不必要的响应式处理。
  • markRaw:适用于需要确保对象永远不会变成响应式对象的场景,例如某些第三方库的对象或不需要响应式的配置对象。

总结

  • toRaw 用于获取响应式对象的原始对象,返回一个非响应式的原始对象。
  • markRaw 用于标记一个对象,使其永远不会被转换为响应式对象。

customRef

在 Vue 3 中,customRef 是一个用于创建自定义 ref 的工具。它允许我们完全控制 ref 的依赖追踪和更新触发机制。通过 customRef,可以实现更复杂的响应式逻辑,例如防抖、节流、异步数据获取等。

customRef 的基本用法

customRef 接受一个工厂函数,该函数返回一个包含 get 和 set 方法的对象。get 方法用于获取值,set 方法用于设置值。

import { customRef } from 'vue';function useDebouncedRef(value, delay = 200) {let timeout;return customRef((track, trigger) => {return {get() {track(); // 追踪依赖return value;},set(newValue) {clearTimeout(timeout);timeout = setTimeout(() => {value = newValue;trigger(); // 触发更新}, delay);}};});
}const debouncedRef = useDebouncedRef('initial value', 500);debouncedRef.value = 'new value'; // 500ms 后才会更新

解释

  • customRef 接受一个工厂函数,该函数返回一个包含 get 和 set 方法的对象。
  • get 方法用于获取值,并调用 track 方法来追踪依赖。
  • set 方法用于设置值,并调用 trigger 方法来触发更新。
  • 在上面的示例中,useDebouncedRef 创建了一个防抖的 ref,只有在指定延迟后才会更新值。

应用场景

  • 防抖和节流:通过 customRef 可以实现防抖和节流的功能,避免频繁触发更新。
  • 异步数据获取:可以在 set 方法中进行异步数据获取,并在数据获取完成后更新值。
  • 自定义依赖追踪:可以根据需要自定义依赖追踪逻辑,实现更复杂的响应式行为。

总结

customRef 是一个强大的工具,允许我们完全控制 ref 的依赖追踪和更新触发机制。通过 customRef,我们可以实现更复杂的响应式逻辑,例如防抖、节流、异步数据获取等。

示例:异步数据获取

import { customRef } from 'vue';function useAsyncRef(initialValue, asyncFunc) {let value = initialValue;let loading = false;return customRef((track, trigger) => {return {get() {track(); // 追踪依赖return value;},set(newValue) {if (typeof newValue === 'function') {loading = true;asyncFunc(newValue).then(result => {value = result;loading = false;trigger(); // 触发更新});} else {value = newValue;trigger(); // 触发更新}}};});
}const asyncRef = useAsyncRef('initial value', async (func) => {return await func();
});asyncRef.value = async () => {return 'new value from async function';
};

解释

  • useAsyncRef 创建了一个可以处理异步数据获取的 ref。
  • 当 set 方法接收到一个函数时,会调用 asyncFunc 进行异步数据获取,并在数据获取完成后更新值。
  • 在 get 方法中,调用 track 方法来追踪依赖。
  • 在 set 方法中,调用 trigger 方法来触发更新。

Vue3新组件

Teleport

Teleport 是 Vue 3 中引入的一个内置组件,用于将组件的模板部分渲染到 DOM 中的指定位置,而不是其父组件的 DOM 结构中。这在处理模态框、弹出层、全局提示等场景时非常有用。

基本用法

Teleport 组件有两个主要属性:

  • to:指定目标元素的选择器或 DOM 元素,表示要将内容渲染到哪个位置。
  • disabled:布尔值,表示是否禁用 Teleport 功能,如果为 true,内容将渲染在当前组件的位置。
<template><div><button @click="showModal = true">打开模态框</button><Teleport to="body"><div v-if="showModal" class="modal"><p>这是一个模态框</p><button @click="showModal = false">关闭</button></div></Teleport></div>
</template><script setup>
import { ref } from 'vue';const showModal = ref(false);
</script><style scoped>
.modal {position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);background-color: white;padding: 20px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
</style>

应用场景

  • 模态框:将模态框的内容渲染到 body 元素中,避免被父组件的样式或布局影响。
  • 全局提示:将全局提示信息渲染到页面的固定位置,如页面顶部或底部。
  • 弹出层:将弹出层的内容渲染到页面的指定位置,避免被父组件的样式或布局影响。

动态控制 Teleport

我们可以通过 disabled 属性动态控制 Teleport 的行为。例如,根据某些条件决定是否将内容渲染到指定位置。

<template><div><button @click="showModal = true">打开模态框</button><Teleport :to="teleportTarget" :disabled="isDisabled"><div v-if="showModal" class="modal"><p>这是一个模态框</p><button @click="showModal = false">关闭</button></div></Teleport></div>
</template><script setup>
import { ref } from 'vue';const showModal = ref(false);
const teleportTarget = ref('body');
const isDisabled = ref(false);// 动态控制 Teleport 的行为
const toggleTeleport = () => {isDisabled.value = !isDisabled.value;
};
</script><style scoped>
.modal {position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);background-color: white;padding: 20px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
</style>

总结

Teleport 是一个非常有用的组件,允许我们将组件的内容渲染到 DOM 中的指定位置,而不是其父组件的 DOM 结构中。这在处理模态框、弹出层、全局提示等场景时非常有用。通过 to 和 disabled 属性,我们可以灵活控制 Teleport 的行为。

Suspense

Suspense 是 Vue 3 中引入的一个内置组件,用于在异步组件加载时渲染一些额外内容,从而提升用户体验。Suspense 允许我们在等待异步组件加载完成时显示一个占位符或加载状态,而不是直接显示空白或未加载的内容。

基本用法

Suspense 组件有两个插槽:

  • default:用于放置异步组件或异步操作的内容。
  • fallback:用于放置在异步组件加载完成前显示的占位符内容。
<template><div><Suspense><template #default><AsyncComponent /></template><template #fallback><div>Loading...</div></template></Suspense></div>
</template><script setup>
import { defineAsyncComponent } from 'vue';// 异步引入组件
const AsyncComponent = defineAsyncComponent(() =>import('./AsyncComponent.vue')
);
</script>

解释

  • Suspense 包裹了异步组件 AsyncComponent。
  • default 插槽放置异步组件的内容。
  • fallback 插槽放置在异步组件加载完成前显示的占位符内容。
  • defineAsyncComponent 用于异步引入组件。

应用场景

  • 异步组件加载:在异步组件加载完成前显示加载状态或占位符内容。
  • 数据获取:在数据获取完成前显示加载状态或占位符内容。

动态控制 Suspense

我们可以通过 Suspense 的 default 和 fallback 插槽动态控制异步组件的加载状态。例如,在数据获取完成前显示加载状态,数据获取完成后显示实际内容。

<template><div><Suspense><template #default><div v-if="data"><h1>{{ data.title }}</h1><p>{{ data.description }}</p></div></template><template #fallback><div>Loading data...</div></template></Suspense></div>
</template><script setup>
import { ref } from 'vue';const data = ref(null);// 模拟异步数据获取
const fetchData = async () => {// 模拟异步请求await new Promise(resolve => setTimeout(resolve, 2000));data.value = {title: 'Async Data',description: 'This is some async data.'};
};fetchData();
</script>

解释

  • Suspense 包裹了异步数据获取的内容。
  • default 插槽放置数据获取完成后的内容。
  • fallback 插槽放置在数据获取完成前显示的加载状态。
  • fetchData 方法模拟异步数据获取,并在数据获取完成后更新 data 的值。

总结

Suspense 是一个非常有用的组件,允许我们在异步组件或异步操作加载完成前显示占位符内容,从而提升用户体验。通过 default 和 fallback 插槽,我们可以灵活控制异步加载状态的显示。

全局API转移到应用对象

在 Vue 3 中,全局 API 被转移到了应用对象(app)上。这意味着我们可以通过应用实例来访问和配置 Vue 的各种功能,而不是直接调用全局 API。这种设计使得每个应用实例更加独立,避免了全局状态的污染。

app.component:用于注册或获取全局组件。

import { createApp } from 'vue';
import App from './App.vue';
import MyComponent from './components/MyComponent.vue';const app = createApp(App);// 注册全局组件
app.component('MyComponent', MyComponent);// 获取全局组件
const MyComponentInstance = app.component('MyComponent');app.mount('#app');

app.config:用于配置应用的全局配置,如错误处理器、警告处理器等。

import { createApp } from 'vue';
import App from './App.vue';const app = createApp(App);// 配置全局错误处理器
app.config.errorHandler = (err, vm, info) => {console.error('Global error handler:', err, vm, info);
};// 配置全局警告处理器
app.config.warnHandler = (msg, vm, trace) => {console.warn('Global warning handler:', msg, vm, trace);
};app.mount('#app');

app.directive:用于注册或获取全局自定义指令。

import { createApp } from 'vue';
import App from './App.vue';const app = createApp(App);// 注册全局自定义指令
app.directive('focus', {mounted(el) {el.focus();}
});// 获取全局自定义指令
const focusDirective = app.directive('focus');app.mount('#app');

app.mount:用于将应用实例挂载到指定的 DOM 元素上。

import { createApp } from 'vue';
import App from './App.vue';const app = createApp(App);// 挂载应用实例到 #app 元素
app.mount('#app');

app.unmount:用于卸载应用实例。

import { createApp } from 'vue';
import App from './App.vue';const app = createApp(App);// 挂载应用实例
const vm = app.mount('#app');// 卸载应用实例
app.unmount();

app.use:用于安装插件。

import { createApp } from 'vue';
import App from './App.vue';
import MyPlugin from './plugins/MyPlugin';const app = createApp(App);// 安装插件
app.use(MyPlugin);app.mount('#app');

其他

  • 过渡类名 `v-enter` 修改为 `v-enter-from`、过渡类名 `v-leave` 修改为 `v-leave-from`。
  • `keyCode` 作为 `v-on` 修饰符的支持。
  • `v-model` 指令在组件上的使用已经被重新设计,替换掉了 `v-bind.sync。`
  • `v-if` 和 `v-for` 在同一个元素身上使用时的优先级发生了变化。
  • 移除了`$on`、`$off` 和 `$once` 实例方法。
  • 移除了过滤器 `filter`。
  • 移除了`$children` 实例 `propert`。
  •   ......

http://www.ppmy.cn/server/116434.html

相关文章

AIPaperGPT写论文靠谱吗?

AIPaperGPT&#xff0c;论文写作神器~ https://www.aipapergpt.com/ 在信息爆炸的今天&#xff0c;学术写作的挑战日益增加&#xff0c;而AIPaperGPT作为一款旨在提升写作效率的工具&#xff0c;其可靠性自然成为了用户关注的焦点。本文将从多个维度对AIPaperGPT进行全面评估&…

AI prompt(提示词)

# 好用的用于学习的AI提示词 ## 费曼学习法 请使用费曼学习法&#xff0c;用简单的语言解释&#xff08;量子力学&#xff09;是什么&#xff0c;并提供一个简单的例子来说明它如何应用 ## 帕累托法则&#xff08;80/20原则&#xff09; 将&#xff08;量子力学&#xff09;最…

网络运维管理:确保企业网络系统稳定运行之道

在当今数字化时代&#xff0c;企业网络系统的稳定运行和高效管理是企业业务持续发展和创新的关键。网络运维管理的核心目标正是确保网络设备和服务的高可用性、优化网络性能、保护网络安全、快速解决网络故障以及有效管理网络配置。本文将深入探讨网络运维管理系统的关键组件、…

接口测试原理及Postman详解

接口测试定义 接口是前后端沟通的桥梁&#xff0c;是数据传输的通道&#xff0c;包括外部接口、内部接口。内部接口又包括:上层服 务与下层服务接口&#xff0c;同级接口 生活中常见接口&#xff1a;电脑上的键盘、USB接口&#xff0c;电梯按钮&#xff0c;KFC下单 接口测试…

计算机毕业设计选题推荐-农家乐综合服务系统-乡村游乐购系统-田园休闲生活系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

Qt 界面设计布局编辑

第1 部分 Qt 基础 (2) 双击dialog.ui 文件&#xff0c;打开Qt 的设计器&#xff0c;中间的空白视窗为一个Parent Widget, 需要建立一些Child Widget 。在左边的工具箱中找到所需要的Widget: 拖曳出一个Label、一个Line Edit&#xff08;用于输入文字&#xff09;、一个Horizo…

Redis进阶(六):缓存

1.缓存 速度快的设备可以作为速度慢的设备的缓存 缓存能够有意义&#xff1a;二八定律&#xff0c;20%的数据可以应对80%的请求 通常使用redis作为数据库的缓存&#xff08;mysql&#xff09; 数据库是非常重要的组件&#xff0c;mysql速度比较慢 因为mysql等数据库&#x…

【C++多线程编程】 线程安全与对象生命周期管理

目录 类的线程安全 实现线程安全 构造函数在多线程中的安全性 析构函数多线程环境的安全 智能指针实现多线程安全 shared_ptr 非完全线程安全 shared_ptr可能导致对象生命周期延长 const引用可以减少传递shared_ptr开销 shared_ptr 智能指针块模块的优点 析构所在线程…