VUE 框架
专题版块详见 VUE 专题。
1. 事件总线
1. 事件总线
事件总线:通过创建一个全局事件管理器,允许跨组件通信。
事件总线适用于小型或中型项目,用于快速的跨组件通信,但在大型应用中,使用 Vuex 或其他状态管理工具会更加规范和高效。事件总线没有集中管理状态的能力,容易导致代码的难以维护。
js
const EventBus = new Vue();
// 在一个组件中
EventBus.$emit("someEvent", data);
// 在另一个组件中
EventBus.$on("someEvent", (data) => {
console.log(data);
});
一般是单独放在一个文件中,如 eventBus.js
,然后在需要的地方引入。
js
// src/event-bus.js
import Vue from "vue";
export const EventBus = new Vue();
vue
<!-- 发送事件(触发事件) -->
<template>
<button @click="sendEvent">发送事件</button>
</template>
<script>
import { EventBus } from "@/event-bus";
export default {
methods: {
sendEvent() {
// 触发事件
EventBus.$emit("myEvent", "Hello from Component A!");
},
},
};
</script>
vue
<!-- 监听事件(接收事件) -->
<template>
<div>{{ message }}</div>
</template>
<script>
import { EventBus } from "@/event-bus";
export default {
data() {
return {
message: "",
};
},
created() {
// 监听事件
EventBus.$on("myEvent", (data) => {
this.message = data;
});
},
beforeDestroy() {
// 记得在组件销毁前取消监听
EventBus.$off("myEvent");
},
};
</script>
2. 虚拟滚动
2.1 原理以及步骤
虚拟滚动的原理: 当用户滚动列表时,只渲染当前视口内的元素,而不是渲染整个数据列表。随着滚动的进行,不断更新显示在视口内的内容,并销毁那些不再可见的元素。
虚拟滚动通常包括以下步骤:
- 计算可视区域:首先,需要计算出容器的高度、每个元素的高度(或宽度)(如果每一个元素的高度不一致?),以及当前可视区域的滚动位置。
- 元素高度不一致时:
heightCache
:为每个元素存储了其高度,并在calculateTotalHeight()
方法中进行缓存。这样在每次更新时,只需要使用缓存的高度进行计算,避免重复的高度计算。updateVisibleItems()
:在滚动时直接使用缓存的高度数据来计算可视区域,避免了每次都要重新计算 DOM 的高度。
- 元素高度不一致时:
- 按需渲染:只渲染可视区域内的元素。通过计算,确定哪些元素在视口范围内,将这些元素渲染出来。
- 元素复用与销毁:当用户滚动时,新的元素会被加载进视口,超出视口的元素会被销毁或隐藏,避免不必要的渲染。
2. 虚拟滚动
虚拟滚动:一些 UI 组件库(如 Vuetify 和 Ant Design Vue)提供虚拟滚动组件,通过按需渲染可见部分的元素来提高性能。
vue
<!-- 以下是一个简单的虚拟滚动实现的伪代码示例: -->
<!--
核心逻辑:
1) 计算开始和结束的索引:根据滚动的偏移量 (scrollTop),计算当前视口内需要显示的元素的索引范围。
2) 更新可见元素:通过 slice() 方法从数据源中取出可见部分的数据,并渲染出来。
3) 动态调整渲染范围:根据滚动事件 (onScroll) 不断更新可见元素列表,实现滚动时元素的动态更新。
关键参数:
1) itemHeight:每个列表项的高度(可以是固定值,也可以动态计算)。
2) scrollTop:当前容器的滚动位置,用于计算当前可视区域。
3) buffer:设置缓存区,表示在视口外但靠近视口的元素也会被提前渲染,避免用户快速滚动时出现空白。
-->
<template>
<div class="scroll-container" @scroll="onScroll">
<div class="virtual-list" :style="{ height: totalHeight + 'px' }">
<!-- 动态生成可见的虚拟元素 -->
<div v-for="item in visibleItems" :key="item.id" class="list-item">
{{ item.content }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
items: Array.from({ length: 10000 }, (_, index) => ({
id: index,
content: `Item ${index + 1}`,
})), // 模拟数据源
visibleItems: [],
itemHeight: 30, // 假设每个项的高度为 30px
containerHeight: 0,
scrollTop: 0,
buffer: 10, // 缓冲区,即在视口外渲染一些元素
};
},
mounted() {
this.containerHeight = this.$el.clientHeight;
this.updateVisibleItems();
},
methods: {
onScroll() {
this.scrollTop = this.$el.scrollTop;
this.updateVisibleItems();
},
updateVisibleItems() {
const startIndex = Math.max(
0,
Math.floor(this.scrollTop / this.itemHeight) - this.buffer
);
const endIndex = Math.min(
this.items.length - 1,
Math.floor((this.scrollTop + this.containerHeight) / this.itemHeight) +
this.buffer
);
this.visibleItems = this.items.slice(startIndex, endIndex);
},
},
};
</script>
<style scoped>
.scroll-container {
overflow-y: auto;
height: 400px; /* 设置容器的高度 */
}
.virtual-list {
position: relative;
}
.list-item {
height: 30px; /* 假设每个列表项的高度 */
line-height: 30px;
border-bottom: 1px solid #ddd;
}
</style>
2.2 应用场景
虚拟滚动通常用于以下几种场景:
- 长列表或大量数据渲染:例如数据表格、商品列表、聊天记录等,列表中包含大量数据时,使用虚拟滚动可以有效提高渲染性能,避免浏览器卡顿。
- 无限滚动:当数据需要从服务器端分页加载时,虚拟滚动非常适合与“懒加载”结合使用,随着滚动的进行,动态加载更多数据并呈现给用户。
- 大数据展示:当页面上需要显示的数据量很大,例如大规模的图表、图像、文件列表等,虚拟滚动能够提供良好的用户体验。
- 性能优化:虚拟滚动是提高长列表性能的标准技术之一,尤其在移动端设备上,由于硬件性能的限制,虚拟滚动尤为重要。
2.3 适用的组件库
许多 UI 组件库和框架都支持虚拟滚动组件。例如:
- Vuetify:通过 v-virtual-scroll 实现虚拟滚动。
- Ant Design Vue:通过 VirtualList 组件实现虚拟滚动。
- React Virtualized:一个常用于 React 应用的虚拟滚动库,适合处理大型数据集。
- Vue Virtual Scroller:一个轻量级的 Vue 组件库,用于虚拟滚动。
3. 懒加载
专题版块详见 图片优化。
3.1 原理
懒加载(Lazy Loading) 是一种延迟加载资源的技术,指的是只在需要时才加载资源,从而提高页面加载速度,节省带宽,改善用户体验。在 UI 开发中,懒加载通常用于图片、视频等资源的加载,或者在滚动到可视区域时才加载某些内容。
3.2 实现方式
- IntersectionObserver:一种浏览器原生 API,提供了一种方法来检测元素与视口的交叉情况,适合用于懒加载的实现。
- 滚动监听:通过监听滚动事件,判断元素是否进入视口范围,从而触发加载。
3. 懒加载
懒加载:对于需要大量图片或资源的组件,可以使用懒加载技术(如 IntersectionObserver)仅加载用户当前视图中的元素。
4. 自定义指令和插件扩展
4. 自定义指令和插件扩展
自定义指令和插件扩展:对于需要大量图片或资源的组件,可以使用懒加载技术(如 IntersectionObserver)仅加载用户当前视图中的元素。
js
Vue.directive("focus", {
// 当绑定元素插入到 DOM 中时
inserted: function (el) {
el.focus();
},
});
// 使用:<input v-focus>
自定义指令的生命周期钩子
- bind:指令与元素绑定时调用。
- inserted:元素插入父节点时调用。
- update:组件更新时调用。
- componentUpdated:组件更新完成后调用。
- unbind:指令与元素解绑时调用。