修复图标引起的卡顿问题

This commit is contained in:
xiangheng
2023-11-30 14:21:48 +08:00
parent 7cc7e12b35
commit ba8b56f68c
12 changed files with 100 additions and 45 deletions

View File

@@ -35,9 +35,9 @@
"vuedraggable": "^4.1.0" "vuedraggable": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.5.1", "@rushstack/eslint-patch": "^1.6.0",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/node": "^20.9.2", "@types/node": "^20.10.1",
"@types/nprogress": "^0.2.3", "@types/nprogress": "^0.2.3",
"@vitejs/plugin-vue": "^4.5.0", "@vitejs/plugin-vue": "^4.5.0",
"@vitejs/plugin-vue-jsx": "^3.1.0", "@vitejs/plugin-vue-jsx": "^3.1.0",
@@ -46,7 +46,7 @@
"@vue/tsconfig": "^0.4.0", "@vue/tsconfig": "^0.4.0",
"autoprefixer": "^10.4.16", "autoprefixer": "^10.4.16",
"eslint": "^8.54.0", "eslint": "^8.54.0",
"eslint-plugin-vue": "^9.18.1", "eslint-plugin-vue": "^9.19.0",
"execa": "^8.0.1", "execa": "^8.0.1",
"fs-extra": "^11.2.0", "fs-extra": "^11.2.0",
"postcss": "^8.4.31", "postcss": "^8.4.31",
@@ -55,12 +55,12 @@
"sass": "^1.69.5", "sass": "^1.69.5",
"tailwindcss": "^3.3.5", "tailwindcss": "^3.3.5",
"typescript": "~5.3.2", "typescript": "~5.3.2",
"unplugin-auto-import": "^0.11.1", "unplugin-auto-import": "^0.17.1",
"unplugin-vue-components": "^0.25.2", "unplugin-vue-components": "^0.25.2",
"vite": "^4.5.0", "vite": "^4.5.0",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-style-import": "^2.0.0", "vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1", "vite-plugin-svg-icons": "^2.0.1",
"vue-tsc": "^1.8.22" "vue-tsc": "^1.8.24"
} }
} }

View File

@@ -1,10 +1,33 @@
<template>
<span style="display: inline-block; line-height: 1">
<span
v-if="isElIcon"
class="svg-icon-container"
:style="{ height: size ? size + 'px' : 'auto', color: color }"
>
<!-- <ElIcon v-if="isElIcon" :size="size" :color="color"> -->
<component :is="name" style="width: 1em; height: 1em"></component>
<!-- </ElIcon> -->
</span>
<ISvgIcon
v-if="isLocalIcon"
class="local-icon"
:size="size"
:color="color"
:name="name"
></ISvgIcon>
</span>
</template>
<script lang="ts"> <script lang="ts">
import { createVNode } from 'vue' // import { ElIcon } from 'element-plus'
import { ElIcon } from 'element-plus'
import { EL_ICON_PREFIX, LOCAL_ICON_PREFIX } from './index' import { EL_ICON_PREFIX, LOCAL_ICON_PREFIX } from './index'
import svgIcon from './svg-icon.vue' import ISvgIcon from './svg-icon.vue'
export default defineComponent({ export default defineComponent({
name: 'Icon', name: 'Icon',
components: {
// ElIcon,
ISvgIcon
},
props: { props: {
name: { name: {
type: String, type: String,
@@ -20,30 +43,34 @@ export default defineComponent({
} }
}, },
setup(props) { setup(props) {
if (props.name.indexOf(EL_ICON_PREFIX) === 0) { // const isElIcon = ref(false)
// el-icon const isLocalIcon = computed(() => {
return () => return props.name.indexOf(LOCAL_ICON_PREFIX) === 0
createVNode( })
ElIcon,
{ const isElIcon = computed(() => {
size: props.size, return props.name.indexOf(EL_ICON_PREFIX) === 0
color: props.color })
},
() => [createVNode(resolveComponent(props.name.replace(EL_ICON_PREFIX, '')))] return {
) isElIcon,
isLocalIcon
} }
if (props.name.indexOf(LOCAL_ICON_PREFIX) === 0) {
// 本地icon
return () =>
h(
'i',
{
class: ['local-icon']
},
createVNode(svgIcon, { ...props })
)
}
return () => {}
} }
}) })
</script> </script>
<style>
.svg-icon-container {
display: inline-block;
line-height: 1;
overflow: hidden;
/* vertical-align: middle; */
/* height: auto; */
/* width: 1em;
*/
}
.local-icon {
display: inline-block;
/* margin: 0 8px; */
}
</style>

