前言

这是我新开的一个对于前端常识的模块,次要解说日常开发中罕用的前端技巧。此模块解说的常识都是能大幅晋升前端性能的奇技淫巧,供大家日常交换,同时也心愿大家不吝赐教,指出自己的有余。

本文应用的技术栈: vue3 + typescript + pinia + element-plus

背景

modal模态框又称之为弹出框、对话框,是前端日常开发最为频繁的组件之一。然而在日常开发过程中常常遇到一些性能、或者写法繁琐的问题。上面是我举例的一些常见问题:

1.modal框塞入以后页面会导致整个组件更新,影响性能

<template>      <div class="about">        <el-button class="todo-list--add-btn" @click="showModal">              增加工作        </el-button>        <ul>              <li             class="todo-list--item-box"                   v-for="(item, index) in list"                    :key="item.title">                    <div>{{ item.title }}</div>                    <div class="todo-list--add-btn" @click="handleDelToDoList(index)">                      删除                    </div>               </li>         </ul>// 此种形式更新会带动组件的更新       <el-dialog :model-value="show" title="增加工作" width="30%">            <el-input v-model="todoListAddInput" placeholder="请输出" />            <template #footer>                  <span class="dialog-footer">                        <el-button @click="modalStore.hideModal(ModalType.TODO_LIST)">                         勾销                        </el-button>                        <el-button type="primary" @click="handleAddToDolist"> 提交 </el-button>                  </span>            </template>     </el-dialog>  </div></template>
  1. 许多后盾利用的modal框体量都是十分宏大的,一些流程modal框动辄成千盈百行代码很失常,如果在首次加载势必影响首次加载耗时
  2. vue应用teleport,react应用createPortal把modal框放到根节点是一些公司的次要优化伎俩,然而没有全局注册调用事件,导致modal框管理混乱,前端开发人员开发的modal框组件遍布我的项目各个文件夹

上面我就针对以上问题做出解决方案

构造示意图:

 

全局注册modal框

应用pinia进行modal的全局治理不仅能使各个组件很不便的调用model框,还能对立modal入口,方便管理。

// 全局modal框惟一身份标识export enum ModalType {  TODO_LIST,}// modal框所须要的参数注册接口export interface ModalDataType {      [ModalType.TODO_LIST]: {           onSubmit: (value: string) => void;      };}// modal框实例对象接口interface ModalInstance<T extends ModalType> {      type: T; // modal框标识     component: any; // modal框vue组件      data?: ModalDataType[T]; // modal框传值      onEnter?: (data: ModalDataType[T]) => void; // 生命周期钩子,在modal框显示之后调用      onExit?: (data: ModalDataType[T]) => void; // 生命周期钩子,在modal框显暗藏之后调用}type ModalListItem = { [key in ModalType]: ModalInstance<ModalType> };

通过以上代码咱们就设计好了全局modal框的所用到的属性。通过对这些属性的使用,咱们能够很不便的建设起一个全局数据中心,这一步解决了modal框的治理问题(具体代码详见文章结尾GitHub地址):

useModalStore = {  //modal注册核心,当有新modal被关上时,把modal实例注册到此对象  modalInstanceMap: Ref<ModalListItem>    //以后关上的modal的汇合  showModalList: Ref<ModalType>    //modal框开启函数,如果以后关上的modal未被注册,showModal将注册此组件  showModal: <T extends ModalType>(modalType: T, data?: ModalDataType[T] | undefined) => void    //modal框暗藏函数     hideModal:(modalType: ModalType) => void    //注册modal框生命周期钩子onEnter  onEnter:<T extends ModalType>(modalType: T, fn: (data: ModalDataType[T]) => void) => void     //注册modal框生命周期钩子onExit    onExit:<T extends ModalType>(modalType: T, fn: (data: ModalDataType[T]) => void) => void}

全局挂载modal框

建设起全局数据中心,咱们下一步就是全局注册modal框,这一步解决了咱们先前所提到的modal框在其余组件外部注册modal框,影响性能的问题:

// app.ts<script>import { useModalStore } from "@/stores/modal";const modalStore = useModalStore();<template>......    <component            v-for="item in modalStore.modalList"              :key="item.type"              :is="item.component"     />...

modal框实例创立

这一步咱们创立所需的对应的模态框,创立步骤为以下流程

  1. modal全局数据中心注册modal组件(新建一个ModalType枚举,定义modal组件传参,引入modal组件并注册)

   2.编写modal组件,注册modal组件的显示暗藏函数

// /modal/todolist.vue  import { ModalType, useModalStore, type ModalDataType } from "@/stores/modal";import { computed, ref } from "vue";const modalStore = useModalStore();const todoListAddInput = ref();//管制modal的显示暗藏const show = computed(() =>  modalStore.showModalList.includes(ModalType.TODO_LIST));
  1. 注册生命周期钩子,此钩子能够拿到传入的参数,并且因为做了泛型解决,data的属性为对应的ModalType的传参类型(具体能够拜访文章前面的github地址感受一下)
modalStore.onEnter(ModalType.TODO_LIST, (data) => {      props = data});modalStore.onExit(ModalType.TODO_LIST, () => {      todoListAddInput.value = ""});

调用modal框

// todolist.vue<script>import { useModalStore, ModalType } from "@/stores/modal";interface TodoList {      title: string;}   const modalStore = useModalStore();function showModal() {     modalStore.showModal(ModalType.TODO_LIST, {           onSubmit: // 自定义提交函数   })}

这样咱们就能够很不便的在各个组件调用modal框了,

结尾

致力于代码层面的优化,进步本身编程能力。通过上述优化操作,解决了modal的大部分痛点,心愿可能帮忙到你。

我的项目地址:https://github.com/charCR2/vue-repo/tree/main/modal-example(记得给star哈~,感激)