5.6.3 • Published 6 months ago

@cimom/vben-effects-hooks v5.6.3

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

@cimom/vben-effects-hooks

用于多个 app 公用的 hook,继承了 @cimom/vben-core-composables 的所有能力,并扩展了更多业务场景下的钩子函数。业务上有通用 hooks 可以放在这里。

安装

# 进入目标应用目录,例如 apps/xxxx-app
# cd apps/xxxx-app
pnpm add @cimom/vben-effects-hooks

可用钩子函数

useAppConfig - 应用配置钩子

用于获取应用的全局配置。

import { useAppConfig } from '@cimom/vben-effects-hooks';

// 在组件中使用
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);

console.log('API URL:', apiURL);

useContentMaximize - 内容区域最大化钩子

用于控制内容区域的最大化状态。

import { useContentMaximize } from '@cimom/vben-effects-hooks';

// 在组件中使用
const { isMaximized, toggleMaximize } = useContentMaximize();

// 切换最大化状态
function handleMaximizeClick() {
  toggleMaximize();
}

useDesignTokens - 设计令牌钩子

用于获取和使用设计系统的颜色、字体、间距等令牌。

import { useDesignTokens } from '@cimom/vben-effects-hooks';

// 在组件中使用
const {
  primaryColor,
  dangerColor,
  successColor,
  fontSizes,
  spacing,
  borderRadius,
} = useDesignTokens();

// 使用设计令牌
const buttonStyle = {
  backgroundColor: primaryColor.value,
  padding: `${spacing.value.sm} ${spacing.value.md}`,
  borderRadius: borderRadius.value.sm,
  fontSize: fontSizes.value.md,
};

useHoverToggle - 悬停切换钩子

用于处理元素悬停状态的钩子函数。

import { useHoverToggle } from '@cimom/vben-effects-hooks';

// 在组件中使用
const { isHovering, onMouseEnter, onMouseLeave } = useHoverToggle();

// 在模板中使用
// <div
//   @mouseenter="onMouseEnter"
//   @mouseleave="onMouseLeave"
//   :class="{ 'hover-class': isHovering }"
// >
//   悬停内容
// </div>

usePagination - 分页钩子

用于处理数组数据的分页。

import { ref } from 'vue';
import { usePagination } from '@cimom/vben-effects-hooks';

// 在组件中使用
const dataList = ref([
  /* 大量数据项... */
]);
const {
  paginationList, // 当前页数据
  total, // 总数据量
  setCurrentPage, // 设置当前页
  setPageSize, // 设置每页条数
} = usePagination(dataList, 10); // 10 是每页条数

// 切换页码
function handlePageChange(page: number) {
  setCurrentPage(page);
}

// 切换每页条数
function handlePageSizeChange(pageSize: number) {
  setPageSize(pageSize);
}

useRefresh - 刷新钩子

用于处理页面或组件的刷新逻辑。

import { useRefresh } from '@cimom/vben-effects-hooks';

// 在组件中使用
const { refreshFlag, refreshPage } = useRefresh();

// 监听刷新标志变化
watch(refreshFlag, () => {
  // 执行刷新逻辑
  fetchData();
});

// 触发刷新
function handleRefresh() {
  refreshPage();
}

useTabs - 标签页钩子

用于管理标签页的状态和操作。

import { useTabs } from '@cimom/vben-effects-hooks';

// 在组件中使用
const {
  tabs, // 标签页列表
  activeTab, // 当前激活的标签页
  addTab, // 添加标签页
  removeTab, // 移除标签页
  setActiveTab, // 设置激活的标签页
  refreshTab, // 刷新标签页
} = useTabs();

// 添加新标签页
function handleAddTab(tab) {
  addTab(tab);
}

// 关闭标签页
function handleCloseTab(tabKey) {
  removeTab(tabKey);
}

// 切换标签页
function handleSwitchTab(tabKey) {
  setActiveTab(tabKey);
}

useWatermark - 水印钩子

用于在页面上添加和管理水印。

import { useWatermark } from '@cimom/vben-effects-hooks';

// 在组件中使用
const { watermark, updateWatermark, destroyWatermark } = useWatermark();

// 初始化水印
onMounted(() => {
  updateWatermark({
    content: '机密文件 - 张三 2025-05-27',
    fontSize: '16px',
    globalAlpha: 0.15,
    rotate: 30,
  });
});

// 更新水印
function changeWatermark(text) {
  updateWatermark({
    content: text,
  });
}

// 移除水印
function removeWatermark() {
  destroyWatermark();
}

// 组件卸载时自动销毁水印
// onUnmounted(() => {
//   destroyWatermark();
// });

继承的核心钩子函数

该包继承了 @cimom/vben-core-composables 中的所有钩子函数,以下是一些常用的核心钩子:

useIsMobile - 移动设备检测

import { useIsMobile } from '@cimom/vben-effects-hooks';

// 在组件中使用
const { isMobile } = useIsMobile();

// 根据设备类型调整布局
const layoutClass = computed(() => {
  return isMobile.value ? 'mobile-layout' : 'desktop-layout';
});

useLayoutStyle - 布局样式钩子

import { useLayoutStyle } from '@cimom/vben-effects-hooks';

// 在组件中使用
const { layoutStyle } = useLayoutStyle({
  width: 1200,
  height: 800,
  top: 50,
  left: 50,
});

usePriorityValue - 优先级值钩子

import { usePriorityValue } from '@cimom/vben-effects-hooks';

// 在组件中使用
const propValue = ref('prop value');
const localValue = ref('local value');
const defaultValue = 'default value';

// 按优先级选择值:propValue > localValue > defaultValue
const value = usePriorityValue(propValue, localValue, defaultValue);

