ソースを参照

feat(config-provider): 覆盖nut-icon属性 (#2016)

thx125 2 年 前
コミット
1506f6487e

+ 28 - 2
src/packages/__VUE/configprovider/__tests__/configprovider.spec.ts

@@ -1,7 +1,16 @@
-import { mount } from '@vue/test-utils';
+import { config, mount } from '@vue/test-utils';
 import ConfigProvider from '../index.vue';
+import NutIcon from '../../icon/index.vue';
+import { h } from 'vue';
 
-test('prop theme & tag', async () => {
+// 所有的测试用例之前执行一次
+beforeAll(() => {
+  config.global.components = {
+    NutIcon
+  };
+});
+
+test('ConfigProvider prop: theme & tag', async () => {
   const wrapper = mount(ConfigProvider, {
     props: {
       theme: 'dark',
@@ -11,3 +20,20 @@ test('prop theme & tag', async () => {
   const html = expect(wrapper.html());
   expect(wrapper.find<HTMLElement>('.nut-theme-dark'));
 });
+
+test('ConfigProvider prop: fontClassName & classPrefix', async () => {
+  const wrapper = mount(ConfigProvider, {
+    props: {
+      theme: 'dark',
+      tag: 'div',
+      fontClassName: 'iconfont',
+      classPrefix: 'icon'
+    },
+    slots: {
+      default: h(NutIcon, {
+        name: 'close'
+      })
+    }
+  });
+  expect(wrapper.find<HTMLElement>('.iconfont.icon-close'));
+});

+ 42 - 3
src/packages/__VUE/configprovider/common.ts

@@ -1,17 +1,56 @@
-import { h, PropType } from 'vue';
+import { isObject } from '@/packages/utils/util';
+import { h, PropType, VNode } from 'vue';
+
 export const component = {
   props: {
     theme: { type: String, default: '' },
-    tag: { type: String as PropType<keyof HTMLElementTagNameMap>, default: 'div' }
+    tag: { type: String as PropType<keyof HTMLElementTagNameMap>, default: 'div' },
+    classPrefix: { type: String, default: 'nut-icon' },
+    fontClassName: { type: String, default: 'nutui-iconfont' }
   },
   setup(props: any, { slots }: any) {
+    // 覆盖默认插槽的属性
+    const overDefaultSlotProp = (vnodes: VNode[]) => {
+      if (!vnodes) {
+        return;
+      }
+      vnodes.forEach((vnode: VNode) => {
+        let type = vnode.type;
+        type = (type as any).name || type;
+        if (!vnode.props) {
+          vnode.props = {};
+        }
+        if (type == 'nut-icon') {
+          vnode.props['fontClassName'] = vnode.props['font-class-name'] || props.fontClassName;
+          vnode.props['classPrefix'] = vnode.props['class-prefix'] || props.classPrefix;
+        }
+
+        if (Array.isArray(vnode.children) && vnode.children?.length) {
+          overDefaultSlotProp(vnode.children as VNode[]);
+        } else if (isObject(vnode.children) && Object.keys(vnode.children)) {
+          let children = vnode.children as any;
+          for (const key in children) {
+            if (key === '_') {
+              break;
+            }
+
+            const childrenVNode = children[key]?.();
+            overDefaultSlotProp(childrenVNode);
+            children[key] = () => childrenVNode;
+          }
+        }
+      });
+    };
+
     return () => {
+      const defaultSlots = slots.default?.();
+      overDefaultSlotProp(defaultSlots);
       return h(
         props.tag,
         {
           class: `nut-theme-${props.theme}`
         },
-        slots.default?.()
+        defaultSlots
       );
     };
   }

+ 6 - 4
src/packages/__VUE/configprovider/doc.en-US.md

@@ -60,10 +60,12 @@ Dark mode takes effect globally, making all NutUI components on the page dark.
 
 ### Props
 
-| Attribute | Description                                                          | Type   | Default |
-|-----------|----------------------------------------------------------------------|--------|---------|
-| theme     | Theme style, set to `dark` to enable dark mode, take effect globally | String | -       |
-| tag       | HTML Tag of root element                                             | String | div     |
+| Attribute       | Description                                                          | Type   | Default          |
+|-----------------|----------------------------------------------------------------------|--------|------------------|
+| theme           | Theme style, set to `dark` to enable dark mode, take effect globally | String | -                |
+| tag             | HTML Tag of root element                                             | String | div              |
+| font-class-name | Custom icon font base class name                                     | String | `nutui-iconfont` |
+| class-prefix    | Custom icon class name prefix for using custom icons                 | String | `nut-icon`       |
 
 
 ## Dark mode adaptation progress

+ 6 - 4
src/packages/__VUE/configprovider/doc.md

@@ -60,10 +60,12 @@ app.use(ConfigProvider);
 
 ### Props
 
-| 参数  | 说明                                             | 类型   | 默认值 |
-|-------|--------------------------------------------------|--------|--------|
-| theme | 主题风格,设置为 `dark` 来开启深色模式,全局生效 | String | -      |
-| tag   | 根节点对应的 HTML 标签名                         | String | div    |
+| 参数             | 说明                                             | 类型   | 默认值            |
+|-----------------|-------------------------------------------------|--------|------------------|
+| theme           | 主题风格,设置为 `dark` 来开启深色模式,全局生效       | String | -                |
+| tag             | 根节点对应的 HTML 标签名                           | String | div              |
+| font-class-name | 自定义 icon 字体基础类名                           | String | `nutui-iconfont` |
+| class-prefix    | 自定义 icon 类名前缀,用于使用自定义图标              | String | `nut-icon`       |
 
 
 ### 暗黑模式适配进度

+ 4 - 2
src/sites/mobile-taro/vue/src/basic/pages/configprovider/index.vue

@@ -1,13 +1,15 @@
 <template>
   <div class="demo">
     <h2>基础使用</h2>
-    <nut-config-provider :theme="theme">
+    <nut-config-provider :theme="theme" font-class-name="iconfont" class-prefix="icon">
       <nut-cell title="切换暗黑">
         <template v-slot:link>
           <nut-switch v-model="switchChecked" @change="switchChange" />
         </template>
       </nut-cell>
-      <nut-cell title="我是标题" sub-title="副标题描述" desc="描述文字"></nut-cell>
+      <nut-cell title="我是标题" sub-title="副标题描述" desc="描述文字"> </nut-cell>
+      <nut-icon name="dongdong" class-prefix="icon">1</nut-icon>
+      <nut-icon font-class-name="nutui-iconfont" class-prefix="nut-icon" name="dongdong"></nut-icon>
 
       <nut-form>
         <nut-form-item label="开关">