【前端学习笔记】Vue3
- 游戏开发
- 2025-08-26 22:00:02

一、Vue3新变化
Vue 3 相比于 Vue 2 做了很多改进,不仅提升了性能,还引入了一些新的功能,使得开发更加高效、灵活。
1. 性能提升Vue 3 在性能方面做了大量的优化,尤其是在渲染和更新方面,主要通过以下几个方式提升:
更快的虚拟 DOM:Vue 3 的虚拟 DOM 实现进行了优化,减少了不必要的渲染和更新,提高了性能。Tree Shaking:Vue 3 在构建时支持更好的 Tree Shaking(摇树优化),即只打包你使用的代码,未使用的代码不会打包进最终文件,从而减小了体积。更小的包体积:由于 Vue 3 引入了许多新特性并优化了内部代码,使得其整体包体积比 Vue 2 更小。响应式系统优化:Vue 3 使用了 Proxy 取代了 Vue 2 的 Object.defineProperty 作为响应式系统的核心,使得 Vue 3 的响应式系统更加高效,并且支持更多的功能。 2. Composition API(组合式 API)这是 Vue 3 最重要的特性之一。组合式 API 为 Vue 提供了更加灵活和清晰的代码结构。它引入了一些新的 API,如 ref、reactive、computed、watch 等,可以让开发者在组件中更加方便地组织和复用逻辑。
例如:
import { ref, reactive, onMounted } from 'vue'; export default { setup() { const count = ref(0); // 响应式数据 const state = reactive({ name: 'Vue 3' }); onMounted(() => { console.log('组件已挂载'); }); return { count, state }; } }; ref 用来创建基础数据类型的响应式数据;reactive 用来创建对象或数组的响应式数据;onMounted 等生命周期钩子函数则让你在组合式 API 中使用组件生命周期。 组合式 API 的优势: 逻辑复用:相比于 Vue 2 的选项式 API,组合式 API 使得在组件中复用逻辑变得更加方便。你可以将多个逻辑片段封装成函数,进行跨组件的共享。更好的 TypeScript 支持:组合式 API 可以更自然地和 TypeScript 配合使用,类型推导更加准确。 3. 新生命周期钩子在 Vue 3 中,组合式 API 的引入使得生命周期钩子的命名有所变化。Vue 2 的生命周期钩子是如 beforeCreate、created、mounted 等,它们是基于选项式 API 的。Vue 3 修改了一些生命周期钩子的名称,去除了 Vue 2 中的 beforeDestroy 和 destroyed,用 beforeUnmount 和 unmounted 代替。类似地,created 被替换成了 setup,以适应 Composition API。 Vue 3 引入了生命周期钩子的组合式 API 版本,它们可以在 setup 函数中使用,如 onMounted、onUpdated、onUnmounted 等。例如:
beforeMount → onBeforeMountmounted → onMountedbeforeUpdate → onBeforeUpdateupdated → onUpdated这些新钩子函数是用于在 setup 函数中使用的。
4. Teleport(传送门)Vue 3 引入了 Teleport 组件,允许你将 DOM 元素从一个地方传送到另一个地方。例如,你可以将模态框、通知等组件的内容从当前组件的 DOM 树中移到根节点或 body 中,而不必改变组件的层级结构。
<template> <Teleport to="body"> <div class="modal">This is a modal!</div> </Teleport> </template> 5. Fragments(片段)Vue 3 支持 Fragments,即一个组件可以返回多个根节点元素,而不再需要一个单独的根元素来包裹组件。这对于优化组件结构、减少无意义的 DOM 元素非常有用。
<template> <div>Part 1</div> <div>Part 2</div> </template>在 Vue 2 中,每个组件必须有且只有一个根节点,而 Vue 3 允许组件返回多个元素。
6. Suspense(延迟加载)Vue 3 引入了 Suspense 组件,用于处理异步组件的加载。它允许你在等待某个组件加载时展示一个加载指示器。
<template> <Suspense> <template #default> <AsyncComponent /> </template> <template #fallback> <div>Loading...</div> </template> </Suspense> </template> 7. 自定义事件(v-model)语法改进在 Vue 3 中,组件可以同时接受多个 v-model,而不仅仅是 value。这意味着你可以为多个 prop 和事件使用不同的 v-model,而不需要再依赖默认的 value 和 input 事件。这对于那些需要多个双向绑定的组件非常有用。
1. 支持多个 v-model在 Vue 3 中,组件可以同时接受多个 v-model,而不仅仅是 value。这意味着你可以为多个 prop 和事件使用不同的 v-model,而不需要再依赖默认的 value 和 input 事件。这对于那些需要多个双向绑定的组件非常有用。
例如,假设有一个组件需要接收两个数据:name 和 age,你可以为它们分别使用不同的 v-model:
<template> <MyForm v-model:name="name" v-model:age="age" /> </template> <script> export default { data() { return { name: 'John', age: 30, }; }, }; </script> <!-- MyForm.vue --> <template> <input :value="name" @input="$emit('update:name', $event)" /> <input :value="age" @input="$emit('update:age', $event)" /> </template> <script> export default { props: { name: String, age: Number, }, }; </script>在这个例子中,name 和 age 分别使用了两个 v-model,并且使用了 update:name 和 update:age 事件来进行更新。
2. 自定义 prop 和事件名Vue 3 引入了自定义 v-model 的能力,允许开发者指定自己的 prop 名和事件名,而不必固定为 value 和 input。这使得自定义组件的设计更加灵活。
在 Vue 2 中,v-model 默认绑定的是组件的 value prop,并监听 input 事件,但在 Vue 3 中,你可以通过自定义 prop 和事件名来定义不同的行为。
例如:
<template> <MyInput v-model="text" /> </template> <script> export default { components: { MyInput: { props: { modelValue: String, // 注意这里使用 modelValue 作为 prop }, emits: ['update:modelValue'], // 自定义事件名 template: '<input :value="modelValue" @input="$emit(\'update:modelValue\', $event)" />', }, }, data() { return { text: 'Hello Vue 3!', }; }, }; </script>在这个例子中,MyInput 组件使用了 modelValue 作为 prop,update:modelValue 作为事件名。这让你可以灵活地命名 prop 和事件,而不仅仅局限于 value 和 input。
3. 简化的语法Vue 3 还简化了 v-model 的使用方式。你可以使用类似于原生 HTML 的简洁语法,不需要额外指定事件或 prop。
例如,在 Vue 3 中,你可以直接这样写:
<MyInput v-model="message" />这里 Vue 会自动将 v-model 绑定到 modelValue,并且自动处理 update:modelValue 事件,避免了冗余的配置。
4. 支持修改事件名在 Vue 3 中,如果你需要使用不同的事件名称来代替默认的 update:modelValue,你可以通过 model 选项来进行配置。这在需要更改事件名称的情况下非常有用。
例如,假设你想将事件名改为 changed,你可以在组件的 model 选项中进行配置:
<template> <MyInput v-model="text" /> </template> <script> export default { components: { MyInput: { props: { modelValue: String, }, emits: ['changed'], model: { prop: 'modelValue', event: 'changed', }, template: '<input :value="modelValue" @input="$emit(\'changed\', $event)" />', }, }, data() { return { text: 'Hello Vue 3!', }; }, }; </script>在这个例子中,modelValue 仍然是传入的 prop,但事件名称变成了 changed,你可以灵活控制事件名。
8. Custom Renderer(自定义渲染器)Vue 3 增强了对自定义渲染器的支持,这意味着你可以用 Vue 来渲染非 DOM 的目标,比如通过 WebGL、Canvas、SVG 或其他渲染系统进行渲染。允许开发者为 Vue 的虚拟 DOM 创建自定义的渲染过程。通过自定义渲染器,开发者可以将 Vue 组件的渲染输出到任何类型的目标(比如原生 DOM、Canvas、WebGL 或者其他平台)上。
createRenderer 是 Vue 3 中的核心 API,用于创建一个自定义的渲染器。它允许你提供自定义的节点操作函数,来替代默认的 DOM 操作。
import { createRenderer } from 'vue'; // 定义一个自定义渲染器 const renderer = createRenderer({ createElement(type) { // 自定义创建元素的方法 return new MyCustomElement(type); // 创建自定义元素 }, insert(child, parent) { // 自定义插入元素的方法 parent.appendChild(child); }, patchProp(el, key, prevValue, nextValue) { // 自定义属性更新的方法 el.setAttribute(key, nextValue); }, // 还可以定义更多的渲染逻辑 }); // 使用自定义渲染器来渲染 Vue 组件 const app = createApp(MyComponent); renderer.render(app, document.getElementById('root')); // 这里的 root 可以是其他非 DOM 的目标 二、使用 1.选项式APIOptions API:Vue2使用的API风格,它通过在组件中定义不同的 选项(options)来声明组件的行为,包括数据、方法、生命周期钩子等。
选项式 API 的核心是将一个 Vue 组件的功能分为几个独立的“选项”,这些选项分别代表了组件的不同部分,比如 data、methods、computed、watch 等。
一个典型的 Vue 组件使用选项式 API 的示例如下:
<template> <div> <p>{{ message }}</p> <button @click="increment">Increment</button> </div> </template> <script> export default { // 1. data 选项:用于声明组件的响应式数据 data() { return { message: 'Hello, Vue 2!', count: 0, }; }, // 2. methods 选项:声明组件中的方法 methods: { increment() { this.count++; }, }, // 3. computed 选项:声明计算属性 computed: { doubledCount() { return this.count * 2; }, }, // 4. 生命周期钩子:Vue 提供的一些生命周期回调 mounted() { console.log('组件已挂载'); }, watch: { // 5. watch 选项:观察某些数据变化并作出反应 count(newVal, oldVal) { console.log(`count 改变了:${oldVal} -> ${newVal}`); }, }, }; </script>选项式 API 的几个关键部分
data:声明组件的响应式数据,返回一个对象,包含组件的状态和数据。
methods:定义组件中的方法,这些方法可以在模板中调用,也可以在生命周期钩子中使用。
computed:计算属性,它是根据数据计算得出的值,具有缓存功能。当依赖的数据发生变化时,计算属性会自动更新。
watch:观察属性的变化,可以监听组件数据的变化,并在数据变化时执行某些操作。与计算属性不同,watch 用于处理异步或开销较大的操作。
生命周期钩子:Vue 提供了多个生命周期钩子来让开发者在组件的不同生命周期阶段执行代码。常见的钩子包括 mounted、created、beforeDestroy 等。
props:定义组件的外部输入(即父组件传递给子组件的数据)。通过 props,你可以在子组件中访问父组件的数据。
emits(Vue 3 引入):用于声明组件能够触发的自定义事件,通常用于子组件向父组件传递数据。
优点:
易于理解和使用:选项式 API 非常直观,结构清晰。每个选项都有固定的作用,使得开发者能够轻松理解和使用。适合小型组件:对于简单的组件,选项式 API 非常合适,因为它把所有的逻辑组织在不同的选项中,使得代码易于理解和维护。结构化的代码:各个部分(如 data、methods、computed 等)都有清晰的分隔,有助于代码的组织。缺点:
逻辑复用困难:选项式 API 组织的逻辑比较散乱。如果多个组件有类似的逻辑,需要通过 mixin 或者其他方式来复用逻辑,但这也可能导致代码耦合。大型组件难以维护:随着组件变得越来越复杂,data、methods、computed 等可能会变得非常庞大,使得代码难以维护和扩展。虽然 Vue 3 引入了 Composition API,但 Vue 3 依然支持选项式 API,开发者可以根据项目的需要选择使用哪种方式。这两者并不是互斥的,开发者可以在同一个项目中混合使用它们。
2.组合式APIComposition API:它通过将组件逻辑拆分成函数(而不是像选项式 API 那样按照 data、methods、computed 等进行组织)来提升代码的灵活性、复用性和可维护性。组合式 API 的核心思想是将相关的业务逻辑封装成函数,并在组件中按需引入和使用。这与选项式 API 中将不同功能(如数据、方法、计算属性等)分开组织的方式不同。通过组合式 API,你可以更加自由地管理和复用组件的逻辑。
Vue 3 引入的 组合式 API(Composition API)是一个全新的方式来编写 Vue 组件,它通过将组件逻辑拆分成函数(而不是像选项式 API 那样按照 data、methods、computed 等进行组织)来提升代码的灵活性、复用性和可维护性。与选项式 API 相比,组合式 API 提供了一种更加灵活、模块化的方式来组织代码,特别适用于复杂组件的开发。
组合式 API 的常用功能
setup 函数
组合式 API 的入口函数是 setup。它是 Vue 3 组件中必不可少的部分,所有的响应式数据、计算属性、方法、生命周期钩子等都可以在 setup 中定义。
setup 函数在组件创建之前执行,返回的对象(或函数)会暴露给模板,作为组件的响应式数据和方法。 import { ref, reactive } from 'vue'; export default { setup() { // 响应式数据 const count = ref(0); // ref 用于基本类型数据 const state = reactive({ name: 'Vue 3' }); // reactive 用于对象或数组 // 计算属性 const doubledCount = computed(() => count.value * 2); // 方法 const increment = () => { count.value++; }; // 返回值暴露给模板 return { count, doubledCount, increment, state }; } }; setup 函数中的返回值会自动暴露给组件的模板,模板中可以直接访问返回的值。setup 中的代码是在 Vue 组件的实例化之前运行的,所以你无法在 setup 中访问 this。响应式数据(ref 和 reactive)
ref 用于创建基本数据类型的响应式数据。ref 返回一个包含 .value 属性的对象,只有通过 .value 来访问和修改它的值。
const count = ref(0); // count 是一个响应式数据 count.value++; // 修改时需要使用 .valuereactive 用于创建对象或数组的响应式数据,它会使对象内部的所有属性变成响应式。
const state = reactive({ name: 'Vue 3', age: 3 }); state.name = 'Vue 4'; // state 里的属性是响应式的ref 和 reactive 是 Vue 3 响应式系统的基础。reactive 更适合用于对象、数组等复杂数据类型,而 ref 更适用于基本数据类型(如 number、string、boolean)。
computed 和 watch
computed 用于定义计算属性,它会根据依赖的响应式数据自动更新。
const count = ref(0); const doubledCount = computed(() => count.value * 2);watch 用于监听响应式数据的变化,适用于需要执行副作用操作(如异步操作或外部 API 调用)的场景。
watch(count, (newVal, oldVal) => { console.log(`count changed from ${oldVal} to ${newVal}`); });watch 可以监听单个数据源,也可以监听对象的多个属性。
生命周期钩子
在组合式 API 中,生命周期钩子通过类似于 onMounted、onCreated 等函数来使用。这些函数可以在 setup 中导入使用。
import { onMounted, onUpdated, onUnmounted } from 'vue'; export default { setup() { onMounted(() => { console.log('组件已挂载'); }); onUpdated(() => { console.log('组件更新'); }); onUnmounted(() => { console.log('组件已销毁'); }); } };这些生命周期钩子函数在 setup 中使用,可以更加灵活地组织代码。
provide 和 inject
Vue 3 中的 provide 和 inject 机制可以帮助你在组件树的不同层级之间共享数据。provide 在父组件中提供数据,而 inject 让子组件获取这些数据。
provide:父组件中提供数据。
import { provide } from 'vue'; export default { setup() { const sharedData = ref('Hello from parent'); provide('sharedData', sharedData); } };inject:子组件中获取父组件提供的数据。
import { inject } from 'vue'; export default { setup() { const sharedData = inject('sharedData'); console.log(sharedData); // 'Hello from parent' } };优势
逻辑复用:
组合式 API 使得组件中的逻辑可以更加灵活地被复用。你可以将相关的逻辑封装成函数,然后在多个组件中引入,避免了选项式 API 中的代码耦合问题。更好的类型推导:
组合式 API 与 TypeScript 更加兼容,TypeScript 可以更好地推导类型。你可以在 setup 函数中显式地声明变量的类型,避免一些隐式类型问题。更好的组织和维护:
组件中的逻辑和状态可以按功能拆分,避免了选项式 API 中不同功能的混杂,使得代码更加易于组织、理解和维护。更清晰的上下文管理:
由于 setup 函数是 Vue 组件的入口,你可以清晰地定义组件的状态和行为,而不会受到其他选项(如 data、methods)的干扰。缺点
学习曲线较陡:
组合式 API 在刚接触时可能需要一定的学习成本,尤其是对于习惯了选项式 API 的开发者来说,初期的上手可能稍微有些困难。代码结构可能不清晰:
对于小型组件来说,选项式 API 的结构非常清晰,而组合式 API 可能会将组件的不同功能分散到多个地方,导致代码难以追踪和理解。模板和 JavaScript 逻辑的分离较弱:
在组合式 API 中,组件的 JavaScript 逻辑通过 setup 函数暴露给模板,可能导致一些模板和逻辑的边界变得模糊,特别是在大组件中,可能会导致组件难以维护。适用场景:
复杂组件:当组件的逻辑越来越复杂时,组合式 API 可以帮助你将逻辑按功能进行拆分,避免代码冗长和难以管理。逻辑复用:如果你需要在多个组件中复用相同的逻辑,组合式 API 提供了更好的机制,可以通过将逻辑封装成函数来复用。TypeScript 项目:组合式 API 与 TypeScript 的兼容性非常好,能够提供更好的类型推导和静态检查,适合类型安全要求较高的项目。 3.响应式APIVue 3 中的响应式系统引入了 reactive 和 ref:
reactive 用于将对象变为响应式。ref 用于将基本数据类型(如字符串、数字、布尔值等)变为响应式。在 Vue 2 中,响应式对象是通过 Object.defineProperty 实现的,而 Vue 3 使用 Proxy 提供了更高效、更灵活的响应式处理。
当你将一个响应式对象的属性赋值或解构到一个本地变量时,访问或赋值该变量是非响应式的,因为它将不再触发源对象上的 get / set 代理。注意这种“断开”只影响变量绑定——如果变量指向一个对象之类的非原始值,那么对该对象的修改仍然是响应式的。从 reactive() 返回的代理尽管行为上表现得像原始对象,但我们通过使用 === 运算符还是能够比较出它们的不同。
ref: ref 返回的是一个包含 value 属性的对象,你需要通过 .value 来访问或修改它的值。在模板中,Vue 会自动解包 ref,所以你不需要写 .value。ref 内部是通过 reactive 来实现的。当你调用 ref 时,Vue 会创建一个包含 value 属性的对象,并将这个对象传递给 reactive,使其变成响应式的。
reactive: reactive 用于创建一个响应式的对象或数组。与 ref 不同,reactive 直接作用于对象或数组,而不需要 .value 来访问或修改。reactive 使用了 Proxy 来实现响应式。Proxy 可以拦截对象的读取、赋值等操作,从而在数据变化时触发视图更新。
4.服务端渲染SSR与客户端的单页应用 (SPA) 相比,SSR 的优势主要在于:
更快的首屏加载:这一点在慢网速或者运行缓慢的设备上尤为重要。服务端渲染的 HTML 无需等到所有的 JavaScript 都下载并执行完成之后才显示,所以你的用户将会更快地看到完整渲染的页面。除此之外,数据获取过程在首次访问时在服务端完成,相比于从客户端获取,可能有更快的数据库连接。这通常可以带来更高的核心 Web 指标评分、更好的用户体验,而对于那些“首屏加载速度与转化率直接相关”的应用来说,这点可能至关重要。统一的心智模型:你可以使用相同的语言以及相同的声明式、面向组件的心智模型来开发整个应用,而不需要在后端模板系统和前端框架之间来回切换。更好的 SEO:搜索引擎爬虫可以直接看到完全渲染的页面。SSR (Server-Side Rendering) 和 SPA (Single-Page Application) 是两种不同的网页渲染方式。它们的根本区别在于页面内容是在哪一端生成的:是在服务器端还是客户端。下面详细解释这两者的概念、优缺点以及它们之间的区别。
什么是 SSR (Server-Side Rendering)?
SSR(服务器端渲染)是指将应用程序的 HTML 内容在服务器端生成后发送到客户端浏览器。也就是说,当用户请求一个页面时,服务器会根据当前路由渲染完整的 HTML 页面并返回给浏览器,浏览器加载和渲染这个 HTML 页面,然后在客户端进行后续的交互。
SSR 的工作流程:
用户请求某个页面。服务器接收到请求后,执行应用程序,生成完整的 HTML 页面。服务器将生成的 HTML 页面返回给客户端。客户端加载 HTML 页面,用户可以看到页面内容。客户端接管后,Vue、React 或其他前端框架初始化,后续交互由客户端处理。SSR 的特点:
页面内容在服务器端渲染,所以首屏加载速度较快,能更快展示页面内容。适合 SEO,因为搜索引擎能够直接抓取到渲染好的 HTML 内容。初次加载页面需要等待服务器的响应,可能导致较高的服务器负担,尤其是流量大时。在客户端接管后,应用就变成了常规的 SPA 进行交互。什么是 SPA (Single-Page Application)?
SPA(单页面应用)是一种通过客户端的 JavaScript 来动态渲染页面的应用。在这种模式下,用户加载页面后,所有的交互、路由跳转、内容更新都通过 JavaScript 来实现,而无需重新加载整个页面。常见的 SPA 框架有 React、Vue、Angular 等。
SPA 的工作流程:
用户请求某个页面,浏览器加载一次 HTML 页面,通常包含基本的框架、CSS、JavaScript 等资源。一旦页面加载完成,JavaScript 会控制后续的页面渲染,所有的页面内容都通过前端路由来加载和渲染,而不需要刷新整个页面。用户点击链接或触发操作时,前端路由会根据请求的 URL 来加载相应的组件并更新页面。SPA 的特点:
首次加载页面时,整个应用会加载所有资源(HTML、JS、CSS 等),因此首次加载时间可能较长。一旦页面加载完成,后续的页面交互不会引发完整的页面刷新,体验更为流畅。适合动态交互丰富的应用。SEO 对比 SSR 要弱,搜索引擎爬虫无法直接抓取 SPA 页面中动态加载的内容,通常需要额外配置如 SSR 或 Pre-rendering 来解决 SEO 问题。 特性SSR (服务器端渲染)SPA (单页面应用)渲染位置页面内容在服务器端渲染后发送到客户端页面内容由客户端通过 JavaScript 动态渲染首屏加载速度首屏加载较快,直接获取完整的 HTML 页面首次加载时较慢,需加载 JavaScript、CSS 和资源交互体验首屏加载后,交互由客户端接管,通常体验流畅不需要重新加载页面,用户交互体验更加流畅SEO 优化由于页面内容在服务器端渲染,搜索引擎可以直接抓取内容由于页面是通过 JavaScript 渲染的,SEO 需要额外配置服务器负担服务器需要每次请求都渲染页面,负担较重服务器仅需提供静态资源,前端通过路由渲染内容,负担较轻客户端路由客户端路由仅在页面加载后激活,通常会有客户端 JavaScript 初始化客户端路由在页面加载后就开始工作,页面内容动态更新复杂度相对复杂,涉及服务器渲染、数据获取、页面更新等多个方面相对简单,前端控制整个应用,逻辑和状态在客户端处理SSR:
SEO 优化:由于页面是服务器端渲染的,搜索引擎能够直接抓取到完整的 HTML 内容,因此对 SEO 有较大帮助。更好的首屏加载体验:由于首屏已经是渲染好的 HTML,用户可以较快地看到内容,特别是对内容密集型应用(如博客、新闻网站等)非常有帮助。适合内容为主的应用:如博客、新闻、广告等需要频繁更新且需要被搜索引擎抓取的应用。服务器负担重:每次页面请求时,服务器都需要生成完整的 HTML,可能导致服务器负担较重,尤其在高并发情况下。开发复杂度高:需要处理服务器端渲染和客户端交互的协调问题,配置和开发过程相对 SPA 更为复杂。SPA:
流畅的用户体验:用户在页面加载后,可以实现无刷新操作,页面之间切换非常流畅,适合动态交互丰富的应用。
较低的服务器负担:服务器只需要提供静态资源,所有的交互都由前端处理,服务器负担较轻。
开发体验好:开发过程中,前后端开发可以独立进行,前端完全控制应用逻辑和状态。
SEO 挑战:由于内容是通过 JavaScript 渲染的,搜索引擎无法直接抓取到页面内容,需要额外配置(例如 SSR、Prerendering)来优化 SEO。
首次加载时间较长:由于需要加载 JavaScript 代码,首次加载页面的时间可能较长,用户看到的内容可能有延迟。
浏览器性能要求高:由于大部分逻辑都在客户端运行,浏览器性能不佳时可能导致应用运行缓慢。
SSR 适用于需要较好 SEO 和更快首屏加载的应用,但其服务器负担较重,开发相对复杂。
SPA 更适合需要动态交互和快速响应的应用,但首次加载较慢,SEO 可能存在问题。
**SEO(Search Engine Optimization,搜索引擎优化)**是一种通过优化网站或网页内容,使其在搜索引擎中获得更高排名的技术和策略。SEO 的目标是提高网站在搜索引擎结果页(SERP)中的可见性,从而吸引更多的自然流量。
静态站点生成 (Static-Site Generation,缩写为 SSG),也被称为预渲染,是另一种流行的构建快速网站的技术。如果用服务端渲染一个页面所需的数据对每个用户来说都是相同的,那么我们可以只渲染一次,提前在构建过程中完成,而不是每次请求进来都重新渲染页面。预渲染的页面生成后作为静态 HTML 文件被服务器托管。
5.内置组件 1.KeepAlive组件<KeepAlive> 是 Vue 提供的一个内置组件,用于 缓存组件的状态,避免组件在切换过程中重新渲染。它能够在组件切换时,保留组件的状态(包括 DOM 结构、数据等),使得在再次显示该组件时无需重新加载,保持上次的状态,从而提升用户体验和性能。<KeepAlive> 主要用于包裹动态组件(如v-if ,v-for,Tab 页切换和Vue路由 控制的组件)
作用: 缓存组件:通过 <KeepAlive>,可以缓存已经渲染过的组件,避免每次切换时重新渲染组件,减少不必要的计算和 DOM 操作。 提高性能:当你有多个页面或多个视图组件时,用户在切换视图时不需要重新渲染整个页面,这样能显著减少性能开销。 保持组件状态:缓存组件的状态,例如输入框的内容、滚动位置、组件内部的动画状态等,这些都能保持在组件重新显示时,避免丢失。
KeepAlive 的主要特性 缓存多个组件: <KeepAlive> 允许多个组件同时被缓存,只要它们在 <KeepAlive> 中渲染过一次,就会保持在内存中。
条件缓存: <KeepAlive> 可以通过 include 和 exclude 属性,指定哪些组件需要缓存,哪些不需要缓存。 include:一个字符串或正则表达式,用于指定哪些组件应该被缓存。 exclude:一个字符串或正则表达式,用于指定哪些组件不应该被缓存。
<template> <keep-alive :include="['ComponentA']" :exclude="['ComponentB']"> <component :is="currentComponent"></component> </keep-alive> </template>生命周期钩子: 使用 <KeepAlive> 时,组件的生命周期会有一些不同之处,具体是 activated 和 deactivated 钩子:使用 <KeepAlive> 缓存的组件不会触发 created 或 mounted 等生命周期钩子,而会触发 activated 和 deactivated
activated:当组件被缓存并恢复时(即被重新激活时)触发。deactivated:当组件被缓存并且失活时(即被切换出视图时)触发。 这两个生命周期钩子专门用于处理缓存组件的逻辑。可以在 activated 中启动某些操作,在 deactivated 中暂停或清理操作。 2.Teleport组件<Teleport> 是 Vue 3 中引入的一个内置组件,用于 将组件的渲染输出传送到 DOM 树的其他位置。它可以将一个组件的内容渲染到 DOM 中指定的任何位置,而不是在当前组件树中渲染。它主要用于一些场景,比如模态框、弹出层、通知等,需要在文档的不同位置显示,但又需要保持在 Vue 组件的上下文中。确保它们的显示层级不会被父级组件的样式或布局影响。<Teleport> 就是为了解决这个问题,它允许你将组件的 DOM 输出传送到一个完全不同的位置,同时依然保持它在 Vue 的组件树中的状态和逻辑。
<Teleport> 组件有两个主要的属性:
to:指定渲染目标的 DOM 元素。可以是一个选择器(如 #app)或者是一个 DOM 元素本身。v-if / v-show:可以控制何时渲染内容。 <template> <div> <button @click="showModal = true">打开模态框</button> <Teleport to="body"> <div v-if="showModal" class="modal"> <div class="modal-content"> <span @click="showModal = false" class="close">×</span> <p>这是一个模态框!</p> </div> </div> </Teleport> </div> </template> <script> export default { data() { return { showModal: false, }; }, }; </script> <style> .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; } .modal-content { background: white; padding: 20px; border-radius: 5px; text-align: center; } .close { position: absolute; top: 10px; right: 10px; font-size: 20px; cursor: pointer; } </style>在这个例子中,模态框被渲染到 body 元素中,而不是原本父组件的位置。点击按钮会显示模态框,而模态框的 DOM 元素会直接插入到 body 中,而不是嵌套在组件的 DOM 树内。
<template> <div> <button @click="toggleMessage">切换消息显示</button> <Teleport to="#notification-area"> <div v-if="showMessage" class="notification"> 这是一个通知消息! </div> </Teleport> <!-- 这个区域用于显示通知消息 --> <div id="notification-area"></div> </div> </template> <script> export default { data() { return { showMessage: false, }; }, methods: { toggleMessage() { this.showMessage = !this.showMessage; } } }; </script> <style> .notification { background-color: #f0ad4e; color: white; padding: 10px; border-radius: 5px; margin-top: 10px; } </style>在这个例子中,通知消息会被传送到页面上一个名为 #notification-area 的区域,而不是放在当前组件的位置。每次点击按钮会在该区域显示或隐藏通知。
<Teleport> 的工作原理
渲染目标: <Teleport> 会通过其 to 属性指定一个 DOM 目标位置,组件的渲染内容会被插入到这个目标位置中。例如,可以是 body、#id 或者传入的 DOM 元素。
保持响应式: 尽管组件的 DOM 被移动到了文档的其他位置,但它仍然保留 Vue 的响应式机制,保持组件的状态、事件处理、绑定等特性。所以,不管这个内容被渲染到哪里,数据和事件仍然按照组件的逻辑工作。
生命周期: 通过 <Teleport> 渲染的内容依旧保持原本组件的生命周期钩子。例如,它的 mounted、updated、destroyed 等生命周期钩子会在其正常生命周期中触发。
v-if 与 Teleport: 如果你使用 v-if 控制 <Teleport> 渲染的内容,当该内容被移除时,它会被从目标 DOM 移除,并且销毁相应的 Vue 组件实例。
保持 Vue 响应式:尽管组件的 DOM 被移动到了其他地方,Vue 仍然会保持其响应式特性,数据、事件等都能正常工作。
Vue 生命周期钩子:由于组件的 DOM 被插入到不同的地方,mounted 钩子会在目标位置的插入时触发,而 destroyed 会在移除时触发。
CSS 样式:由于被传送到页面其他地方,某些组件的样式可能会受到影响。确保组件本身的样式可以独立或外部样式不会干扰其显示。
6.Proxy在 Vue 3 中,Proxy 是核心特性之一,用于实现 响应式数据(reactivity)系统。Vue 3 使用 JavaScript 的 Proxy API 来替代 Vue 2 中的 Object.defineProperty 来进行数据代理。这使得 Vue 3 在响应式性能和易用性上都有了显著的提升。
Proxy 是 JavaScript 的一种新特性(在 ES6 中引入),它可以用来定义一个对象的代理。通过 Proxy,你可以拦截对对象的操作(如属性访问、修改、删除等),并定义自定义的行为。Proxy 的语法如下:
let proxy = new Proxy(target, handler); target:需要被代理的目标对象。handler:一个对象,用于定义拦截操作(例如 get、set、deleteProperty 等)。在 Vue 3 中,响应式系统就是基于 Proxy 实现的。Vue 会通过 Proxy 来代理数据对象,捕获对数据的各种操作(如读取、修改、删除、赋值等),并自动更新视图。当数据发生变化时,Vue 会触发视图的更新,从而实现响应式。
Vue 3 Proxy 的主要功能
拦截属性访问(get): 当访问某个属性时,Proxy 会捕获到这个操作,并执行 get 钩子。Vue 会记录依赖(即哪些组件或计算属性依赖于这个属性)。
拦截属性赋值(set): 当修改对象的某个属性时,Proxy 会捕获这个赋值操作,并执行 set 钩子。Vue 会在 set 钩子中触发视图更新。
拦截属性删除(deleteProperty): 当删除某个属性时,Proxy 会捕获这个操作,Vue 会处理相关的依赖更新。
拦截对象的其他操作: 比如操作对象的长度、遍历对象(for...in)等,Vue 会通过 Proxy 捕获并处理。
Vue 3 Proxy 工作原理
代理数据对象: Vue 3 在初始化数据时,会将数据对象通过 Proxy 进行代理。代理后的对象会拦截对数据对象的访问,监控每个属性的变化。
依赖收集: 当组件访问某个数据属性时,Vue 会记录这个访问行为,标记该属性为该组件的依赖。这样,当数据发生变化时,组件就会重新渲染。
触发视图更新: 当数据属性被修改时,set 操作会被触发,Vue 会通过 Proxy 捕获到这个变化,并通知视图更新。它会通知所有依赖于这个数据的组件或计算属性,进行重新渲染。
Proxy 与 Vue 2 的响应式系统对比
在 Vue 2 中,响应式系统是通过 Object.defineProperty 实现的。Object.defineProperty 会为每个属性定义 getter 和 setter,从而拦截对该属性的访问和修改。这种方式的缺点包括:
无法处理动态添加或删除的属性。对数组等特殊类型的支持有限。性能较差,尤其在大规模数据更新时。而 Vue 3 使用 Proxy 解决了这些问题,Proxy 具有以下优势:
支持代理整个对象:Proxy 可以直接代理整个对象或数组,不需要为每个属性单独定义 getter 和 setter。支持动态属性添加和删除:通过 Proxy,你可以直接添加或删除属性,Vue 会自动处理这些操作。性能提升:Proxy 的性能比 Object.defineProperty 更好,尤其在大量数据更新的情况下。Vue 3 中 Proxy 代理的数据对象的特点
响应式对象:使用 reactive 函数将对象转换为响应式对象后,这个对象会被 Proxy 代理,所有对它的操作都会被拦截和处理。引用传递:Proxy 是基于引用的,意味着通过代理对象修改数据会影响到原始对象。嵌套对象:Proxy 支持深度嵌套。当你访问嵌套对象时,Vue 会为嵌套对象中的每个属性都创建一个 Proxy 代理。 const state = reactive({ user: { name: "John", age: 30 } }); // 修改嵌套对象属性 state.user.name = "Jane"; // 会触发 Proxy 的 `set` 方法在这个例子中,state.user 也是一个 Proxy 代理的对象。因此,当你修改 state.user.name 时,它会触发嵌套的 Proxy 的 set 操作。
Vue 3 Proxy 的性能优化:
懒代理:Vue 3 会对访问的对象或属性进行懒代理,只有在访问该对象或属性时,才会创建相应的 Proxy 代理。这样可以避免不必要的代理操作。优化依赖收集:Vue 3 的响应式系统会智能地进行依赖收集和更新,确保只有真正依赖于某个属性的组件或计算属性才会被重新渲染。【前端学习笔记】Vue3由讯客互联游戏开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【前端学习笔记】Vue3”
上一篇
php系统命令执行及绕过
下一篇
SIM盾构建安全底座的可行性分析