View File

@@ -9,6 +9,7 @@ import { addUnit } from '@/utils/util'
import type { CSSProperties } from 'vue' import type { CSSProperties } from 'vue'
export default defineComponent({ export default defineComponent({
name: 'SvgIcon',
props: { props: {
name: { name: {
type: String, type: String,

View File

@@ -6,6 +6,8 @@ import 'element-plus/es/components/dialog/style/css'
export default (app: App<Element>) => { export default (app: App<Element>) => {
// 全局注册ElementPlus图标 // 全局注册ElementPlus图标
for (const [key, component] of Object.entries(ElementPlusIcons)) { for (const [key, component] of Object.entries(ElementPlusIcons)) {
app.component(key, component) // app.component(key, component)
app.component('el-icon-' + key, component)
} }
} }

View File

@@ -39,6 +39,9 @@ import Setting from '../setting/index.vue'
import MultipleTabs from './multiple-tabs.vue' import MultipleTabs from './multiple-tabs.vue'
import useSettingStore from '@/stores/modules/setting' import useSettingStore from '@/stores/modules/setting'
defineOptions({
name: 'LayoutHeader'
})
const appStore = useAppStore() const appStore = useAppStore()
const isMobile = computed(() => appStore.isMobile) const isMobile = computed(() => appStore.isMobile)
const settingStore = useSettingStore() const settingStore = useSettingStore()

View File

@@ -16,6 +16,10 @@
import useAppStore from '@/stores/modules/app' import useAppStore from '@/stores/modules/app'
import useTabsStore from '@/stores/modules/multipleTabs' import useTabsStore from '@/stores/modules/multipleTabs'
import useSettingStore from '@/stores/modules/setting' import useSettingStore from '@/stores/modules/setting'
defineOptions({
name: 'LayoutMain'
})
const appStore = useAppStore() const appStore = useAppStore()
const tabsStore = useTabsStore() const tabsStore = useTabsStore()
const settingStore = useSettingStore() const settingStore = useSettingStore()

View File

@@ -7,9 +7,9 @@
title="主题设置" title="主题设置"
:with-header="false" :with-header="false"
> >
<side /> <Side />
</el-drawer> </el-drawer>
<side v-show="!isMobile" /> <Side v-show="!isMobile" />
</aside> </aside>
</template> </template>
@@ -17,7 +17,9 @@
import Side from './side.vue' import Side from './side.vue'
import useAppStore from '@/stores/modules/app' import useAppStore from '@/stores/modules/app'
import useSettingStore from '@/stores/modules/setting' import useSettingStore from '@/stores/modules/setting'
defineOptions({
name: 'LayoutSidebar'
})
const appStore = useAppStore() const appStore = useAppStore()
const settingStore = useSettingStore() const settingStore = useSettingStore()
const isMobile = computed(() => appStore.isMobile) const isMobile = computed(() => appStore.isMobile)

View File

@@ -23,6 +23,9 @@
<script setup lang="ts"> <script setup lang="ts">
import useAppStore from '@/stores/modules/app' import useAppStore from '@/stores/modules/app'
import { ThemeEnum } from '@/enums/appEnums' import { ThemeEnum } from '@/enums/appEnums'
defineOptions({
name: 'SideLogo'
})
defineProps({ defineProps({
szie: { type: Number, default: 34 }, szie: { type: Number, default: 34 },
title: { type: String }, title: { type: String },

View File

@@ -2,7 +2,7 @@
<template v-if="!route.meta?.hidden"> <template v-if="!route.meta?.hidden">
<app-link v-if="!hasShowChild" :to="`${routePath}?${queryStr}`"> <app-link v-if="!hasShowChild" :to="`${routePath}?${queryStr}`">
<el-menu-item :index="routePath"> <el-menu-item :index="routePath">
<icon <Icon
class="menu-item-icon" class="menu-item-icon"
:size="16" :size="16"
v-if="routeMeta?.icon" v-if="routeMeta?.icon"
@@ -13,9 +13,11 @@
</template> </template>
</el-menu-item> </el-menu-item>
</app-link> </app-link>
<el-sub-menu v-else :index="routePath" :popper-class="popperClass"> <el-sub-menu v-else :index="routePath" :popper-class="props.popperClass">
<template #title> <template #title>
<icon <!-- {{ routeMeta }} -->
<Icon
class="menu-item-icon" class="menu-item-icon"
:size="16" :size="16"
v-if="routeMeta?.icon" v-if="routeMeta?.icon"
@@ -24,11 +26,11 @@
<span>{{ routeMeta?.title }}</span> <span>{{ routeMeta?.title }}</span>
</template> </template>
<menu-item <menu-item
v-for="item in route?.children" v-for="item in route?.children || []"
:key="resolvePath(item.path)" :key="resolvePath(item.path)"
:route="item" :route="item"
:route-path="resolvePath(item.path)" :route-path="resolvePath(item.path)"
:popper-class="popperClass" :popper-class="props.popperClass"
/> />
</el-sub-menu> </el-sub-menu>
</template> </template>
@@ -43,7 +45,9 @@ interface Props {
routePath: string routePath: string
popperClass: string popperClass: string
} }
defineOptions({
name: 'MenuItem'
})
const props = defineProps<Props>() const props = defineProps<Props>()
const hasShowChild = computed(() => { const hasShowChild = computed(() => {
@@ -52,7 +56,7 @@ const hasShowChild = computed(() => {
}) })
const routeMeta = computed(() => { const routeMeta = computed(() => {
return props.route.meta return props?.route?.meta
}) })
const resolvePath = (path: string) => { const resolvePath = (path: string) => {

View File

@@ -29,7 +29,9 @@
import type { PropType } from 'vue' import type { PropType } from 'vue'
import MenuItem from './menu-item.vue' import MenuItem from './menu-item.vue'
import type { RouteRecordRaw } from 'vue-router' import type { RouteRecordRaw } from 'vue-router'
defineOptions({
name: 'SideMenu'
})
const props = defineProps({ const props = defineProps({
routes: { routes: {
type: Object as PropType<RouteRecordRaw[]> type: Object as PropType<RouteRecordRaw[]>

View File

@@ -19,7 +19,9 @@ import useSettingStore from '@/stores/modules/setting'
import useUserStore from '@/stores/modules/user' import useUserStore from '@/stores/modules/user'
import SideLogo from './logo.vue' import SideLogo from './logo.vue'
import SideMenu from './menu.vue' import SideMenu from './menu.vue'
defineOptions({
name: 'Side'
})
const appStore = useAppStore() const appStore = useAppStore()
const isCollapsed = computed(() => { const isCollapsed = computed(() => {
if (appStore.isMobile) { if (appStore.isMobile) {

View File

@@ -86,11 +86,16 @@
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" /> <edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
</div> </div>
</template> </template>
<script lang="ts" setup name="post"> <script lang="ts" setup>
import { postDelete, postLists } from '@/api/org/post' import { postDelete, postLists } from '@/api/org/post'
import { usePaging } from '@/hooks/usePaging' import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback' import feedback from '@/utils/feedback'
import EditPopup from './edit.vue' import EditPopup from './edit.vue'
defineOptions({
name: 'post'
})
const editRef = shallowRef<InstanceType<typeof EditPopup>>() const editRef = shallowRef<InstanceType<typeof EditPopup>>()
const showEdit = ref(false) const showEdit = ref(false)
const queryParams = reactive({ const queryParams = reactive({