做过尝试

这个功能完成之前,本博客静态生成的html是无法使用懒加载的,因为懒加载组件是一个vue component。关于如何静态生成html,可以参考edit组件。我试过动态编译v-html,但是无法避免html字符串里有和vue冲突的东西。

改变思路

直到昨天,我都没有想好如何解决这个问题,一直留了个TODO在那。昨晚躺床上时灵光一现:无法编译整个html,那我只取出想要的部分,然后手动替换成vue实例呢?今早起来,打开电脑准备试试,这是这周最后一次在家里用电脑了

  1. 首先就是如何在js里手动实例化一个.vue单文件组件,找到了一个方法,尝试可行。

  2. 第二步,在v-html渲染后,手动替换图片为懒加载图片组件。只需在$nextTick加上:

    import LazyImg from "~/comps/lazy-img";
    const LazyImgComp = Vue.extend(LazyImg);
    
    this.$refs.markdown.querySelectorAll('.image-container img').forEach(el => {
        new LazyImgComp({
          propsData: {
            src: el.getAttribute('src'),
            alt: el.title,
            viewer: true,
            imgStyle: el.getAttribute('style'),
            title: el.title,
          }
        }).$mount(el);
    })
    

对,没错,这一步就行了。但是有一个问题,项目之前懒加载监听的scroll事件,是从layout父级组件provide拿的。因为懒加载很多,若每一个都去addEventListener太不优雅;另外scroll还要被其他页面使用,例如文章详情的menu;另外scroll做了节流。所以我把它放到了顶级元素里(这里也是一个骚操作,有兴趣可以扒扒源码),这会导致一个问题:手动实例化的LazyImgComp,拿不到这个scroll inject!现在只有一种办法,把原本就不属于vue管的浏览器事件,脱离出去。

真正的问题

所以现在的问题就是,如何把scroll事件脱离出去,而且要让它为全站所使用。这个问题对我来说有点棘手,之前没这样做过。但是!又一个灵光一现,既然scroll是事件监听,那我为何不直接代理它,然后想怎么转发就怎么转发呢。于是就有了以下操作:

  1. 删掉之前的scroll烂代码。

  2. 新建一个scroll-event.js文件,如下:

    import {inBrowser} from "~/utils/utils";
    import throttle from "lodash/throttle";
    
    let scrollEvent = null;
    // 初始化window监听
    export function initScrollTrigger () {
      if (inBrowser) {
        scrollEvent = new CustomEvent('scroll-event');
        window.addEventListener('scroll', throttle(e => {
          window.dispatchEvent(scrollEvent);
        }, 200));
      }
    }
    // 监听转发的事件
    export function addScrollListener (callback) {
      if (scrollEvent) {
        window.addEventListener('scroll-event', callback);
      }
    }
    // 取消监听
    export function rmScrollListener (callback) {
      if (scrollEvent) {
        window.removeEventListener('scroll-event', callback);
      }
    }
    
  3. initScrollTrigger只需要在layout顶级元素的mount里调用一次。然后addScrollListener作为节流过的scroll事件,就可以随便用了。实测可行。

冬天手冻僵了,人也懒,文章写得太简单,以后空闲想写了再完善吧。。。