为富文本开发图片懒加载功能

2,637 阅读2分钟

本文基于Vue、Vue-lazyload

前段时间接到了一个展示运营编辑的文章的需求。

第一时间反应就是用v-html渲染出来即可。

但处理后发现,效果并不理想。原因是v-html指令会将内容按普通 HTML 插入,不会作为 Vue 模板进行编译。

v-html 官方解释

由于项目使用vue-lazyload作为图片懒加载方案,直接渲染会使图片懒加载功能失效,且还有一个调用原生功能的需求,所以需要使这部分html作为Vue模板编译出来

在查询一定资料后,我们实现了这个效果。

这个功能的实现分为两步

  1. 使用带编译器版本的Vue
  2. 将html文本转为支持懒加载的文本

第一步:使用带编译器版本的Vue

我们需要将html字符串作为Vue模板来编译,也就是让html字符串支持Vuejs的各种功能。

这就需要使用带编译器的Vuejs

因为不带编译器版本的Vuejs相比完整版体积要小大约30%。所以Vuejs的默认导出是不带编译器版本。 也就是官网中所说的【运行时版本】。他基本是完整版除去编译器的其它一切。

我们根据官网提示,通过打包工具为Vuejs配置别名

module.exports = {
  // ...
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js' // 用 webpack 1 时需用 'vue/dist/vue.common.js'
    }
  }
}

这样 我们就可以使用

new Vue({
  template: '<div>{{ hi }}</div>'
})

这种形式来渲染普通的html文本字符串了。

第二步:将html文本转为支持懒加载的文本

let template = '<img src="xxx" />'

由于我们使用的vue-lazyload插件,所以需要对字符串做一定处理。 首先,将字符串中的src字段替换为vue-lazyload可识别的data-src=

let introTemplate = template.replace(/src=/g, 'data-src')
introTemplate = `<div v-lazy-container="{ selector: 'img'}">${introTemplate}</div>`

vue-lazyload的做法,不同库需要不同的流程

然后创建一个Vue实例

<template>
<div>
    <div id="htmlDom"></div>
</div>
</template>

...
let instance = new Vue({
  template: introTemplate,
  el: document.querySelector('#htmlDom')
}).$mount() // 创建好之后挂载到el字段指向的DOM节点
...

这样,就能够实现富文本图片懒加载的功能了。

注意事项

做好错误处理,如果数据异常导致处理出来的字符串编译错误,那么需要使用原始数据来渲染 在$mount()抛错的情况下,需要使用v-html来渲染原始的数据,这样即使报错,也会退回最低可用的状态

<template>
<div>
    <div v-if="!errorRander" id="htmlDom"></div>
    <div v-else v-html="template"></div>
</div>
</template>

try {
 let instance = new Vue({
  template: introTemplate,
  el: document.querySelector('#htmlDom')
 }).$mount() // 创建好之后挂载到el字段指向的DOM节点   
} catch (e) {
 this.errorRander = true
}