wdy_custom_hooks

1.4.0 • Public • Published

基于 Vue3 的常用自定义指令钩子

v-focus:自动焦点

<template>
  <input v-focus />
</template>

v-resize:监听元素大小的变化

<template>
  <!-- 基本用法,默认200ms触发一次 -->
  <div v-resize="resizeCallback"></div>
  <!-- 支持自定义防抖时间 -->
  <div v-resize:300="resizeCallback"></div>
</template>

<script setup lang="ts">
// 元素大小的变化回调函数
const resizeCallback = (e) => {
  console.log("回调触发了:" + e);
};
</script>

v-copy:复制文本

<template>
  <button v-copy="copyConfig">点击复制</button>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { ElMessage } from "element-plus";

const copyConfig = ref({
  text: "Hello,World!", // 要复制的文本
  // 自定义复制成功的回调,可选,默认console.log("复制成功")
  success: () => {
    ElMessage.success("复制成功");
  },
  // 自定义复制失败的回调,可选,默认console.error("复制失败")
  error: (err: any) => {
    ElMessage.error("失败:" + err);
  },
});
</script>

v-scrollLoad:滚动加载更多

<template>
  <div style="height: 100vh; overflow: auto" v-scrollLoad="scrollConfig">
    <ul>
      <li
        v-for="item in items"
        :key="item"
        style="padding: 30px; font-size: 20px"
      >
        {{ item }}
      </li>
    </ul>
    <div
      v-if="loading"
      style="
        height: 50px;
        display: flex;
        justify-content: center;
        font-size: 20px;
      "
    >
      <el-icon><Loading /></el-icon>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { Loading } from "@element-plus/icons-vue";

const loading = ref(false);
const items = ref<string[]>([
  "Item 1",
  "Item 2",
  "Item 3",
  "Item 4",
  "Item 5",
  "Item 6",
  "Item 7",
  "Item 8",
  "Item 9",
  "Item 10",
]);

// 指令配置项
const scrollConfig = ref({
  distance: 100, // 距离底部的距离,可选,默认举例底部100px触发回调
  loadMoreFn: loadMore, // 回调函数
});

// 模拟请求,加载更多数据
async function loadMore() {
  if (loading.value) return;
  if (items.value.length >= 30) return; // 假设数据只有30条
  loading.value = true;
  console.log("触发了回调");
  // 模拟加载更多数据, 每次加载10条数据;
  for (let i = 0; i < 10; i++) {
    items.value.push("Item " + (items.value.length + 1));
  }
  loading.value = false;
}
</script>

v-imgLazy:图片懒加载

<template>
  <div>
    <img v-lazyLoad="imgConfig" alt="Image" />
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";

const imgConfig = ref({
  // 真实图片地址
  src: "https://q4.itc.cn/images01/20241017/4cf3fe55a9584eb0b2c111f9e0baabfd.jpeg",
  // 占位图地址,可选,没有默认的占位图
  placeholderSrc:
    "https://img.zcool.cn/community/01efbc5a1e6efda80120908dcb1567.gif",
  // 加载失败图地址,可选,没有默认的加载失败图
  errorSrc:
    "https://gss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/574e9258d109b3de93ad439cc9bf6c81800a4c37.jpg",
});
</script>

v-longPress:绑定长按事件

<template>
  <div>
    {{ count }}
    <el-button type="primary" v-longPress="longPressConfig"> 长按我 </el-button>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";

const count = ref(1);

const longPressConfig = ref({
  callback: () => {
    console.log("长按事件触发!");
    count.value++;
  }, // 长按事件触发的回调函数
  time: 2000, // 长按事件触发的时间,可选,默认 2000ms
});
</script>

v-waterMarker:页面水印

<template>
  <div v-waterMarker="waterMarkerConfig" style="width: 100%; height: 100vh;">
    <h1>我的标题</h1>
    <p>这是页面内容……</p>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";

const waterMarkerConfig = ref({
  text: "某某档案@123456789@qq.com", // 水印内容
  font: "16px Microsoft Yahei", // 字体样式,可选,默认 '16px Microsoft Yahei'
  color: "rgba(0, 0, 0, 0.1)", // 字体颜色,可选,默认 'rgba(0, 0, 0, 0.1)'
  rotate: -20, // 字体旋转角度,可选, 默认 -20
  labelGap: 50, // 水印之间的间距,可选, 默认 50
});
</script>

v-outsideClick:点击元素外部事件

<template>
  <div v-outsideClick="clickOutside" style="position: relative; margin: 30px">
    <button @click="visible = true">下拉菜单</button>
    <div
      v-if="visible"
      style="
        position: absolute;
        top: 30px;
        z-index: 99;
        background-color: #bfa;
        width: 150px;
        height: 200px;
        padding: 6px 10px;
        border: 1px solid #d9d9d9;
      "
    >
      <ul>
        <li>菜单项1</li>
        <li>菜单项2</li>
        <li>菜单项3</li>
      </ul>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
const visible = ref(false);

const clickOutside = () => {
  visible.value = false;
};
</script>

v-debounce:防抖指令

<template>
  <el-button type="primary" v-debounce:click="debounceConfig"
    >防抖测试{{ count }}</el-button
  >
</template>

<script setup lang="ts">
import { ref } from "vue";

const count = ref(0);

const debounceConfig = ref({
  callback: () => {
    // 点击事件触发的回调函数
    console.log("点击了按钮");
    count.value++;
  },
  delay: 500, // 点击事件触发的时间,可选,默认 300ms
});
</script>

v-throttle:节流指令

<template>
  <el-button type="primary" v-debounce:click="debounceConfig"
    >节流测试{{ count }}</el-button
  >
</template>

<script setup lang="ts">
import { ref } from "vue";

const count = ref(0);

const throttleConfig = ref({
  callback: () => {
    // 点击事件触发的回调函数
    console.log("点击了按钮");
    count.value++;
  },
  delay: 500, // 点击事件触发的时间,可选,默认 300ms
});
</script>

v-permission:权限按钮指令

<template>
  <div>
    <button v-permission:sys:user:add="permissions">添加用户</button>
    <button v-permission:[dynaimcAuth]="permissions">删除角色</button>
  </div>
</template>
<script setup>
import { ref, onMounted } from "vue";

// 模拟用户权限列表,实际项目中可以从 Vuex 或 Pinia或请求 中获取
const permissions = ref(["sys:user:add", "sys:role:add", "sys:role:delete"]);

// 动态按钮权限
const dynaimcAuth = ref("sys:user:delete");

onMounted(() => {
  setTimeout(() => {
    dynaimcAuth.value = "sys:role:delete"; // 模拟按钮权限变化
    permissions.value = ["sys:role:add", "sys:role:delete"]; // 模拟用户权限列表变化
  }, 3000);
});

Package Sidebar

Install

npm i wdy_custom_hooks

Weekly Downloads

54

Version

1.4.0

License

ISC

Unpacked Size

28.1 kB

Total Files

5

Last publish

Collaborators

  • wangdongyou