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

@robot-admin/directives

v2.0.1

Published

Vue3 自定义指令集合 - 复制、防抖、节流、拖拽、长按、权限、水印、懒加载、Loading、Tooltip、点击外部

Readme

@robot-admin/directives

面向 Vue 3 的通用交互指令集。提供 11 个指令、完整 TypeScript 类型、按需子路径导入、应用级权限与消息适配器,以及可预测的挂载、更新和卸载行为。

npm version license

能力与约束

  • Vue >=3.3,无运行时 UI 框架依赖。
  • ESM、CommonJS、完整声明文件和显式子路径导出。
  • 指令状态使用 WeakMap 隔离;卸载时清理计时器、Observer、全局监听器和临时 DOM。
  • 优先采用 Pointer Events,并补齐键盘、ARIA、焦点和 reduced-motion 行为。
  • Loading/Tooltip 样式按 Document 注入,可通过 styleNonce 适配 CSP。
  • 权限、复制提示均可在应用安装时注入,适合多应用和微前端场景。

当前主版本:2.x

安装

npm install @robot-admin/directives
# 或
bun add @robot-admin/directives

注册

推荐使用标准 Vue 插件 API:

import { createApp } from "vue";
import { createDirectives } from "@robot-admin/directives";

const app = createApp(App);

app.use(
  createDirectives({
    prefix: "", // 可设置为 "ra-",对应 v-ra-copy
    notify: (type, message) => uiMessage[type](message),
    permission: {
      getAuthData: () => permissionStore.permissionMap,
      onDenied: (reason, element) => auditDenied(reason, element),
    },
  }),
);

app.mount("#app");

兼容入口仍可使用:

import { setupDirectives } from "@robot-admin/directives";

setupDirectives(app, options);

按需注册时可从根入口或子路径导入:

import { vDebounce } from "@robot-admin/directives";
import vPermission from "@robot-admin/directives/permission";

app.directive("debounce", vDebounce);
app.directive("permission", vPermission);

可用子路径:copydebouncethrottledraglongpresspermissionwatermarklazyloadingtooltipclick-outside

指令一览

| 指令 | 主要用途 | 关键能力 | | --- | --- | --- | | v-copy | 复制文本 | 动态文本、Clipboard 降级、键盘操作、消息适配 | | v-debounce | 防抖 | handler-owned 模式、leading/trailing、动态事件 | | v-throttle | 节流 | handler-owned 模式、leading/trailing、动态事件 | | v-drag | 拖拽 | Pointer Events、边界、轴向、网格、无侵入清理 | | v-longpress | 长按 | 指针与键盘、移动容差、进度、取消 | | v-permission | 权限控制 | 应用级 Provider、AND/OR、通配符、三种降级 | | v-watermark | 水印 | 多行、高 DPI、缓存、响应更新、可选防删除 | | v-lazy | 懒加载 | 图片/背景、占位与错误图、竞态与请求清理 | | v-loading | 加载遮罩 | 最小展示时长、全屏、ARIA、CSP | | v-tooltip | 提示 | hover/focus/Escape、视口翻转、ellipsis | | v-click-outside | 外部点击 | Shadow DOM、排除项、Document 级共享监听 |

推荐事件模式

v-debouncev-throttle 推荐由指令直接持有 handler,原始事件通过参数传入。这样不会依赖阻断并重新派发 DOM 事件:

<script setup lang="ts">
const search = (event: Event) => {
  const value = (event.target as HTMLInputElement).value;
  // 请求搜索接口
};

const save = () => {
  // 保存
};
</script>

<template>
  <input
    v-debounce:input="{
      handler: search,
      delay: 300,
      trailing: true,
    }"
  />

  <button
    v-throttle:click="{
      handler: save,
      delay: 1000,
      leading: true,
      trailing: false,
    }"
  >
    保存
  </button>
</template>

v-debounce="300" @click="save"v-throttle="300" @click="save" 仍作为兼容模式保留,新代码建议迁移到 handler-owned 模式。

使用示例

复制

<button
  v-copy="{
    text: async () => order.shareUrl,
    successMessage: '链接已复制',
    statusDuration: 500,
    onSuccess: (text) => audit(text),
    onError: (error) => report(error),
  }"
>
  复制链接
</button>

普通元素会自动获得 role="button"tabindex="0" 和 Enter/Space 键支持;卸载时恢复原属性。messageInstance 仅为兼容旧版保留,推荐使用安装级 notify

权限

<button v-permission="'orders:read'">查看订单</button>

<button
  v-permission="{
    permissions: ['orders:read', 'orders:approve'],
    mode: 'AND',
    fallback: 'disable',
    onDenied: (reason) => log(reason),
  }"
>
  审批订单
</button>

权限映射示例:

const permissionMap = {
  "orders:read": true,
  "users:*": true, // 匹配 users:read、users:write 等
};

fallback 可为:

  • hide:隐藏元素,默认值。
  • disable:禁用表单控件;普通元素禁用指针交互。
  • show:保留可见性,同时使用禁用状态和半透明提示。