useNamespace - 命名空间钩子

import { useNamespace } from '@cimom/vben-effects-hooks';

// 在组件中使用
const ns = useNamespace('button');

// 生成带命名空间的类名
const classes = computed(() => [
  ns.b(), // 'vben-button'
  ns.m('primary'), // 'vben-button--primary'
  ns.e('label'), // 'vben-button__label'
  ns.em('label', 'bold'), // 'vben-button__label--bold'
]);

高级用法

组合多个钩子函数

import {
  useIsMobile,
  useDesignTokens,
  useWatermark,
} from '@cimom/vben-effects-hooks';

// 在组件中组合使用多个钩子
const { isMobile } = useIsMobile();
const { primaryColor } = useDesignTokens();
const { updateWatermark } = useWatermark();

// 根据设备类型和主题设置水印
watchEffect(() => {
  if (isMobile.value) {
    // 移动设备上的水印配置
    updateWatermark({
      content: '移动版',
      fontSize: '14px',
      globalAlpha: 0.1,
    });
  } else {
    // 桌面设备上的水印配置
    updateWatermark({
      content: '桌面版',
      fontSize: '18px',
      globalAlpha: 0.15,
      advancedStyle: {
        colorStops: [
          {
            color: primaryColor.value,
            offset: 0,
          },
          {
            color: primaryColor.value,
            offset: 1,
          },
        ],
        type: 'linear',
      },
    });
  }
});

创建自定义钩子函数

import { ref, computed } from 'vue';
import { useIsMobile, useDesignTokens } from '@cimom/vben-effects-hooks';

// 创建自定义钩子函数
export function useResponsiveUI() {
  const { isMobile } = useIsMobile();
  const { spacing, fontSizes } = useDesignTokens();

  // 响应式 UI 配置
  const config = computed(() => {
    if (isMobile.value) {
      return {
        fontSize: fontSizes.value.sm,
        padding: spacing.value.xs,
        columnCount: 1,
      };
    } else {
      return {
        fontSize: fontSizes.value.md,
        padding: spacing.value.md,
        columnCount: 3,
      };
    }
  });

  // 响应式类名
  const classes = computed(() => {
    return {
      'mobile-ui': isMobile.value,
      'desktop-ui': !isMobile.value,
    };
  });

  return {
    config,
    classes,
    isMobile,
  };
}

// 在组件中使用自定义钩子
// const { config, classes } = useResponsiveUI();

与其他包的集成

与 @cimom/vben-stores 集成

import { useUserStore } from '@cimom/vben-stores';
import { useWatermark } from '@cimom/vben-effects-hooks';

// 创建集成钩子
export function useUserWatermark() {
  const userStore = useUserStore();
  const { updateWatermark, destroyWatermark } = useWatermark();

  // 监听用户信息变化,更新水印
  watch(
    () => userStore.userInfo,
    (userInfo) => {
      if (userInfo?.username) {
        const now = new Date().toLocaleDateString();
        updateWatermark({
          content: `${userInfo.username} - ${now}`,
          globalAlpha: 0.15,
        });
      } else {
        destroyWatermark();
      }
    },
    { immediate: true },
  );

  return {
    updateWatermark,
    destroyWatermark,
  };
}

与 @cimom/vben-preferences 集成

import { usePreferences } from '@cimom/vben-preferences';
import { useDesignTokens } from '@cimom/vben-effects-hooks';

// 创建主题钩子
export function useThemeTokens() {
  const { preferences } = usePreferences();
  const designTokens = useDesignTokens();

  // 根据用户偏好设置返回对应的设计令牌
  const themeTokens = computed(() => {
    const isDark = preferences.theme === 'dark';

    return {
      backgroundColor: isDark
        ? designTokens.darkBackground.value
        : designTokens.lightBackground.value,
      textColor: isDark
        ? designTokens.darkTextColor.value
        : designTokens.lightTextColor.value,
      // 其他主题相关令牌...
    };
  });

  return themeTokens;
}

注意事项

  1. 钩子函数应该在组件的 setup 函数或 <script setup> 中调用,不应在普通函数中调用。
  2. 某些钩子函数(如 useWatermark)会在组件卸载时自动清理资源,无需手动处理。
  3. 使用 usePagination 时,如果源数据列表发生变化,分页状态会自动更新。
  4. 响应式钩子返回的大多数值都是 Vue 的响应式对象(Ref 或 ComputedRef),使用时需要通过 .value 访问实际值。

常见问题

钩子函数返回的值不是响应式的

确保正确使用了 .value 访问响应式对象的值:

// 错误用法
const { primaryColor } = useDesignTokens();
const style = { color: primaryColor }; // primaryColor 是 Ref,需要使用 .value

// 正确用法
const { primaryColor } = useDesignTokens();
const style = { color: primaryColor.value };

// 或者使用计算属性
const style = computed(() => ({ color: primaryColor.value }));

水印不显示或显示异常

确保在调用 updateWatermark 时提供了正确的参数,并且在组件挂载后调用:

import { onMounted } from 'vue';
import { useWatermark } from '@cimom/vben-effects-hooks';

const { updateWatermark } = useWatermark();

onMounted(() => {
  // 在组件挂载后初始化水印
  updateWatermark({
    content: '水印内容',
    fontSize: '16px',
    globalAlpha: 0.2, // 透明度 0-1
  });
});

分页钩子无法正确分页

确保提供给 usePagination 的数据列表是响应式的:

// 错误用法
const dataList = [
  /* 数据项... */
]; // 非响应式数组
const { paginationList } = usePagination(dataList, 10);

// 正确用法
const dataList = ref([
  /* 数据项... */
]); // 使用 ref 创建响应式数组
const { paginationList } = usePagination(dataList, 10);