vue自定义指令监听元素是否进入父元素视窗内

简介: 一般涉及 dom 的操作,我们都可以通过自定义指令来实现,比如点击文本直接复制到粘贴板、按钮权限的判断(无权限时隐藏或禁用)...这一点一般通过指令钩子函数的第一个参数 el 就能实现

需求背景

一个每行3列的列表布局,列表中的每一项有一个已读/未读状态,只要展现在了用户的视窗内就算已读状态了。

想到的方案:

  • 直接监听滚动高度,根据滚动距离来计算是否展现在页面内
  • 借助第三方插件,找到一个 vue-check-view,不过只能监听整个 window 视窗的页面滚动,如果想监听某个元素的内部滚动是否可见没法实现

刚开始直接用的 vue-check-view,但是因为项目是用 electron 开发的桌面应用,布局上需要在列表父盒子上实现滚动。然后想到h5里新出的监听元素是否进入视口的 IntersectionObserver,一看好像可以满足,在借助 vue 的自定义指令来封装成一个自定义指令使用。

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

一般涉及 dom 的操作,我们都可以通过自定义指令来实现,比如点击文本直接复制到粘贴板、按钮权限的判断(无权限时隐藏或禁用)...这一点一般通过指令钩子函数的第一个参数 el 就能实现。

但是,有时我们除了对 dom 的操作外,还需要实现对 vue 页面 data 数据的修改、methods 里方法的调用,或者一些额外的参数需要传到指令里来进行判断的...这时我们就可以借助第二个参数 binding 来实现,binding.value 就是我们写在指令 = 后面的东西,可以传递函数、对象、数值、字符串、布尔任意类型(注意和 binding.expression 的区别)。

监听元素是否进入某个视口自定义指令

监听元素是否进入某个视口自定义指令,可以通过 root 参数传入父视口的选择器,不传就默认是相对于浏览器window窗口。适用于元素懒加载、埋点上报、查看了修改状态。

viewport.js

export default {
   
  inserted(el, binding, vnode) {
   
    const value = binding.value
    const isObject = Object.prototype.toString.call(value) === '[object Object]'
    const func = isObject ? value.callback : value
    const isFunc = func && typeof func === 'function'

    const selector = isObject ? value.root : null
    const threshold = isObject ? value.threshold : 1
    const options = {
   
      root: selector ? document.querySelector(selector) : null, // 指定根(root)元素,未指定或 null 则默认为浏览器视窗
      threshold: threshold || 1, // 监听目标与边界盒交叉区域的比例值 0-1
    }

    const observer = new IntersectionObserver(entries => {
   
      entries.forEach(entry => {
   
        if (entry.isIntersecting) {
   
          // 执行回调方法
          isFunc && func()

          // 停止监听
          observer.unobserve(el)
        }
      })
    }, options)

    // 开始监听元素
    observer.observe(el)
  },
}

使用方式

  • 使用方式一:v-viewport="handleViewport" 直接绑定一个回调方法
  • 使用方式二:v-viewport="{callback: handleViewport, root: '#scroll', threshold: 0.8}" 绑定一个对象自定义各项配置
<template>
  <div class="list">
    <div
      v-for="(item, index) in 100"
      :key="index"
      class="item"
      v-viewport="handleViewport(index)"
    >
      我是第 {
  { index }} 个
    </div>
  </div>
</template>
<script>
import viewport from 'xx/viewport.js'
export default {
  directives: {
    viewport
  },
  methods: {
    handleViewport(i) {
      console.log(`第${i}个进入视窗内`)
    }
  }
}
</script>
<style>
.list {
  height: 400px;
  overflow-y: auto;
}

.item {
  height: 100px;
  background: green;
  margin-bottom: 10px;
}
</style>
相关文章
|
3月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
311 2
|
2月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
291 137
|
5月前
|
人工智能 JSON JavaScript
VTJ.PRO 首发 MasterGo 设计智能识别引擎,秒级生成 Vue 代码
VTJ.PRO发布「AI MasterGo设计稿识别引擎」,成为全球首个支持解析MasterGo原生JSON文件并自动生成Vue组件的AI工具。通过双引擎架构,实现设计到代码全流程自动化,效率提升300%,助力企业降本增效,引领“设计即生产”新时代。
416 1
|
5月前
|
JavaScript 安全
在 Vue 中,如何在回调函数中正确使用 this?
在 Vue 中,如何在回调函数中正确使用 this?
261 0
|
JavaScript 数据安全/隐私保护
Vue:几个实用的 Vue 自定义指令
Vue:几个实用的 Vue 自定义指令
261 0
Vue:几个实用的 Vue 自定义指令
|
6月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
787 0
|
8月前
|
JavaScript
vue实现任务周期cron表达式选择组件
vue实现任务周期cron表达式选择组件
1020 4
|
6月前
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能
|
7月前
|
JavaScript 数据可视化 前端开发
基于 Vue 与 D3 的可拖拽拓扑图技术方案及应用案例解析
本文介绍了基于Vue和D3实现可拖拽拓扑图的技术方案与应用实例。通过Vue构建用户界面和交互逻辑,结合D3强大的数据可视化能力,实现了力导向布局、节点拖拽、交互事件等功能。文章详细讲解了数据模型设计、拖拽功能实现、组件封装及高级扩展(如节点类型定制、连接样式优化等),并提供了性能优化方案以应对大数据量场景。最终,展示了基础网络拓扑、实时更新拓扑等应用实例,为开发者提供了一套完整的实现思路和实践经验。
843 77
|
8月前
|
缓存 JavaScript 前端开发
Vue 基础语法介绍
Vue 基础语法介绍