From 8b743d0c3991045f6f2bc9914e622d7c07726dc1 Mon Sep 17 00:00:00 2001 From: ajaxzheng <894103554@qq.com> Date: Mon, 9 Sep 2024 19:42:14 +0800 Subject: [PATCH] =?UTF-8?q?fix(icon):=20solve=20the=20style=20problem=20ca?= =?UTF-8?q?used=20by=20multiple=20identical=20ids=20o=E2=80=A6=20(#2086)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(icon): solve the style problem caused by multiple identical ids of gradient svg * fix: fix vue2 icon error * fix: fix reviews --- examples/sites/vite.config.ts | 17 ++++++- examples/vue2/vite.config.ts | 16 +++++- examples/vue3/vite.config.ts | 17 ++++++- packages/modules.json | 11 ++++ packages/vue-common/src/generateIcon.ts | 68 +++++++++++++++++++++++++ packages/vue-common/src/index.ts | 13 +++++ 6 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 packages/vue-common/src/generateIcon.ts diff --git a/examples/sites/vite.config.ts b/examples/sites/vite.config.ts index 42d610b5d..469fb28e0 100644 --- a/examples/sites/vite.config.ts +++ b/examples/sites/vite.config.ts @@ -70,7 +70,22 @@ export default defineConfig((config) => { include: [/\.vue$/, /\.md$/] }), vueJsx(), - vue3SvgPlugin(), + vue3SvgPlugin({ + defaultImport: 'component', + svgoConfig: { + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + removeViewBox: false + } + } + }, + 'prefixIds' + ] + } + }), importPlugin([ { libraryName: '@opentiny/vue' diff --git a/examples/vue2/vite.config.ts b/examples/vue2/vite.config.ts index 29f98446d..71e9d60f6 100644 --- a/examples/vue2/vite.config.ts +++ b/examples/vue2/vite.config.ts @@ -29,7 +29,21 @@ export default defineConfig((config) => { include: [/\.vue$/, /\.md$/] }), scriptSetupPlugin(), - vue2SvgPlugin(), + vue2SvgPlugin({ + svgoConfig: { + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + removeViewBox: false + } + } + }, + 'prefixIds' + ] + } + }), importPlugin({ options: [ { diff --git a/examples/vue3/vite.config.ts b/examples/vue3/vite.config.ts index 2b5375503..5587ee3fb 100644 --- a/examples/vue3/vite.config.ts +++ b/examples/vue3/vite.config.ts @@ -36,7 +36,22 @@ export default defineConfig((config) => { include: [/\.vue$/, /\.md$/] }), vue3JsxPlugin(), - vue3SvgPlugin(), + vue3SvgPlugin({ + defaultImport: 'component', + svgoConfig: { + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + removeViewBox: false + } + } + }, + 'prefixIds' + ] + } + }), importPlugin([ { libraryName: '@opentiny/vue' diff --git a/packages/modules.json b/packages/modules.json index 0e874982f..ff1672c42 100644 --- a/packages/modules.json +++ b/packages/modules.json @@ -80,9 +80,15 @@ "type": "component", "exclude": false, "mode": [ + "mobile-first", "pc" ] }, + "AnchorMobileFirst": { + "path": "vue/src/anchor/src/mobile-first.vue", + "type": "template", + "exclude": false + }, "AnchorPc": { "path": "vue/src/anchor/src/pc.vue", "type": "template", @@ -1464,6 +1470,11 @@ "type": "template", "exclude": false }, + "Hooks": { + "path": "vue-hooks/index.ts", + "type": "module", + "exclude": false + }, "Hrapprover": { "path": "vue/src/hrapprover/index.ts", "type": "component", diff --git a/packages/vue-common/src/generateIcon.ts b/packages/vue-common/src/generateIcon.ts new file mode 100644 index 000000000..1e497f293 --- /dev/null +++ b/packages/vue-common/src/generateIcon.ts @@ -0,0 +1,68 @@ +import { isVue2 } from './adapter' + +export const GRADIENT_ICONS_LIST = ['IconLoadingShadow', 'IconNoData'] +let uniqueId = 0 + +const generateId = (vnode, idMaps) => { + if (isVue2) { + if (vnode.data?.attrs?.id) { + const newId = `${vnode.data.attrs.id}${uniqueId}` + idMaps[vnode.data.attrs.id] = newId + vnode.data.attrs.id = newId + } + } else { + if (vnode.props?.id) { + const newId = `${vnode.props.id}${uniqueId}` + idMaps[vnode.props.id] = newId + vnode.props.id = newId + } + } + + if (vnode?.children) { + vnode.children.forEach((item) => { + generateId(item, idMaps) + }) + } +} + +const generateUrl = (vnode, idMaps) => { + const checkList = ['fill', 'mask', 'filter'] + + checkList.forEach((item) => { + if (isVue2) { + if (vnode.data?.attrs?.[item]?.includes('url(#')) { + const oldId = vnode.data.attrs[item].replace('url(#', '').replace(')', '') + const newId = idMaps[oldId] + if (newId) { + vnode.data.attrs[item] = `url(#${newId})` + } + } + } else { + if (vnode.props?.[item]?.includes('url(#')) { + const oldId = vnode.props[item].replace('url(#', '').replace(')', '') + const newId = idMaps[oldId] + if (newId) { + vnode.props[item] = `url(#${newId})` + } + } + } + }) + + if (vnode.children) { + vnode.children.forEach((item) => { + generateUrl(item, idMaps) + }) + } +} + +export const generateIcon = (vnode) => { + if (!vnode) { + return + } + // 映射老的id和新id的哈希表 + const idMaps = {} + + generateId(vnode, idMaps) + generateUrl(vnode, idMaps) + uniqueId++ +} diff --git a/packages/vue-common/src/index.ts b/packages/vue-common/src/index.ts index 89791c876..e4edc64a5 100644 --- a/packages/vue-common/src/index.ts +++ b/packages/vue-common/src/index.ts @@ -25,6 +25,7 @@ import '@opentiny/vue-theme/base/index.less' import { defineComponent, isVue2, isVue3 } from './adapter' import { useBreakpoint } from './breakpoint' import { useDefer } from './usedefer' +import { GRADIENT_ICONS_LIST, generateIcon } from './generateIcon' import { useInstanceSlots as createUseInstanceSlots } from '@opentiny/vue-renderless/common/deps/useInstanceSlots' import { useRelation as createUseRelation } from '@opentiny/vue-renderless/common/deps/useRelation' @@ -282,6 +283,18 @@ export function svg({ name = 'Icon', component }) { extend.nativeOn = context.listeners } + // 解决多个相同的渐变图标svg中有相同id时,在display:none,情况下导致的样式异常问题 + if (GRADIENT_ICONS_LIST.includes(name)) { + const render = component.render + component.render = function (...args) { + // 指向正确的this对象,保证vue2运行正常 + const newRender = render.bind(this) + const vnode = newRender(args) + generateIcon(vnode) + return vnode + } + } + return renderComponent({ component, props: mergeProps,