未提供权限数据时采用拒绝默认值。权限恢复或指令卸载时只回收指令仍然持有的 displayopacitypointer-eventsdisabledaria-disabled;若业务在指令生效期间更新了这些状态,会保留业务的新值,避免卸载覆盖宿主状态。权限集合发生变化时会重新触发一次拒绝通知,重复渲染同一集合不会重复通知。

拖拽与长按

<section
  v-drag="{
    handle: '.card-title',
    boundary: true,
    axis: 'both',
    grid: [8, 8],
    onEnd: (_element, position) => savePosition(position),
  }"
>
  <header class="card-title">拖动</header>
</section>

<button
  v-longpress="{
    duration: 800,
    movementTolerance: 10,
    onProgress: (progress) => setProgress(progress),
    onTrigger: removeItem,
  }"
>
  长按删除
</button>

v-dragboundary 支持 true(父元素)、CSS 选择器或 HTMLElementaxis 支持 xyboth。更新或卸载时只恢复仍由指令写入的内联样式,并主动释放 Pointer Capture、动画帧、Document 监听与文本选择锁,不覆盖业务运行期写入的新样式。

水印与懒加载

<div
  v-watermark="{
    text: [user.name, user.employeeNo],
    fontFamily: 'sans-serif',
    fontSize: 15,
    gap: [120, 100],
    rotate: -25,
    opacity: 0.15,
    preventDelete: true,
  }"
>
  敏感内容
</div>

<img
  v-lazy="{
    src: imageUrl,
    loading: '/placeholder.svg',
    error: '/fallback.png',
    rootMargin: '300px 0px',
    threshold: 0.1,
    onError: report,
  }"
/>

<div v-lazy:background="bannerUrl" />

水印会按当前 devicePixelRatio 生成清晰位图(内部上限为 4),同时保持 CSS 平铺尺寸不变。preventDelete 会启用 MutationObserver,只建议用于确有防篡改需求的区域。懒加载在不支持 IntersectionObserver 时会立即加载,并使用 generation 标记阻止旧异步请求覆盖新绑定值;更新或卸载会断开观察器并移除预加载器属性,不会通过空 src 触发额外请求。

Loading、Tooltip 与外部点击

<div
  v-loading="{
    value: loading,
    text: '加载中…',
    minDuration: 300,
    spinnerSize: 32,
    ariaLabel: '订单列表加载中',
    styleNonce: cspNonce,
  }"
>
  <!-- content -->
</div>

<button
  v-tooltip="{
    content: '重新同步数据',
    placement: 'top',
    showDelay: 150,
    maxWidth: 320,
    styleNonce: cspNonce,
  }"
>
  同步
</button>

<aside
  v-click-outside="{
    handler: close,
    exclude: ['[data-popover-trigger]', triggerElement],
    onError: report,
  }"
>
  <!-- popover -->
</aside>

Loading 文本通过 textContent 渲染。Tooltip 使用 role="tooltip"aria-describedby,支持键盘焦点与 Escape。Click-outside 使用 composedPath(),可正确处理 Shadow DOM。

TypeScript

import type {
  ClickOutsideOptions,
  CopyOptions,
  DebounceOptions,
  DirectivesPluginOptions,
  DragOptions,
  LazyOptions,
  LoadingOptions,
  LongPressOptions,
  PermissionOptions,
  PermissionProvider,
  ThrottleOptions,
  TooltipOptions,
  WatermarkOptions,
} from "@robot-admin/directives";

SSR、CSP 与浏览器说明

  • 指令生命周期只在客户端执行;Nuxt 中应在 .client.ts 插件注册。
  • 根模块导入不会主动访问 windowdocument
  • Clipboard API 在安全上下文中使用,失败时回退至浏览器兼容复制路径。
  • Loading/Tooltip 的内联样式标签可传 styleNonce;水印使用 Canvas data URL,应同步评估站点 CSP。
  • Pointer Events、IntersectionObserver、ResizeObserver 和 MutationObserver 均采用能力检测或在卸载时释放。

从 1.x 升级到 2.x

| 变化 | 迁移建议 | | --- | --- | | 推荐 app.use(createDirectives(options)) | setupDirectives(app) 仍可用,可逐步迁移 | | 防抖/节流新增 handler-owned 模式 | 使用 v-debounce:event="{ handler }",兼容模式仍保留 | | 权限支持应用级 Provider,缺失数据时拒绝 | 安装时配置 permission.getAuthData,或绑定中传 authData | | 拖拽改用 Pointer Events | 回调事件类型改为 PointerEvent;触摸设备不再需要独立适配 | | 长按回调统一为 onTrigger | 直接函数绑定仍可用,旧配置请改为 onTrigger | | 子路径导入正式公开 | 避免访问包内 src 或未声明的深层路径 | | Copy 的 messageInstance 标为 deprecated | 使用插件 notifyonSuccess/onError |

2.x 会更严格校验负延时、非法尺寸、阈值和网格配置;捕获 RangeError 可将配置错误接入应用监控。

开发验证

bun run type-check
bun run test
bun run build

测试覆盖权限恢复、事件防抖与清理、外部点击排除、复制与无障碍属性、插件注册以及 Loading 的安全 DOM 构造。

License

MIT © ChenYu