luoyu-vue-core
v1.0.9
Published
工具包-封装一些常用的方法与api请求
Maintainers
Readme
luoyu-vue-core 使用示例文档
目录
安装
npm install luoyu-vue-core
# 或
yarn add luoyu-vue-core
# 或
pnpm add luoyu-vue-core核心钩子函数
worker 相关
useWebWorker
创建和管理 Web Worker 的钩子函数。
使用示例:
<template>
<div>
<h2>Web Worker Example</h2>
<button @click="sendMessage">Send Message to Worker</button>
<div v-if="worker.message">{{ worker.message }}</div>
</div>
</template>
<script setup lang="ts">
import { useWebWorker } from 'luoyu-vue-core';
// 方式 1: 直接传递 worker 文件路径
const worker = useWebWorker({
workerScript: './my-worker.js',
type: 'module'
});
// 方式 2: 使用内联函数
// const worker = useWebWorker({
// workerScript: function() {
// self.onmessage = function(e) {
// console.log('Worker received:', e.data);
// self.postMessage('Response from worker: ' + e.data);
// };
// }
// });
// 监听 worker 消息
worker.onMessage((data) => {
console.log('Main thread received:', data);
});
// 发送消息到 worker
const sendMessage = () => {
worker.postMessage('Hello from main thread!');
};
</script>基础工具
useDebounce
创建防抖引用。
使用示例:
<template>
<div>
<h2>Debounce Example</h2>
<input v-model="searchText" placeholder="Search..." />
<div v-if="searchResult">Search result: {{ searchResult }}</div>
</div>
</template>
<script setup lang="ts">
import { useDebounce, ref, watch } from 'luoyu-vue-core';
// 创建防抖引用,延迟 500ms
const searchText = useDebounce('', { delay: 500 });
const searchResult = ref('');
// 监听防抖后的值变化
watch(searchText, (newValue) => {
if (newValue) {
// 模拟异步搜索
searchResult.value = `Searching for: ${newValue}`;
} else {
searchResult.value = '';
}
});
</script>useThrottle
创建节流引用。
使用示例:
<template>
<div>
<h2>Throttle Example</h2>
<button @click="handleClick">Click me rapidly</button>
<div>Click count: {{ clickCount }}</div>
</div>
</template>
<script setup lang="ts">
import { useThrottle, ref } from 'luoyu-vue-core';
// 创建节流引用,间隔 1000ms
const clickCount = useThrottle(0, { interval: 1000 });
const handleClick = () => {
clickCount.value++;
};
</script>useStorage
本地存储 Hook,支持 localStorage 和 sessionStorage。
使用示例:
<template>
<div>
<h2>Storage Example</h2>
<input v-model="userInput" placeholder="Enter value" />
<button @click="saveValue">Save</button>
<button @click="removeValue">Remove</button>
<div>Stored value: {{ storedValue }}</div>
<div v-if="isExpired">Value has expired</div>
</div>
</template>
<script setup lang="ts">
import { useStorage, ref } from 'luoyu-vue-core';
const userInput = ref('');
// 创建本地存储引用,键为 'example-key',默认值为 'default'
const { value: storedValue, set, remove, isExpired } = useStorage('example-key', 'default', {
type: 'localStorage', // 可选:localStorage 或 sessionStorage
expire: 30000, // 可选:30秒后过期
});
const saveValue = () => {
set(userInput.value);
};
const removeValue = () => {
remove();
};
</script>useWindowSize
监听窗口尺寸变化。
使用示例:
<template>
<div>
<h2>Window Size Example</h2>
<div>Window width: {{ windowSize.width }}px</div>
<div>Window height: {{ windowSize.height }}px</div>
</div>
</template>
<script setup lang="ts">
import { useWindowSize } from 'luoyu-vue-core';
const windowSize = useWindowSize();
</script>useSafeWatch
安全的监听函数,自动在组件卸载时清理。
使用示例:
<template>
<div>
<h2>Safe Watch Example</h2>
<input v-model="count" type="number" />
<div>Doubled: {{ doubled }}</div>
</div>
</template>
<script setup lang="ts">
import { useSafeWatch, ref, computed } from 'luoyu-vue-core';
const count = ref(0);
const doubled = computed(() => count.value * 2);
// 使用安全监听,自动在组件卸载时清理
useSafeWatch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`);
});
// 监听多个源
useSafeWatch([count, doubled], ([newCount, newDoubled], [oldCount, oldDoubled]) => {
console.log(`Count: ${oldCount} -> ${newCount}, Doubled: ${oldDoubled} -> ${newDoubled}`);
}, { deep: true });
</script>事件总线
useMitt
全局事件总线,提供组件间通信能力。
使用示例:
<!-- ComponentA.vue -->
<template>
<div>
<h2>Component A</h2>
<button @click="sendEvent">Send Event</button>
</div>
</template>
<script setup lang="ts">
import { useMitt, ref } from 'luoyu-vue-core';
const useMittInstance = useMitt;
const sendEvent = () => {
useMittInstance.emit('custom-event', { message: 'Hello from Component A' });
};
</script>
<!-- ComponentB.vue -->
<template>
<div>
<h2>Component B</h2>
<div v-if="eventData">Received: {{ eventData.message }}</div>
</div>
</template>
<script setup lang="ts">
import { useMitt, ref, onUnmounted } from 'luoyu-vue-core';
const useMittInstance = useMitt;
const eventData = ref(null);
// 监听事件
useMittInstance.on('custom-event', (data) => {
eventData.value = data;
});
// 组件卸载时移除监听
onUnmounted(() => {
useMittInstance.off('custom-event', (data) => {
eventData.value = data;
});
});
</script>UI 相关
useVideo
视频处理工具。
使用示例:
<template>
<div>
<h2>Video Player Example</h2>
<video ref="videoRef" width="400" controls>
<source src="https://example.com/video.mp4" type="video/mp4">
</video>
<div>
<button @click="play">Play</button>
<button @click="pause">Pause</button>
<button @click="toggleMute">Toggle Mute</button>
<input type="range" min="0" max="1" step="0.1" v-model="volume" @input="setVolume(volume)">
</div>
<div>Current time: {{ currentTime.toFixed(1) }}s</div>
<div>Duration: {{ duration.toFixed(1) }}s</div>
</div>
</template>
<script setup lang="ts">
import { useVideo, ref, onMounted, computed } from 'luoyu-vue-core';
const videoRef = ref<HTMLVideoElement | null>(null);
const { play, pause, setVolume, setMuted, getVolume, getMuted, getCurrentVideoTime, getVideoDuration, setupPlayer } = useVideo();
const volume = ref(1);
const isMuted = ref(false);
onMounted(() => {
if (videoRef.value) {
setupPlayer(videoRef.value);
volume.value = getVolume() || 1;
isMuted.value = getMuted() || false;
}
});
const toggleMute = () => {
setMuted(!isMuted.value);
isMuted.value = !isMuted.value;
};
const currentTime = computed(() => getCurrentVideoTime());
const duration = computed(() => getVideoDuration());
</script>useTable
表格数据管理工具。
使用示例:
<template>
<div>
<h2>Table Example</h2>
<div class="search-bar">
<input v-model="searchParam.name" placeholder="Search by name" />
<button @click="search">Search</button>
</div>
<table v-if="!loading">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="item in tableData" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.email }}</td>
</tr>
</tbody>
</table>
<div v-else>Loading...</div>
<div v-if="isPaginationVisible" class="pagination">
<button @click="pagination.current--" :disabled="pagination.current === 1">Previous</button>
<span>Page {{ pagination.current }} of {{ Math.ceil(pagination.total / pagination.size) }}</span>
<button @click="pagination.current++" :disabled="pagination.current >= Math.ceil(pagination.total / pagination.size)">Next</button>
</div>
</div>
</template>
<script setup lang="ts">
import { useTable, ref } from 'luoyu-vue-core';
// 模拟 API 请求
const fetchData = async (params: Record<string, any>) => {
try {
const response = await fetch(`https://api.example.com/users?page=${params.page}&pageSize=${params.size}&name=${params.name || ''}`);
const data = await response.json();
return [null, data];
} catch (error) {
return [error as Error, null];
}
};
const searchParam = ref({ name: '' });
const {
tableData,
pagination,
loading,
isPaginationVisible,
search
} = useTable({
request: fetchData,
initParam: { name: '' },
isPageAble: true,
immediate: true
});
</script>useProgressBar
进度条动画控制。
使用示例:
<template>
<div>
<h2>Progress Bar Example</h2>
<div class="progress-container">
<div class="progress-bar" :style="{ width: `${progress.percentage}%` }"></div>
</div>
<div class="controls">
<button @click="start" :disabled="isRunning">Start</button>
<button @click="stop" :disabled="!isRunning">Stop</button>
<button @click="reset">Reset</button>
<button @click="complete">Complete</button>
</div>
<div class="status">
<p>Status: {{ isCompleted ? 'Completed' : isRunning ? 'Running' : 'Stopped' }}</p>
<p>Progress: {{ Math.round(progress.percentage) }}%</p>
</div>
</div>
</template>
<script setup lang="ts">
import { useProgressBar } from 'luoyu-vue-core';
const {
progress,
percentage,
isRunning,
isCompleted,
start,
stop,
reset,
complete
} = useProgressBar({
min: 0,
max: 100,
duration: 3000 // 3秒完成
});
</script>
<style scoped>
.progress-container {
width: 100%;
height: 20px;
background-color: #f0f0f0;
border-radius: 10px;
overflow: hidden;
}
.progress-bar {
height: 100%;
background-color: #4caf50;
transition: width 0.1s ease;
}
</style>usePixel
像素转换工具。
使用示例:
<template>
<div>
<h2>Pixel Conversion Example</h2>
<div>
<label>px to rem: </label>
<input v-model="pxValue" type="number" />
<span>{{ remValue }}rem</span>
</div>
<div>
<label>rem to px: </label>
<input v-model="remInput" type="number" />
<span>{{ pxResult }}px</span>
</div>
<div>Generated ID: {{ generatedId }}</div>
</div>
</template>
<script setup lang="ts">
import { usePixel, computed, ref, onMounted } from 'luoyu-vue-core';
const { pxToRem, remToPx, getId } = usePixel();
const pxValue = ref(16);
const remInput = ref(1);
const generatedId = ref('');
const remValue = computed(() => pxToRem(pxValue.value));
const pxResult = computed(() => remToPx(remInput.value));
onMounted(() => {
generatedId.value = getId();
});
</script>useDynamicViewport
动态视口管理。
使用示例:
<template>
<div>
<h2>Dynamic Viewport Example</h2>
<div class="container" :ref="containerRef">
<div class="dynamic-box" :style="{ width: `${width}px`, height: `${height}px` }"></div>
</div>
<div class="controls">
<label>Height percentage: </label>
<input type="range" min="0" max="100" v-model="heightPercentage" @input="setHeight(heightPercentage)" />
<label>Width percentage: </label>
<input type="range" min="0" max="100" v-model="widthPercentage" @input="setWidth(widthPercentage)" />
</div>
</div>
</template>
<script setup lang="ts">
import { useDynamicViewport, ref } from 'luoyu-vue-core';
const containerRef = ref<HTMLElement | null>(null);
const { width, height, setHeight, setWidth } = useDynamicViewport(50, 50, containerRef);
const heightPercentage = ref(50);
const widthPercentage = ref(50);
</script>
<style scoped>
.container {
width: 400px;
height: 300px;
background-color: #f0f0f0;
margin: 20px 0;
}
.dynamic-box {
background-color: #4caf50;
transition: width 0.3s ease, height 0.3s ease;
}
</style>useScreenAdaptation
屏幕适配工具。
使用示例:
<template>
<div>
<h2>Screen Adaptation Example</h2>
<div class="screen-info">
<p>Screen type: {{ screen.type }}</p>
<p>Window size: {{ width }}px × {{ height }}px</p>
<p>Device pixel ratio: {{ screen.devicePixelRatio }}</p>
<p>High DPI: {{ screen.isHighDPI ? 'Yes' : 'No' }}</p>
<p>Scale factor: {{ scale }}</p>
</div>
<div class="adapted-box" :style="{ fontSize: `${adaptSize(16)}px` }">
This text adapts to screen size
</div>
</div>
</template>
<script setup lang="ts">
import { useScreenAdaptation } from 'luoyu-vue-core';
const { screen, width, height, type, isHighDPI, scale, adaptSize } = useScreenAdaptation();
</script>
<style scoped>
.adapted-box {
padding: 20px;
background-color: #e3f2fd;
margin-top: 20px;
}
</style>工具函数
组件管理
createComponentsInstaller
创建全局组件安装函数。
使用示例:
import { createApp } from 'vue';
import { createComponentsInstaller } from 'luoyu-vue-core';
import Button from './components/Button.vue';
import Input from './components/Input.vue';
import App from './App.vue';
// 创建组件安装器
const installComponents = createComponentsInstaller({
MyButton: Button,
MyInput: Input
});
// 创建应用并安装组件
const app = createApp(App);
installComponents(app);
app.mount('#app');mountComponent
动态挂载组件到 DOM。
使用示例:
<template>
<div>
<h2>Dynamic Component Mounting</h2>
<div id="dynamic-container"></div>
<button @click="mountDynamicComponent">Mount Component</button>
<button @click="unmountDynamicComponent" :disabled="!componentInstance">Unmount Component</button>
</div>
</template>
<script setup lang="ts">
import { mountComponent, unmountComponent, ref } from 'luoyu-vue-core';
import DynamicComponent from './components/DynamicComponent.vue';
const componentInstance = ref(null);
const mountDynamicComponent = () => {
componentInstance.value = mountComponent(DynamicComponent, {
container: '#dynamic-container',
props: {
title: 'Dynamically Mounted',
message: 'This component was mounted dynamically'
}
});
};
const unmountDynamicComponent = () => {
if (componentInstance.value) {
unmountComponent(componentInstance.value);
componentInstance.value = null;
}
};
</script>unmountComponent
卸载已挂载的组件。
使用示例:
import { unmountComponent } from 'luoyu-vue-core';
// 假设我们已经有一个已挂载的组件实例
const instance = mountComponent(MyComponent, { container: '#app' });
// 后来需要卸载组件
unmountComponent(instance);getComponentName
获取组件名称。
使用示例:
import { getComponentName } from 'luoyu-vue-core';
import MyComponent from './components/MyComponent.vue';
// 获取组件名称
const componentName = getComponentName(MyComponent);
console.log(`Component name: ${componentName}`);响应式工具
isRef
检查值是否为 Ref 对象。
使用示例:
import { isRef, ref, computed } from 'luoyu-vue-core';
const refValue = ref(10);
const computedValue = computed(() => refValue.value * 2);
const normalValue = 20;
console.log(isRef(refValue)); // true
console.log(isRef(computedValue)); // false
console.log(isRef(normalValue)); // falseisComputed
检查值是否为计算属性。
使用示例:
import { isComputed, ref, computed } from 'luoyu-vue-core';
const refValue = ref(10);
const computedValue = computed(() => refValue.value * 2);
const normalValue = 20;
console.log(isComputed(refValue)); // false
console.log(isComputed(computedValue)); // true
console.log(isComputed(normalValue)); // falseisWritableComputed
检查值是否为可写计算属性。
使用示例:
import { isWritableComputed, ref, computed } from 'luoyu-vue-core';
const refValue = ref(10);
const readOnlyComputed = computed(() => refValue.value * 2);
const writableComputed = computed({
get: () => refValue.value,
set: (value) => refValue.value = value
});
console.log(isWritableComputed(readOnlyComputed)); // false
console.log(isWritableComputed(writableComputed)); // trueunref
解包 Ref 或 ComputedRef 值。
使用示例:
import { unref, ref, computed } from 'luoyu-vue-core';
const refValue = ref(10);
const computedValue = computed(() => refValue.value * 2);
const normalValue = 20;
console.log(unref(refValue)); // 10
console.log(unref(computedValue)); // 20
console.log(unref(normalValue)); // 20组件实例操作
getInstanceProperty
安全地获取组件实例的属性。
使用示例:
import { getInstanceProperty } from 'luoyu-vue-core';
// 假设我们有一个组件实例
const instance = {
title: 'My Component',
count: 5
};
// 获取存在的属性
const title = getInstanceProperty(instance, 'title', 'Default Title');
console.log(title); // 'My Component'
// 获取不存在的属性,使用默认值
const description = getInstanceProperty(instance, 'description', 'No description');
console.log(description); // 'No description'callInstanceMethod
安全地调用组件实例的方法。
使用示例:
import { callInstanceMethod } from 'luoyu-vue-core';
// 假设我们有一个组件实例
const instance = {
count: 5,
increment() {
this.count++;
return this.count;
},
add(a: number, b: number) {
return a + b;
}
};
// 调用存在的方法
const newCount = callInstanceMethod(instance, 'increment');
console.log(newCount); // 6
// 调用带参数的方法
const sum = callInstanceMethod(instance, 'add', 5, 10);
console.log(sum); // 15
// 调用不存在的方法
const result = callInstanceMethod(instance, 'nonExistentMethod');
console.log(result); // undefined计算属性增强
computedDebounced
防抖计算属性。
使用示例:
<template>
<div>
<h2>Debounced Computed Example</h2>
<input v-model="searchQuery" placeholder="Search..." />
<div>Debounced result: {{ debouncedResult }}</div>
</div>
</template>
<script setup lang="ts">
import { computedDebounced, ref } from 'luoyu-vue-core';
const searchQuery = ref('');
// 创建防抖计算属性,延迟 500ms
const debouncedResult = computedDebounced(() => {
// 模拟耗时操作
console.log('Computing result for:', searchQuery.value);
return `Result for: ${searchQuery.value}`;
}, { delay: 500 });
</script>computedThrottled
节流计算属性。
使用示例:
<template>
<div>
<h2>Throttled Computed Example</h2>
<button @click="increment">Click rapidly ({{ count }})</button>
<div>Throttled count: {{ throttledCount }}</div>
</div>
</template>
<script setup lang="ts">
import { computedThrottled, ref } from 'luoyu-vue-core';
const count = ref(0);
const increment = () => {
count.value++;
};
// 创建节流计算属性,间隔 1000ms
const throttledCount = computedThrottled(() => {
console.log('Throttled update:', count.value);
return count.value;
}, { interval: 1000 });
</script>