fix(icon): solve the style problem caused by multiple identical ids o… (#2086)

* fix(icon): solve the style problem caused by multiple identical ids of gradient svg

* fix: fix vue2 icon error

* fix: fix reviews
This commit is contained in:
ajaxzheng 2024-09-09 19:42:14 +08:00 committed by GitHub
parent 2dcbfdbb82
commit 8b743d0c39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 139 additions and 3 deletions

View File

@ -70,7 +70,22 @@ export default defineConfig((config) => {
include: [/\.vue$/, /\.md$/] include: [/\.vue$/, /\.md$/]
}), }),
vueJsx(), vueJsx(),
vue3SvgPlugin(), vue3SvgPlugin({
defaultImport: 'component',
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false
}
}
},
'prefixIds'
]
}
}),
importPlugin([ importPlugin([
{ {
libraryName: '@opentiny/vue' libraryName: '@opentiny/vue'

View File

@ -29,7 +29,21 @@ export default defineConfig((config) => {
include: [/\.vue$/, /\.md$/] include: [/\.vue$/, /\.md$/]
}), }),
scriptSetupPlugin(), scriptSetupPlugin(),
vue2SvgPlugin(), vue2SvgPlugin({
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false
}
}
},
'prefixIds'
]
}
}),
importPlugin({ importPlugin({
options: [ options: [
{ {

View File

@ -36,7 +36,22 @@ export default defineConfig((config) => {
include: [/\.vue$/, /\.md$/] include: [/\.vue$/, /\.md$/]
}), }),
vue3JsxPlugin(), vue3JsxPlugin(),
vue3SvgPlugin(), vue3SvgPlugin({
defaultImport: 'component',
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false
}
}
},
'prefixIds'
]
}
}),
importPlugin([ importPlugin([
{ {
libraryName: '@opentiny/vue' libraryName: '@opentiny/vue'

View File

@ -80,9 +80,15 @@
"type": "component", "type": "component",
"exclude": false, "exclude": false,
"mode": [ "mode": [
"mobile-first",
"pc" "pc"
] ]
}, },
"AnchorMobileFirst": {
"path": "vue/src/anchor/src/mobile-first.vue",
"type": "template",
"exclude": false
},
"AnchorPc": { "AnchorPc": {
"path": "vue/src/anchor/src/pc.vue", "path": "vue/src/anchor/src/pc.vue",
"type": "template", "type": "template",
@ -1464,6 +1470,11 @@
"type": "template", "type": "template",
"exclude": false "exclude": false
}, },
"Hooks": {
"path": "vue-hooks/index.ts",
"type": "module",
"exclude": false
},
"Hrapprover": { "Hrapprover": {
"path": "vue/src/hrapprover/index.ts", "path": "vue/src/hrapprover/index.ts",
"type": "component", "type": "component",

View File

@ -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++
}

View File

@ -25,6 +25,7 @@ import '@opentiny/vue-theme/base/index.less'
import { defineComponent, isVue2, isVue3 } from './adapter' import { defineComponent, isVue2, isVue3 } from './adapter'
import { useBreakpoint } from './breakpoint' import { useBreakpoint } from './breakpoint'
import { useDefer } from './usedefer' import { useDefer } from './usedefer'
import { GRADIENT_ICONS_LIST, generateIcon } from './generateIcon'
import { useInstanceSlots as createUseInstanceSlots } from '@opentiny/vue-renderless/common/deps/useInstanceSlots' import { useInstanceSlots as createUseInstanceSlots } from '@opentiny/vue-renderless/common/deps/useInstanceSlots'
import { useRelation as createUseRelation } from '@opentiny/vue-renderless/common/deps/useRelation' 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 extend.nativeOn = context.listeners
} }
// 解决多个相同的渐变图标svg中有相同id时在displaynone情况下导致的样式异常问题
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({ return renderComponent({
component, component,
props: mergeProps, props: mergeProps,