Vue3
watch和watchEffect的区别
watch 和 watchEffect 都能响应式地执行回调函数。区别是追踪响应式依赖的方式不同:
watch只追踪明确定义的数据源,不会追踪在回调中访问到的东西;默认情况下,只有在数据源发生改变时才会触发回调;watch需要传入指定的属性;watch可以访问侦听数据的新值和旧值。watchEffect会初始化执行一次,在副作用发生期间追踪依赖,自动分析出侦听数据源;watchEffect需要传入回调函数;watchEffect无法访问侦听数据的新值和旧值。
简单一句话,watch 功能更加强大,而 watchEffect 在某些场景下更加简洁。
Vue3响应式拦截底层大致原理
-
创建 Proxy 对象:当 Vue 3 需要创建一个响应式对象时,它会使用
new Proxy(target, handler)来创建一个代理对象。其中target是要被代理的目标对象(通常是原始数据对象),handler是一个对象,定义了拦截目标对象各种操作的行为。 -
定义 handler:在
handler对象中,Vue 3 会定义一些陷阱函数(trap functions),如get和set。这些函数会在代理对象上的相应操作被调用时执行。- get 陷阱函数:当访问代理对象的属性时,
get函数会被调用。Vue 3 在这里收集依赖关系,并将这些依赖关系存储在内部的数据结构中。这样,当数据发生变化时,可以通知相关的依赖进行更新。 - set 陷阱函数:当修改代理对象的属性时,
set函数会被调用。Vue 3 在这里触发属性的变化,并通知所有依赖于该属性的观察者进行更新。这通常涉及重新运行与该属性相关的计算属性或方法,并更新 DOM。
- get 陷阱函数:当访问代理对象的属性时,
-
依赖收集和触发更新:Vue 3 使用一个内部的数据结构来跟踪每个属性的依赖关系。当属性被访问时,Vue 3 会收集当前的观察者(如计算属性、渲染函数等),并将它们与属性关联起来。当属性被修改时,Vue 3 会触发这些观察者的更新。
-
优化和性能:Vue 3 还进行了一些优化,以减少不必要的计算和更新。例如,它会检查属性是否真的发生了变化,并且只会触发依赖于已更改属性的观察者的更新。
Vue3传送门
传送门(Teleport)是一种组件,用于将子组件的内容渲染到 DOM 的其他位置。这在需要将组件的内容插入到 DOM 结构中不在其父组件的层次结构中的情况特别有用,例如模态框、弹出菜单、提示框等。
<template>
<div>
<h1>这是主内容</h1>
<button @click="showModal = true">显示模态框</button>
<teleport to="body">
<div v-if="showModal" class="modal">
<h2>这是模态框!</h2>
<button @click="showModal = false">关闭模态框</button>
</div>
</teleport>
<style>
.modal {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
border: 1px solid #ccc;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
</style>
</div>
</template>
<script>
export default {
data() {
return {
showModal: false,
};
},
};
</script>
<teleport to="body">:to属性指定了目标位置。在这个例子中,我们选择了body,意味着模态框的内容将直接添加到文档的 body 元素中。- 目标元素可以是任何有效的 CSS 选择器,如
body,.class-name,#id-name等。 - 在大量动态内容的场景下,使用
Teleport可能会影响性能。
Vue中如何实现缓存页面
<keep-alive> <component :is="currentComponent"></component> </keep-alive>
- 动态组件:使用
<component :is="currentComponent">来实现动态组件,根据currentComponent的值加载不同的组件。 <keep-alive>组件:将动态组件包裹在<keep-alive>中,这样被切换的组件会被缓存,其状态(如输入内容、滚动位置等)也会保持。
<keep-alive> 组件可以通过 include 和 exclude 属性来控制缓存的组件。
include:只有匹配这个属性中列出的组件名称的组件才会被缓存。exclude:任何组件名称与这个属性中列出的名称匹配的组件都不会被缓存。
<template>
<div>
<button @click="currentComponent = 'ComponentA'">Component A</button>
<keep-alive include="ComponentA">
<component :is="currentComponent"></component>
</keep-alive>
</div>
</template>
在这个示例中,只有 ComponentA 会被缓存,而 ComponentB 和 ComponentC 切换时则不会被缓存。
使用 v-slot 自定义插槽
你也可以利用 <keep-alive> 提供的插槽特性来自定义其行为。例如,可以为缓存的组件状态添加自定义逻辑。
<template>
<div>
<button @click="currentComponent = 'ComponentA'">Component A</button>
<button @click="currentComponent = 'ComponentB'">Component B</button>
<keep-alive>
<component :is="currentComponent" v-slot="{ key }">
{{ key }}
</component>
</keep-alive>
</div>
</template>
注意事项
- 在使用
<keep-alive>时,要注意缓存的组件可能会持有状态,因此在设计组件时要考虑到这一点。 - 只适合用于不受较高动态更新频率影响的组件,例如表单、列表等。
总结
<keep-alive>用于高效缓存动态组件,提升应用性能。- 可以通过
include和exclude控制缓存组件。 - 支持组件的
activated和deactivated生命周期钩子。
JS\TS
JS基础类型
Number、String、Boolean、undefined、Null
数组去重
使用扩展运算符和new Set() [...new Set(arr)]
判断数据类型
- 使用
typeof运算符
typeof 运算符可以用来检查基本数据类型(如字符串、数字、布尔值等)。
javascript复制代码
console.log(typeof "Hello"); // "string"
console.log(typeof 10); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (这是一个历史遗留问题)
console.log(typeof Symbol()); // "symbol"
console.log(typeof BigInt(123)); // "bigint"
- 使用
instanceof
instanceof 操作符可以用于检测对象是否是特定构造函数的实例。
javascript复制代码
class Person {}
const person = new Person();
console.log(person instanceof Person); // true
console.log(person instanceof Object); // true
- 使用
Array.isArray()
用来判断一个变量是否为数组。
javascript复制代码
const arr = [1, 2, 3];
const notArr = { key: 'value' };
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(notArr)); // false
- 使用
Object.prototype.toString.call()
这种方法可以更准确地识别各种对象类型,包括内置对象和自定义对象。
javascript复制代码
console.log(Object.prototype.toString.call("Hello")); // "[object String]"
console.log(Object.prototype.toString.call(10)); // "[object Number]"
console.log(Object.prototype.toString.call([])); // "[object Array]"
console.log(Object.prototype.toString.call({})); // "[object Object]"
console.log(Object.prototype.toString.call(null)); // "[object Null]"
console.log(Object.prototype.toString.call(new Date())); // "[object Date]"
- 使用
typeof判断基本类型。 - 使用
instanceof判断对象实例。 - 使用
Array.isArray()判断是否为数组。 - 使用
Object.prototype.toString.call()获取更精确的对象类型。
js与ts区别
- JS是弱类型;TS是强类型。
- TS是JS的超集。主要用于解决大项项目的代码复杂性。
- TS的数据类型有:布尔值、数字、字符串、数组、 元组(tuple)、枚举(enum)、any、void、null和undefined、never、object ,unknown;JS的数据类型有:string,number,boolean,null,undefined,object,array,function,symbol
- TS需要将代码编译为js代码才能在浏览器中执行;JS可以直接在浏览器中运行
- TS有类型断言 变量 as 类型; 可以直接告知该变量的实际类型
ts定义接口
在 TypeScript 中,可以使用 interface 关键字来定义接口。接口用于描述对象的形状,包括其属性及方法的类型。
可以使用extends继承别的interface
ts定义接口的interface,如何设置为全部可选
使用 Partial 内置工具类型
interface Person { name: string; age: number; }
// 使用 Partial 来使所有属性可选
const person: Partial<Person> = { name: "Alice" // age 属性是可选的 };
ts中的泛型
泛型指的是在定义函数/接口/类型时,不预先指定具体的类型,而是在使用的时候在指定类型限制的一种特性。
在数组中取第二到第五个元素
slice() 方法返回一个新的数组对象,这一对象是一个由 start 和 end 决定的原数组的浅拷贝(包括 start,不包括 end),其中 start 和 end 代表了数组元素的索引。原始数组不会被改变。
let a = [0,1,2,3,4,5,6]
// 传值,采用左闭右开 [1,5)
let b = a.slice(1,5)
Threejs
Threejs如何优化渲染性能
在使用 Three.js 处理 3D 模型时,优化性能是非常重要的,尤其是在构建复杂场景或需要支持低功耗设备的情况下。以下是一些常见的优化策略:
- 减少多边形数量
- 简化模型:使用 3D 建模软件(如 Blender、Maya 等)来简化模型的网格,减少多边形数量。
- LOD(细节层次) :实现不同细节层次的模型,根据相机距离动态加载不同分辨率的模型。
- 使用纹理而不是几何体
- 使用纹理:尽量使用纹理贴图来模拟复杂表面,而不是增加更多的几何体细节。
- 合并纹理:将多个小纹理合并成一张大纹理(例如使用纹理图集),以减少材质切换的次数。
- 降低材质和光源数量
- 减少材质数量:尽量使用统一的材质,以减少渲染时的状态切换。
- 限制光源:使用较少的动态光源,考虑使用环境光或全局光照替代阴影和高光。
- 缓存和重用对象
- 实例化:对于重复的模型,可以使用
THREE.InstancedMesh来减少开销。 - 对象池:使用对象池管理可重用的对象,避免频繁创建和销毁对象。
- 优化动画
- 骨骼动画:尽量使用骨骼动画而不是顶点动画,这样可以提高性能。
- 动画混合:使用动画混合(Animation blending)来平滑过渡,减少动画切换的频繁性。
- 限制视野范围
- 剔除干扰:开启视锥体剔除(frustum culling),确保只渲染在摄像机视野内的对象。
- 使用遮挡剔除:使用遮挡剔除技术来避免渲染被其他物体遮挡的部分。
- WebGL 状态管理
- 减少状态切换:尽量减少材质、着色器之间的切换,以提高性能。
- 压缩纹理:使用压缩纹理格式(如 KTX、DDS),以减少内存占用和提升加载速度。
- 调整渲染设置
- 降低渲染质量:根据需求调整渲染设置,例如减少抗锯齿、阴影质量等。
- 选择适当的渲染循环:根据场景需求选择
requestAnimationFrame或者固定时间步长更新。
- 使用工具和库
- 使用优化工具:使用工具(如 draco)进行模型压缩和优化。
- Three.js 自带的优化功能:利用 Three.js 中的一些优化特性,如
BufferGeometry等。