关于vue自定义指令实现简单无限流

361 阅读1分钟

自定义指令 vue

  • 全局自定义指令语法

    Vue.directive('指令名字',{指令定义})
    ​
    eg:
    index.vue
    improt { scroll } from './scroll'; // 在scroll.ts中 定义指令,再导入
    Vue.directive('scroll',scroll)
    ​
    scroll.ts
    export default {
        // 钩子函数
    }
    
    • 详细钩子函数介绍可以参考 Vue.js 自定义指令
    • 在实现无限流加载,我们需要监听滚动条,因此,只需要绑定对应的el实例,也就是我们只需要用到 bindunbind 钩子函数
  • 官网对于 bindunbind 的介绍

    bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
    unbind:只调用一次,指令与元素解绑时调用
    
  • 钩子函数的参数有以下四个: el、binding、vnode、oldVnode,除了 el ,其他参数均只读

    • el:指令所绑定的元素,可以用来直接操作 DOM
    • binding:指令所绑定的对象,可以通过 binding.value 获取指令绑定的值,可以是一个函数,也可以是一个计算值,通过 binding.expression 获得指令的字符串表达式,其他参数请参考官方文档..
    • vnode: Vue 编译生成的虚拟节点
    • oldVnode:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用

实现原理

  • 滚动条底部距离页面底部的距离小于某个定值(该定值绑定在 el 上,通过 el.getAttribute 获取该定值),便触发 binding 绑定的函数
directive.timer = setInterval(() => {
    // 滑动到底部的距离:滑动的全部高度 - 容器的高度 - 滑动的顶部距离顶部的高度
    const bottom = el.scrollHeight - el.clientHeight - el.scrollTop;
    const disabled = el.getAttribute('scroll-disabled') === 'true';
    const loadMoreFlag = loadMore && bottomDistance > bottom && !disabled && (el.clientHeight && el.scrollTop);
    // console.log(`[direct.scrollpull] timer|${bottom}(bottom)|${bottomDistance}`
    //   + `(bottomDist)|${disabled}(disabled)|${loadMoreFlag}(loadMoreFlag)|${el.scrollTop}`
    //   + `(scrollTop) | ${el.scrollHeight}(scrollHeight) | ${el.clientHeight}(height)`);
    loadMoreFlag && loadMore();
}, 500);
// 该div为页面根元素
<div v-scroll="loadMoreList" scroll-distance="600" :scroll-disabled="canScroll" v-on:scroll="scrollHandle" ref="loadmore">
</div>
.container {
  width100vw;
  height100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  margin0;
  padding0;
  background-color#f3f3f3;
  overflow-y: scroll;
}