vue项目封装并发布无限滚动指令优化渲染性能的npm模块

曾经在前端之巅看过这么一篇文章,标题是《网站性能优化实战——从12.67s到1.06s的故事》,当时我就纳闷了,哪来的网站首屏需要加载12秒,而且怎么做到这么极致的优化的?

果然过了几天,接手了一份祖传代码,运行后发现项目奇卡,渲染也不是一般的慢,除了谷歌和火狐,其他浏览器一律崩溃。

亚马逊的工程师形容说他们的祖传代码:“一座很大的屎山,你见过的最大的山,每次你想修正一个bug,你的工作就是爬到屎山的正中心去

原项目是混合在php项目中的,我的任务是抽离并优化它,瞬间觉得很有挑战了。

13908708-a88ad9f8b6699118
当我尝试修复一个bug时

略过具体的抽离过程,直接其中一个优化关键点,就是有多个页面都使用element-uiel-table组件进行数据渲染,发现当需要渲染超过1K+的数据的时候页面渲染需要很久,查看控制台发现渲染时间占用10S之久。

查看el-table源码发现内部使用的div来实现table布局,导致产生了大量的dom节点,又由于业务需要无法采用分页,所以当务之急是开发一个无限滚动、滚动加载的组件,而该组件的核心的无限滚动实现逻辑,而且在下拉框中也需要滚动加载,所以干脆抽离出一个无限滚动指令

主要思路是创建三个指令

无限滚动指令参数描述
v-infinite-scrollcallback:function滚动到指定底部后触发的事件
v-infinite-scroll-distancepx:number距离底部多远触发事件
v-infinite-scroll-disabledbusy:bool当前是否为忙碌状态
<div v-infinite-scroll="scrollLoad" v-infinite-scroll-disabled="busy" v-infinite-scroll-distance="250">
    ...
</div>

infinite-scroll-distanceinfinite-scroll-disabled指令分别设置目标标签的data-infiniteScrollDistancedata-infiniteScrollDisabled属性。

infinite-scroll指令在目标标签上注册滚动事件,但达到data-infiniteScrollDistance高度和data-infiniteScrollDisabled为true时,触发回调。(回调中应该填充目标标签内容,使得高度变化,触发下一轮滚动事件)

下面是具体实现
InfiniteScrollDisabled.js

// directives/InfiniteScrollDisabled.js
export default {
  bind(el, binding) {
    el.setAttribute('data-infiniteScrollDisabled', binding.value);
  },
  update(el, binding) {
    el.setAttribute('data-infiniteScrollDisabled', binding.value);
  },
};

InfiniteScrollDistance.js

// directives/InfiniteScrollDistance.js
export default {
  bind(el, binding) {
    el.setAttribute('data-infiniteScrollDistance', binding.value);
  },
  update(el, binding) {
    el.setAttribute('data-infiniteScrollDistance', binding.value);
  },
};

InfiniteScroll.js

// directives/InfiniteScroll.js
export default {
  bind(el, binding) {
    let target = el;
    if (el.getAttribute('data-scrollTarget')) {
      target = el.querySelector(el.getAttribute('data-scrollTarget'));
    }
    target.addEventListener('scroll', e => {
      const busy = el.getAttribute('data-infiniteScrollDisabled') ? false : true;
      const distance = el.getAttribute('data-infiniteScrollDistance')
        ? Number.parseInt(el.getAttribute('data-infiniteScrollDistance'), 10)
        : 100;
      if (!busy && e.target.scrollHeight - (e.target.scrollTop + e.target.clientHeight) < distance) {
        el.setAttribute('data-infiniteScrollDisabled', true);
        binding.value(e);
      }
    });
  },
};

这里有一个点需要注意,这里接受一个data-scrollTarget属性,代表绑定滚动事件的元素,默认是当前元素,如果需要指定为内部的某个元素可以使用该属性。


到这里无限滚动指令逻辑已经结束了,我们再创建一个文件,用于统一导出指令,并让vue项目通过vue.use(...)的形式使用。

// index.js
import InfiniteScroll from './directives/InfiniteScroll';
import InfiniteScrollDisabled from './directives/InfiniteScrollDisabled';
import InfiniteScrollDistance from './directives/InfiniteScrollDistance';

export default {
  install(Vue, options) {
    const directives = {
      InfiniteScroll,
      InfiniteScrollDisabled,
      InfiniteScrollDistance
    };
    Object.keys(directives).forEach(key => {
      directives[key].$options = options;
      Vue.directive(key, directives[key]);
    });
  },
};

导致index.js后,直接用vue.use(...),将会触发导出的install方法,并传入vue实例和相关参数。
当然也可以发布到npm上,具体发布流程这里暂不介绍。

13908708-b758a8aa78b299b9.png

细心的朋友可能已经发现了,这里写的是es6代码,在不兼容的浏览器上将无法使用,我们可以全部改回es5,但是,我建议使用 babel进行 转译

首先我们先安装babel-clibabel-preset-es2015

$ npm install  babel-cli  babel-preset-es2015 --save-dev

然后添加一个转译命令

// package.json
"scripts": {
  "build": "babel ./src --presets babel-preset-es2015 --out-dir ./lib"
},

把./src下的全部文件转译成es5到./lib文件夹下。

执行打包转译

$ npm run build

后面的任务就是通过该无限滚动指令指令封装无限滚动组件,请看后续文章。

最后奉上git地址:https://gitee.com/zhkumsg/common-directive

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ScrollReveal是一个JavaScript库,可以用来创建动画效果,使网页元素在滚动时以逐渐出现或消失的方式进行渲染。在Vue2中,可以通过以下方式封装ScrollReveal: 1. 安装ScrollReveal 可以通过npm安装ScrollReveal: ``` npm install scrollreveal --save ``` 2. 创建ScrollReveal插件 在Vue项目中创建一个新文件,名为scrollreveal.js,用于创建ScrollReveal插件。在该文件中,需要引入ScrollReveal库,并使用Vue.use()将其注册为Vue插件: ```javascript import ScrollReveal from 'scrollreveal' const ScrollRevealPlugin = { install(Vue) { Vue.prototype.$sr = ScrollReveal() } } export default ScrollRevealPlugin ``` 在上述代码中,我们创建了一个名为ScrollRevealPlugin的对象,该对象包含一个名为install的方法,该方法接受Vue作为参数。在该方法中,我们使用Vue.prototype将ScrollReveal实例 $sr 注册到Vue实例中。 3. 在Vue项目中使用ScrollReveal 在Vue项目中,我们可以在需要使用ScrollReveal的组件中引入并使用该插件。例如,在Home.vue组件中,我们可以这样使用: ```javascript <template> <div> <h1 ref="title">Hello world</h1> </div> </template> <script> import ScrollRevealPlugin from '@/plugins/scrollreveal' export default { name: 'Home', mounted() { this.$sr.reveal(this.$refs.title, { duration: 1000, origin: 'bottom', distance: '100px', delay: 500, }) }, plugins: [ScrollRevealPlugin], } </script> ``` 在上述代码中,我们首先引入了刚刚创建的ScrollReveal插件。在mounted生命周期钩子中,我们使用 $sr.reveal() 方法将标题元素 $refs.title 进行动画渲染。在该方法中,我们可以指定动画的持续时间、起始点、移动距离和延迟时间等参数。 这样,我们就可以在Vue2项目中使用封装好的ScrollReveal插件来创建动画效果了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值