1.0.2 • Published 6 months ago
@achuan9/use-load-deps v1.0.2
use-load-deps
一个用于管理外部依赖(如JS、CSS文件)加载的Vue 3组合式API工具。
特性
- 🚀 支持按需加载外部依赖
- 🔄 支持并行或串行加载
- ⏱️ 支持空闲时间加载
- 🔒 防止重复加载
- 📊 提供加载状态管理
- 🎯 支持加载回调函数
安装
# 使用 pnpm
pnpm add @achuan9/use-load-deps
# 使用 npm
npm install @achuan9/use-load-deps
# 使用 yarn
yarn add @achuan9/use-load-deps使用方法
1. 基础用法
首先,在你的应用入口处配置需要加载的依赖:
import { setDepsConfig } from '@achuan9/use-load-deps'
setDepsConfig({
// 配置依赖
flv: {
js: ['https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.js'],
css: ['https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.css'],
},
echarts: {
js: ['https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js'],
sequential: true, // 保证js中的依赖数组串行加载
},
})然后在组件中使用:
<template>
<div>
<div v-if="depsStatus.flv === 'loading'">加载中...</div>
<div v-else-if="depsStatus.flv === 'unload'">未加载</div>
<div v-else>
<!-- 依赖加载完成后的内容 -->
</div>
<button @click="loadDeps('flv')">加载依赖</button>
</div>
</template>
<script setup lang="ts">
import { useLoadDeps } from '@achuan9/use-load-deps'
const { depsStatus, loadDeps, loadDepsOnIdle } = useLoadDeps({
onLoading: (dep) => console.log(`Loading ${dep}...`),
onLoaded: (dep) => console.log(`${dep} loaded!`),
onError: (dep, error) => console.error(`Failed to load ${dep}:`, error),
})
</script>2. 路由守卫用法
// main.ts
import { createApp } from 'vue'
import { createRouter } from 'vue-router'
import { setDepsConfig } from '@achuan9/use-load-deps'
import type { ExternalDependencies } from '@achuan9/use-load-deps'
import { setupDepsGuard } from './router/guard'
// 1. 首先配置依赖
export const depsConfig: ExternalDependencies = {
echarts: {
js: ['https://cdn.bootcdn.net/ajax/libs/echarts/5.6.0/echarts.min.js'],
css: [],
sequential: true
},
flv: {
js: ['https://cdn.bootcdn.net/ajax/libs/flv.js/1.6.2/flv.min.js'],
css: []
}
}
// 2. 设置全局依赖配置(必须在 setupDepsGuard 之前)
setDepsConfig(depsConfig)
// 3. 创建路由
const router = createRouter({
routes: [
{
path: '/echarts',
component: () => import('./views/Echarts.vue'),
meta: {
deps: ['echarts'] // 指定路由需要的依赖
}
},
{
path: '/flv',
component: () => import('./views/Flv.vue'),
meta: {
deps: ['flv']
}
}
]
})
// 4. 设置路由守卫
setupDepsGuard(router)
// 5. 创建应用
const app = createApp(App)
app.use(router)
app.mount('#app')
// router/guard.ts
import { useLoadDeps } from '@achuan9/use-load-deps'
import type { Router, RouteLocationNormalized } from 'vue-router'
export function setupDepsGuard(router: Router) {
const { getUnloadDeps, loadDeps, loadDepsOnIdle } = useLoadDeps({
onLoading: (dep) => console.log(`Loading ${dep}...`),
onLoaded: (dep) => console.log(`${dep} loaded!`),
onError: (dep, error) => console.error(`Failed to load ${dep}:`, error)
})
// 路由进入前加载依赖
router.beforeEach(async (to: RouteLocationNormalized) => {
const targetDeps = to.meta.deps as string[] || []
console.log('目标路由需要的依赖,必须加载完才能进入', targetDeps)
if (targetDeps.length > 0) {
try {
await loadDeps(targetDeps)
} catch (error) {
console.error('Failed to load dependencies:', error)
}
}
return true
})
// 路由进入后,利用空闲时间加载其他依赖
router.afterEach(() => {
const unloadDeps = getUnloadDeps()
console.log('未加载的依赖,利用空闲时间加载', unloadDeps)
if (unloadDeps.length > 0) {
loadDepsOnIdle(unloadDeps)
}
})
}
// views/Echarts.vue
<template>
<div class="echarts-demo">
<h2>Echarts 示例 -- 确定加载完成才进入页面</h2>
<div v-if="depsStatus.echarts === 'loading'">加载中...</div>
<div v-else-if="depsStatus.echarts === 'unload'">未加载</div>
<div v-else>加载完成</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useLoadDeps } from '@achuan9/use-load-deps'
const chartRef = ref<HTMLElement>()
const { depsStatus } = useLoadDeps({
onLoading: (dep) => console.log(`echarts: Loading ${dep}...`),
onLoaded: (dep) => console.log(`echarts: ${dep} loaded!`),
onError: (dep, error) => console.error(`echarts: Failed to load ${dep}:`, error)
})
onMounted(() => {
if (chartRef.value) {
echarts.init(chartRef.value)
// 创建地图
}
})
</script>API
setDepsConfig
配置需要加载的依赖。
setDepsConfig(config: ExternalDependencies)参数
config: 依赖配置对象interface ExternalDependencies { [key: string]: { js?: string[] // JS文件URL数组 css?: string[] // CSS文件URL数组 sequential?: boolean // 是否串行加载JS文件 } }
useLoadDeps
返回依赖加载相关的状态和方法。
const { depsStatus, loadDeps, loadDepsOnIdle, getUnloadDeps } = useLoadDeps(callbacks?)参数
callbacks: 可选的回调函数对象interface LazyDepsCallbacks { onLoading?: (dep: string) => void // 开始加载时触发 onLoaded?: (dep: string) => void // 加载完成时触发 onError?: (dep: string, error: Error) => void // 加载失败时触发 }
返回值
depsStatus: 响应式的依赖状态对象{ [key: string]: 'unload' | 'loading' | 'loaded' }loadDeps: 加载依赖的方法;(deps: string | string[]) => Promise<ExternalDependencyStatus>loadDepsOnIdle: 在空闲时间加载依赖的方法;(deps: string | string[]) => Promise<ExternalDependencyStatus>getUnloadDeps: 获取未加载的依赖列表() => string[]
依赖状态
依赖有三种状态:
unload: 未加载loading: 加载中loaded: 已加载
特性说明
防止重复加载:
- 如果依赖正在加载中,会复用现有的加载Promise
- 如果依赖已加载完成,不会重复加载
并行/串行加载:
- 默认并行加载所有JS文件
- 设置
sequential: true可以串行加载JS文件 - CSS文件始终并行加载
空闲时间加载:
- 使用
requestIdleCallback在浏览器空闲时加载依赖 - 如果浏览器不支持
requestIdleCallback,会立即加载
- 使用
状态管理:
- 提供响应式的依赖状态
- 支持加载状态的回调函数
- 支持错误处理
许可证
MIT