diff --git a/examples/sites/vite.config.ts b/examples/sites/vite.config.ts index 5b04ab836f..72576ba399 100644 --- a/examples/sites/vite.config.ts +++ b/examples/sites/vite.config.ts @@ -46,7 +46,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 29f98446d7..71e9d60f64 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 2b53755037..5587ee3fb6 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 0e874982fd..ff1672c42b 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 0000000000..1e497f293c --- /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 89791c876c..e4edc64a59 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,