perf: perf layout

This commit is contained in:
xiaoxian521 2021-09-21 20:41:27 +08:00
parent 15e751dee8
commit fe6dfb9e3d
7 changed files with 292 additions and 357 deletions

View File

@ -21,6 +21,7 @@ const getBreadcrumb = (): void => {
matched = [
{
path: "/welcome",
parentPath: "/",
meta: { title: "message.hshome" }
} as unknown as RouteLocationMatched
].concat(matched);

View File

@ -1,3 +1,19 @@
<script setup lang="ts">
import { ref, unref, computed, getCurrentInstance } from "vue";
import { useSettingStoreHook } from "/@/store/modules/settings";
const keepAlive: Boolean = ref(
getCurrentInstance().appContext.config.globalProperties.$config?.keepAlive
);
const getCachedPageList = computed((): string[] => {
if (!unref(keepAlive)) {
return [];
}
return useSettingStoreHook().cachedPageList;
});
</script>
<template>
<section class="app-main">
<router-view>
@ -13,32 +29,6 @@
</section>
</template>
<script lang="ts">
import { ref, unref, computed, defineComponent, getCurrentInstance } from "vue";
import { useRoute } from "vue-router";
import { useSettingStoreHook } from "/@/store/modules/settings";
export default defineComponent({
name: "appMain",
setup() {
const keepAlive: Boolean = ref(
getCurrentInstance().appContext.config.globalProperties.$config?.keepAlive
);
const route = useRoute();
const key = computed(() => route.path);
const getCachedPageList = computed((): string[] => {
if (!unref(keepAlive)) {
return [];
}
return useSettingStoreHook().cachedPageList;
});
return { key, keepAlive, getCachedPageList };
}
});
</script>
<style scoped>
.app-main {
min-height: calc(100vh - 70px);

View File

@ -67,6 +67,7 @@ import { useI18n } from "vue-i18n";
let routerArrays: Array<object> = [
{
path: "/welcome",
parentPath: "/",
meta: {
title: "message.hshome",
icon: "el-icon-s-home",

View File

@ -1,3 +1,35 @@
<script setup lang="ts">
import { ref } from "vue";
import { useEventListener, onClickOutside } from "@vueuse/core";
import { emitter } from "/@/utils/mitt";
let show = ref(false);
const target = ref(null);
onClickOutside(target, () => {
show.value = false;
});
const addEventClick = (): void => {
useEventListener("click", closeSidebar);
};
const closeSidebar = (evt: any): void => {
const parent = evt.target.closest(".right-panel");
if (!parent) {
show.value = false;
window.removeEventListener("click", closeSidebar);
}
};
emitter.on("openPanel", () => {
show.value = true;
});
defineExpose({
addEventClick
});
</script>
<template>
<div :class="{ show: show }" class="right-panel-container">
<div class="right-panel-background" />
@ -14,47 +46,6 @@
</div>
</template>
<script lang="ts">
import { ref } from "vue";
import { useEventListener, onClickOutside } from "@vueuse/core";
import { emitter } from "/@/utils/mitt";
export default {
name: "panel",
setup() {
let show = ref(false);
const target = ref(null);
onClickOutside(target, () => {
show.value = false;
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
const addEventClick = (): void => {
useEventListener("click", closeSidebar);
};
const closeSidebar = (evt: any): void => {
const parent = evt.target.closest(".right-panel");
if (!parent) {
show.value = false;
window.removeEventListener("click", closeSidebar);
}
};
emitter.on("openPanel", () => {
show.value = true;
});
return {
show,
target
};
}
};
</script>
<style>
.showright-panel {
overflow: hidden;

View File

@ -1,3 +1,118 @@
<script setup lang="ts">
import panel from "../panel/index.vue";
import { useRouter } from "vue-router";
import { emitter } from "/@/utils/mitt";
import { templateRef } from "@vueuse/core";
import { reactive, ref, unref, useCssModule } from "vue";
import { storageLocal, storageSession } from "/@/utils/storage";
const router = useRouter();
const { isSelect } = useCssModule();
//
const markValue = ref(storageLocal.getItem("showModel") || "smart");
const logoVal = ref(storageLocal.getItem("logoVal") || "1");
const localOperate = (key: string, value?: any, model?: string): any => {
model && model === "set"
? storageLocal.setItem(key, value)
: storageLocal.getItem(key);
};
const settings = reactive({
greyVal: storageLocal.getItem("greyVal"),
weekVal: storageLocal.getItem("weekVal"),
tagsVal: storageLocal.getItem("tagsVal")
});
settings.greyVal === null
? localOperate("greyVal", false, "set")
: document.querySelector("html")?.setAttribute("class", "html-grey");
settings.weekVal === null
? localOperate("weekVal", false, "set")
: document.querySelector("html")?.setAttribute("class", "html-weakness");
function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
const targetEl = target || document.body;
let { className } = targetEl;
className = className.replace(clsName, "");
targetEl.className = flag ? `${className} ${clsName} ` : className;
}
//
const greyChange = ({ value }): void => {
toggleClass(settings.greyVal, "html-grey", document.querySelector("html"));
value
? localOperate("greyVal", true, "set")
: localOperate("greyVal", false, "set");
};
//
const weekChange = ({ value }): void => {
toggleClass(
settings.weekVal,
"html-weakness",
document.querySelector("html")
);
value
? localOperate("weekVal", true, "set")
: localOperate("weekVal", false, "set");
};
const tagsChange = () => {
let showVal = settings.tagsVal;
showVal
? storageLocal.setItem("tagsVal", true)
: storageLocal.setItem("tagsVal", false);
emitter.emit("tagViewsChange", showVal);
};
function onReset() {
storageLocal.clear();
storageSession.clear();
router.push("/login");
}
function onChange({ label }) {
storageLocal.setItem("showModel", label);
emitter.emit("tagViewsShowModel", label);
}
const firstTheme = templateRef<HTMLElement | null>("firstTheme", null);
const secondTheme = templateRef<HTMLElement | null>("secondTheme", null);
const dataTheme = ref(storageLocal.getItem("data-theme") || "dark");
if (dataTheme.value) {
storageLocal.setItem("data-theme", unref(dataTheme));
window.document.body.setAttribute("data-theme", unref(dataTheme));
}
// dark
function onDark() {
storageLocal.setItem("data-theme", "dark");
window.document.body.setAttribute("data-theme", "dark");
toggleClass(true, isSelect, unref(firstTheme));
toggleClass(false, isSelect, unref(secondTheme));
}
// light
function onLight() {
storageLocal.setItem("data-theme", "light");
window.document.body.setAttribute("data-theme", "light");
toggleClass(false, isSelect, unref(firstTheme));
toggleClass(true, isSelect, unref(secondTheme));
}
function logoChange() {
unref(logoVal) === "1"
? storageLocal.setItem("logoVal", "1")
: storageLocal.setItem("logoVal", "-1");
emitter.emit("logoChange", unref(logoVal));
}
</script>
<template>
<panel>
<el-divider>主题风格</el-divider>
@ -40,7 +155,7 @@
<li>
<span>灰色模式</span>
<vxe-switch
v-model="greyVal"
v-model="settings.greyVal"
open-label="开"
close-label="关"
@change="greyChange"
@ -49,7 +164,7 @@
<li>
<span>色弱模式</span>
<vxe-switch
v-model="weekVal"
v-model="settings.weekVal"
open-label="开"
close-label="关"
@change="weekChange"
@ -58,7 +173,7 @@
<li>
<span>隐藏标签页</span>
<vxe-switch
v-model="tagsVal"
v-model="settings.tagsVal"
open-label="开"
close-label="关"
@change="tagsChange"
@ -96,147 +211,6 @@
</panel>
</template>
<script lang="ts">
import panel from "../panel/index.vue";
import { reactive, toRefs, ref, unref, useCssModule } from "vue";
import { storageLocal, storageSession } from "/@/utils/storage";
import { emitter } from "/@/utils/mitt";
import { useRouter } from "vue-router";
import { templateRef } from "@vueuse/core";
export default {
name: "setting",
components: { panel },
setup() {
const router = useRouter();
const { isSelect } = useCssModule();
//
const markValue = ref(storageLocal.getItem("showModel") || "smart");
const logoVal = ref(storageLocal.getItem("logoVal") || "1");
const localOperate = (key: string, value?: any, model?: string): any => {
model && model === "set"
? storageLocal.setItem(key, value)
: storageLocal.getItem(key);
};
const settings = reactive({
greyVal: storageLocal.getItem("greyVal"),
weekVal: storageLocal.getItem("weekVal"),
tagsVal: storageLocal.getItem("tagsVal")
});
settings.greyVal === null
? localOperate("greyVal", false, "set")
: document.querySelector("html")?.setAttribute("class", "html-grey");
settings.weekVal === null
? localOperate("weekVal", false, "set")
: document.querySelector("html")?.setAttribute("class", "html-weakness");
function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
const targetEl = target || document.body;
let { className } = targetEl;
className = className.replace(clsName, "");
targetEl.className = flag ? `${className} ${clsName} ` : className;
}
//
const greyChange = ({ value }): void => {
toggleClass(
settings.greyVal,
"html-grey",
document.querySelector("html")
);
value
? localOperate("greyVal", true, "set")
: localOperate("greyVal", false, "set");
};
//
const weekChange = ({ value }): void => {
toggleClass(
settings.weekVal,
"html-weakness",
document.querySelector("html")
);
value
? localOperate("weekVal", true, "set")
: localOperate("weekVal", false, "set");
};
const tagsChange = () => {
let showVal = settings.tagsVal;
showVal
? storageLocal.setItem("tagsVal", true)
: storageLocal.setItem("tagsVal", false);
emitter.emit("tagViewsChange", showVal);
};
function onReset() {
storageLocal.clear();
storageSession.clear();
router.push("/login");
}
function onChange({ label }) {
storageLocal.setItem("showModel", label);
emitter.emit("tagViewsShowModel", label);
}
const firstTheme = templateRef<HTMLElement | null>("firstTheme", null);
const secondTheme = templateRef<HTMLElement | null>("secondTheme", null);
const dataTheme = ref(storageLocal.getItem("data-theme") || "dark");
if (dataTheme.value) {
storageLocal.setItem("data-theme", unref(dataTheme));
window.document.body.setAttribute("data-theme", unref(dataTheme));
}
// dark
function onDark() {
storageLocal.setItem("data-theme", "dark");
window.document.body.setAttribute("data-theme", "dark");
toggleClass(true, isSelect, unref(firstTheme));
toggleClass(false, isSelect, unref(secondTheme));
}
// light
function onLight() {
storageLocal.setItem("data-theme", "light");
window.document.body.setAttribute("data-theme", "light");
toggleClass(false, isSelect, unref(firstTheme));
toggleClass(true, isSelect, unref(secondTheme));
}
function logoChange() {
unref(logoVal) === "1"
? storageLocal.setItem("logoVal", "1")
: storageLocal.setItem("logoVal", "-1");
emitter.emit("logoChange", unref(logoVal));
}
return {
...toRefs(settings),
localOperate,
greyChange,
weekChange,
tagsChange,
onReset,
markValue,
onChange,
onDark,
onLight,
dataTheme,
logoVal,
logoChange
};
}
};
</script>
<style scoped module>
.isSelect {
border: 2px solid #0960bd;

View File

@ -4,9 +4,9 @@
</component>
</template>
<script>
<script lang="ts">
import { computed, defineComponent, unref } from "vue";
import { isUrl } from "/@/utils/is.ts";
import { isUrl } from "/@/utils/is";
export default defineComponent({
name: "Link",

View File

@ -1,14 +1,133 @@
<script setup lang="ts">
import {
ref,
unref,
reactive,
computed,
watchEffect,
onMounted,
onBeforeMount,
useCssModule
} from "vue";
import options from "/@/settings";
import { toggleClass } from "/@/utils/operate";
import { useEventListener } from "@vueuse/core";
import { useAppStoreHook } from "/@/store/modules/app";
import fullScreen from "/@/assets/svg/full_screen.svg";
import exitScreen from "/@/assets/svg/exit_screen.svg";
import { useSettingStoreHook } from "/@/store/modules/settings";
import { Navbar, Sidebar, AppMain, setting, tag } from "./components";
interface setInter {
sidebar: any;
device: string;
fixedHeader: boolean;
classes: any;
}
const pureApp = useAppStoreHook();
const pureSetting = useSettingStoreHook();
const { hiddenMainContainer } = useCssModule();
const WIDTH = ref(992);
let containerHiddenSideBar = ref(options.hiddenSideBar);
const set: setInter = reactive({
sidebar: computed(() => {
return pureApp.sidebar;
}),
device: computed(() => {
return pureApp.device;
}),
fixedHeader: computed(() => {
return pureSetting.fixedHeader;
}),
classes: computed(() => {
return {
hideSidebar: !set.sidebar.opened,
openSidebar: set.sidebar.opened,
withoutAnimation: set.sidebar.withoutAnimation,
mobile: set.device === "mobile"
};
})
});
const handleClickOutside = (params: boolean) => {
pureApp.closeSideBar({ withoutAnimation: params });
};
watchEffect(() => {
if (set.device === "mobile" && !set.sidebar.opened) {
handleClickOutside(false);
}
});
const $_isMobile = () => {
const rect = document.body.getBoundingClientRect();
return rect.width - 1 < WIDTH.value;
};
const $_resizeHandler = () => {
if (!document.hidden) {
const isMobile = $_isMobile();
pureApp.toggleDevice(isMobile ? "mobile" : "desktop");
if (isMobile) {
handleClickOutside(true);
}
}
};
function onFullScreen() {
if (unref(containerHiddenSideBar)) {
containerHiddenSideBar.value = false;
toggleClass(
false,
hiddenMainContainer,
document.querySelector(".main-container")
);
} else {
containerHiddenSideBar.value = true;
toggleClass(
true,
hiddenMainContainer,
document.querySelector(".main-container")
);
}
}
onMounted(() => {
const isMobile = $_isMobile();
if (isMobile) {
pureApp.toggleDevice("mobile");
handleClickOutside(true);
}
toggleClass(
unref(containerHiddenSideBar),
hiddenMainContainer,
document.querySelector(".main-container")
);
});
onBeforeMount(() => {
useEventListener("resize", $_resizeHandler);
});
</script>
<template>
<div :class="classes" class="app-wrapper">
<div :class="set.classes" class="app-wrapper">
<div
v-if="device === 'mobile' && sidebar.opened"
v-if="set.device === 'mobile' && set.sidebar.opened"
class="drawer-bg"
@click="handleClickOutside(false)"
/>
<!-- 侧边栏 -->
<sidebar class="sidebar-container" v-if="!containerHiddenSideBar" />
<div class="main-container">
<div :class="{ 'fixed-header': fixedHeader }">
<div :class="{ 'fixed-header': set.fixedHeader }">
<!-- 顶部导航栏 -->
<navbar v-show="!containerHiddenSideBar" />
<!-- tabs标签页 -->
@ -27,147 +146,6 @@
</div>
</template>
<script lang="ts">
import { Navbar, Sidebar, AppMain, setting, tag } from "./components";
import {
ref,
unref,
reactive,
computed,
toRefs,
watchEffect,
onMounted,
onBeforeMount,
useCssModule
} from "vue";
import { useAppStoreHook } from "/@/store/modules/app";
import { useSettingStoreHook } from "/@/store/modules/settings";
import { useEventListener } from "@vueuse/core";
import { toggleClass } from "/@/utils/operate";
import options from "/@/settings";
import fullScreen from "/@/assets/svg/full_screen.svg";
import exitScreen from "/@/assets/svg/exit_screen.svg";
interface setInter {
sidebar: any;
device: string;
fixedHeader: boolean;
classes: any;
}
export default {
name: "layout",
components: {
Navbar,
Sidebar,
AppMain,
setting,
tag,
fullScreen,
exitScreen
},
setup() {
const pureApp = useAppStoreHook();
const pureSetting = useSettingStoreHook();
const { hiddenMainContainer } = useCssModule();
const WIDTH = ref(992);
let containerHiddenSideBar = ref(options.hiddenSideBar);
const set: setInter = reactive({
sidebar: computed(() => {
return pureApp.sidebar;
}),
device: computed(() => {
return pureApp.device;
}),
fixedHeader: computed(() => {
return pureSetting.fixedHeader;
}),
classes: computed(() => {
return {
hideSidebar: !set.sidebar.opened,
openSidebar: set.sidebar.opened,
withoutAnimation: set.sidebar.withoutAnimation,
mobile: set.device === "mobile"
};
})
});
const handleClickOutside = (params: boolean) => {
pureApp.closeSideBar({ withoutAnimation: params });
};
watchEffect(() => {
if (set.device === "mobile" && !set.sidebar.opened) {
handleClickOutside(false);
}
});
const $_isMobile = () => {
const rect = document.body.getBoundingClientRect();
return rect.width - 1 < WIDTH.value;
};
const $_resizeHandler = () => {
if (!document.hidden) {
const isMobile = $_isMobile();
pureApp.toggleDevice(isMobile ? "mobile" : "desktop");
if (isMobile) {
handleClickOutside(true);
}
}
};
function onFullScreen() {
if (unref(containerHiddenSideBar)) {
containerHiddenSideBar.value = false;
toggleClass(
false,
hiddenMainContainer,
document.querySelector(".main-container")
);
} else {
containerHiddenSideBar.value = true;
toggleClass(
true,
hiddenMainContainer,
document.querySelector(".main-container")
);
}
}
onMounted(() => {
const isMobile = $_isMobile();
if (isMobile) {
pureApp.toggleDevice("mobile");
handleClickOutside(true);
}
toggleClass(
unref(containerHiddenSideBar),
hiddenMainContainer,
document.querySelector(".main-container")
);
});
onBeforeMount(() => {
useEventListener("resize", $_resizeHandler);
});
return {
...toRefs(set),
handleClickOutside,
containerHiddenSideBar,
onFullScreen
};
}
};
</script>
<style scoped module>
.hiddenMainContainer {
margin-left: 0 !important;