el-dialog的内容预加载

4,294 阅读3分钟

遇到的问题

经常使用vue的同学对element-ui的弹框组件应该都不陌生,element为了优化性能,在弹框未首次打开之前,是会不渲染弹框body中的内容的,一般情况下这样的设定是没有问题的,弹框未打开时我们一般也是不需要对弹框内容做操作的,但是在一些特殊情况,可能就有问题了。

正好也是一个偶然的需求导致了这个问题的思考,​vue-monoplasty-slide-verify​这个组件可能很多人用过,是一个vue的滑动验证组件,使用起来非常简单,直接引入注册,就可以以组件的方式直接使用了,我这边是作为登录检验使用,在用户输入密码账户点登录之后弹框一个滑动验证,成功之后开始登录。

那么问题来了,vue-monoplasty-slide-verif组件有一个初始化的资源加载时间,当我们将其包裹在el-dialog中使用时,首次打开弹框,组件才开始加载,此时网络不是很快时就有一个较长的载入时间,并且载入动画不是很明显,是一个白色的蒙版在闪动,不知情的用户可能以为页面加载不出来了。

GIF 2021-7-16 14-43-58.gif

那么如果可以让el-dialog提前把组件渲染了,在用户输入账户密码的期间,是有一段时间可以利用来加载数据的。翻看element的文档,el-dialog在api是没有预加载相关的参数的,那么el-dailog是怎么实现首次打开才渲染组件的呢。

寻找根源

让我们继续翻看el-dialog的源码

image.png

可以看到body部分的渲染是通过​rendered​参数来控制的

image.pngel

rendered是el-dialog中的内部参数,在首次打开之后,el-dialog将rendered置为true,之后body内容就开始渲染。

解决问题

知道el-dialog的代码实现之后,我们想解决这个问题就非常简单了,只要让rendered参数在未打开时就值为true不就完事了吗,

虽然rendered是内部参数,不暴露api,但是我们可以通过弹框实例直接修改他,说干就干

image.png

直接在我们的mounted事件中调用dialog实例,将rendered置为true,此时body内容就可以开始渲染了。再次打开试试

GIF 2021-7-16 14-40-14.gif

快了不少,几乎看不到白色加载过程了。

更进一步

通过以上的处理,基本满足我们的需求了,但是可不可以更进一步呢,比如有多处需要类似需求,那我们需要在业务逻辑中每次都写一个处理,非常不方便,同时处理需要在mounted事件中,否则拿不到弹框实例,而弹框实例挂载也是需要时间的(尽管时间非常快),所以我们最好可以封装一个直接做一个独立的组件使用。

正好vue就提供了这样的api,让我们可以非常方便的扩展组件。

image.png

利用extends我们可以保留组件来源的全部功能,只需加上我们需要的逻辑就行了,话不多说,直接上代码:

<script>
import { Dialog } from "element-ui";
export default {
  extends: Dialog,
  props: {
    preload: {
      type: Boolean,
      default: false,
    },
  },
  created() {
    this.preload && (this.rendered = true);
  },
};
</script>

通过简单的扩展,我们就可以直接使用preload参数开控制弹框是否需要预渲染了。直接调试看一下结果,刷新页面可以通过dev-tools可以看到rendered已经变成true了。

image.png

代码都非常简单,主要就是分享一下思路。