npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

luoyu-vue-core

v1.0.9

Published

工具包-封装一些常用的方法与api请求

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)); // false

isComputed

检查值是否为计算属性。

使用示例

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)); // false

isWritableComputed

检查值是否为可写计算属性。

使用示例

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)); // true

unref

解包 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>