首先我的路由菜单是后端请求返回的,如下:
在这里就不贴详细的路由菜单了,
bug就是:打包放到服务器后,红框部分是没有的,也就是el-menu没渲染
<template>
<div :class="{ 'has-logo': showLogo }">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu active-text-color="f4f4f5" background-color="#304156" text-color="#bfcbd9" :default-active="now_path"
mode="vertical" router :default-openeds="default_open">
<div v-for="(item, index) in permission_routes" :key="index">
<el-menu-item v-if="item.children.length == 0 && !item.hidden" :index="item.path" :route="item.path">
<svg-icon :name="item.icon" class="icon-svg" />
<span> {{ item.title }}</span>
</el-menu-item>
<el-sub-menu :index="index" v-else>
<template #title>
<svg-icon :name="item.icon" class="icon-svg" />
<span> {{ item.title }}</span>
</template>
<template v-for="(chItem, i) in item.children" :key="i">
<el-menu-item v-if="!chItem.hidden" :index="chItem.path" :route="chItem.path">
<svg-icon :name="item.icon" class="icon-svg" />
<span> {{ chItem.title }}</span>
</el-menu-item>
</template>
</el-sub-menu>
</div>
</el-menu>
</el-scrollbar>
</div>
</template>
<script setup>
import Logo from './Logo.vue'
import '/src/styles/variables.scss'
import { ref, reactive, computed,} from 'vue'
import { useRoute, } from 'vue-router'
const $route = useRoute()
const now_path = $route.path
import { useStore } from 'vuex'
const $store = useStore()
const permission_routes = ref(computed(() => $store.getters.permission_routes))
const sidebar = reactive(computed(() => $store.getters.sidebar))
const showLogo = reactive(true)
const isCollapse = !sidebar.opened
const default_open = ref([1, 2, 3, 4, 5, 6, 7, 8, 9])//默认打开菜单
</script>
然后经过我一段时间折腾后,终于找到bug所在
原因是:因为vite是热加载,我使用的这部分比较慢👇
const permission_routes = ref(computed(() => $store.getters.permission_routes))
(具体原理说的不够专业,但大概意思就是permission_routes数据👆 跟不上页面dom👇)
<el-menu active-text-color="f4f4f5" background-color="#304156" text-color="#bfcbd9" :default-active="now_path"
mode="vertical" router :default-openeds="default_open">
<div v-for="(item, index) in permission_routes" :key="index">
<el-menu-item v-if="item.children.length == 0 && !item.hidden" :index="item.path" :route="item.path">
.....
当permission_routes数据为空,item后的数据就会报错👆
然后解决办法👇
重点就是:isMounted部分
<template>
<div :class="{ 'has-logo': showLogo }" v-if="isMounted">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu active-text-color="f4f4f5" background-color="#304156" text-color="#bfcbd9" :default-active="now_path"
mode="vertical" router :default-openeds="default_open">
<div v-for="(item, index) in permission_routes" :key="index">
<el-menu-item v-if="item.children.length == 0 && !item.hidden" :index="item.path" :route="item.path">
<svg-icon :name="item.icon" class="icon-svg" />
<span> {{ item.title }}</span>
</el-menu-item>
<el-sub-menu :index="index" v-else>
<template #title>
<svg-icon :name="item.icon" class="icon-svg" />
<span> {{ item.title }}</span>
</template>
<template v-for="(chItem, i) in item.children" :key="i">
<el-menu-item v-if="!chItem.hidden" :index="chItem.path" :route="chItem.path">
<svg-icon :name="item.icon" class="icon-svg" />
<span> {{ chItem.title }}</span>
</el-menu-item>
</template>
</el-sub-menu>
</div>
</el-menu>
</el-scrollbar>
</div>
</template>
<script setup>
import Logo from './Logo.vue'
import '/src/styles/variables.scss'
import { ref, reactive, computed, onMounted } from 'vue'
import { useRoute, } from 'vue-router'
const $route = useRoute()
const now_path = $route.path
import { useStore } from 'vuex'
const $store = useStore()
const isMounted = ref(false)//修复vite打包后热加载
onMounted(() => {
isMounted.value = true
})
const permission_routes = ref(computed(() => {
if (isMounted.value) {
return $store.getters.permission_routes
}
}))
const sidebar = reactive(computed(() => $store.getters.sidebar))
const showLogo = reactive(true)
const isCollapse = !sidebar.opened
const default_open = ref([1, 2, 3, 4, 5, 6, 7, 8, 9])//默认打开菜单
</script>
简易原理版本👇
<template>
<div v-if="isMounted">
{{ expensiveComputed }}
</div>
</template>
<script>
import { computed, ref } from 'vue';
export default {
setup() {
const isMounted = ref(false);
const expensiveComputed = computed(() => {
// 计算过程
return $store.getters.someExpensiveGetter;
});
onMounted(() => {
isMounted.value = true;
});
return { isMounted, expensiveComputed };
}
};
</script>
版本2
<template>
<div v-if="isMounted">
{{ expensiveComputed }}
</div>
</template>
<script setup>
import { computed, ref,onMounted } from 'vue';
const isMounted = ref(false);
onMounted(() => {
isMounted.value = true;
});
const expensiveComputed = computed(() => {
if (isMounted.value) {
// 计算过程
return $store.getters.someExpensiveGetter;
}
});
</script>
最后贴个ai讲解: