From 1506f6487e97f274b8ab9e83b1a624a488ae5603 Mon Sep 17 00:00:00 2001 From: thx125 <574959367@qq.com> Date: Tue, 17 Jan 2023 17:40:04 +0800 Subject: [PATCH] =?UTF-8?q?feat(config-provider):=20=E8=A6=86=E7=9B=96nut-?= =?UTF-8?q?icon=E5=B1=9E=E6=80=A7=20(#2016)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/configprovider.spec.ts | 30 ++++++++++++- src/packages/__VUE/configprovider/common.ts | 45 +++++++++++++++++-- .../__VUE/configprovider/doc.en-US.md | 10 +++-- src/packages/__VUE/configprovider/doc.md | 10 +++-- .../src/basic/pages/configprovider/index.vue | 6 ++- 5 files changed, 86 insertions(+), 15 deletions(-) diff --git a/src/packages/__VUE/configprovider/__tests__/configprovider.spec.ts b/src/packages/__VUE/configprovider/__tests__/configprovider.spec.ts index 57c57638f..10530581e 100644 --- a/src/packages/__VUE/configprovider/__tests__/configprovider.spec.ts +++ b/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('.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('.iconfont.icon-close')); +}); diff --git a/src/packages/__VUE/configprovider/common.ts b/src/packages/__VUE/configprovider/common.ts index 7ca1e9534..89d3d6a8c 100644 --- a/src/packages/__VUE/configprovider/common.ts +++ b/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, default: 'div' } + tag: { type: String as PropType, 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 ); }; } diff --git a/src/packages/__VUE/configprovider/doc.en-US.md b/src/packages/__VUE/configprovider/doc.en-US.md index a6c00dc79..f88449547 100644 --- a/src/packages/__VUE/configprovider/doc.en-US.md +++ b/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 diff --git a/src/packages/__VUE/configprovider/doc.md b/src/packages/__VUE/configprovider/doc.md index 2d858e03a..5aca6b9e2 100644 --- a/src/packages/__VUE/configprovider/doc.md +++ b/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` | ### 暗黑模式适配进度 diff --git a/src/sites/mobile-taro/vue/src/basic/pages/configprovider/index.vue b/src/sites/mobile-taro/vue/src/basic/pages/configprovider/index.vue index ffbc5eab8..1408a2ca3 100644 --- a/src/sites/mobile-taro/vue/src/basic/pages/configprovider/index.vue +++ b/src/sites/mobile-taro/vue/src/basic/pages/configprovider/index.vue @@ -1,13 +1,15 @@