Vue.directive 实现元素scroll逻辑复用


Posted in Javascript onNovember 29, 2019

继上篇Vue 滚动触底 mixins,将对于文档滚动触底的逻辑迁移到某个dom上,将会用到 Vue.directive 来实现代码逻辑复用。

元素滚动

如何实现滚动

元素实现滚动的条件有两个:

  • 有父子两个元素
  • 子元素的高度 > 父元素的高度, 并且父元素设置 overflow:scroll / auto;

Vue.directive 实现元素scroll逻辑复用 

scrollHeight 计算

Element.scrollHeight这个只读属性是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容。

可以简单的理解为,滚动高度是元素可以滚动的最大值,分为两种情况

滚动高度 = 当前元素的 clientHeight = height + padding

滚动高度 = 当前元素的padding + 子元素的clientHeight + 子元素的(padding,margin,border) + 伪元素(:after,:before)
scrollTop

Element.scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数。

需要注意的是,scrollTop 是针对产生滚动条的元素而言,所以分为两种情况

  • 不符合滚动条件, scrollTop 为0
  • 符合滚动条件,可以通过 Element.scrollTop 来获取它的子元素的顶部到父级元素顶部的距离,不包括(border,padding)。

判断触底

为了简单起见,假设 father 和 child 都只设置了宽高。

<div class="father" ref="father">
 <div class="child" ref="child"></div>
</div>
// 若为真说明触底
father.clientHeight + father.scrollTop >= child.scrollHeight

抽离成 Vue-directive

基本语法

参数1

指令名称,如focus 使用的时候就通过 v-focus 去绑定指定dom

参数2

options配置项,包含以下的钩子函数,分别在对应的生命周期触发

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
 bind(){
 // 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
 },
 // 当被绑定的元素插入到 DOM 中时……
 inserted: function (el) {
 // 聚焦元素
 el.focus()
 },
 update(){
 // 所在组件的 VNode 更新时调用
 },
 componentUpdated(){
 // 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
 },
 unbind(){
 // 只调用一次,指令与元素解绑时调用。
 }
})

钩子函数的回调参数

上面的钩子函数都接受 el、binding、vnode 和 oldVnode 这些回调参数,对常用的参数做下解释

  • el : 指令所 绑定的元素 ,可以用来直接操作 DOM 。
  • binding : { name,value ,arg}

是绑定组件的data中的变量名

来说下 value 和 arg 的区别,假设我们想向指令传递特定的数据,可以通过下面的方式 arg传递值,和 value绑定值只能使用一种

// 通过 binding.value 接收
<div v-test="title">这里是测试</div>
// 通过 binding.arg 接收
<div v-test:id1>测试2</div>

如何注册指令

全局注册

// 在单独一个文件中单独管理所有 directive 
import Vue from 'vue'
import inputClear from './input-clear'
import forNested from './picker-item-for-nested'
import copy from "./copy";

const directives = {
 copy,
 'input-clear':inputClear,
 'for-nested':forNested
}
Object.keys(directives).forEach(key=>{
 Vue.directive(key,directives[key])
})

局部注册,通过directives选项来注册

export default {
 directives:{
 // 自定义指令的名字
 autoFocus:{
  inserted(el){
  el.focus()
  console.log( 'inserted' );
  }
 }
 }
}

Vue.install的方式来安装

// directive.js
export default {
 install(Vue){
 Object.keys(directives).forEach(key=>{
  Vue.directive(key,directives[key])
 })
 }
}

// main.js
import Directives from "./directive/index";
// Vue.use 通过注册插件的方式来注册指令 `Vue 插件中 install 函数接受 Vue构造函数作为第一入参`
Vue.use(Directives);

Vue.use 源码

// 接收一个 plugin 参数可以是 Function 也可以是 Object
 Vue.use = function (plugin: Function | Object) {
 // 如果传入的是对象,需要有一个install 方法,并执行该方法
 if (typeof plugin.install === 'function') {
  plugin.install.apply(plugin, args)
 // 如果传入的是是函数则立即执行
 } else if (typeof plugin === 'function') {
  plugin.apply(null, args)
 }
 }

将scroll 逻辑添加到 v-directive 中

如果子元素有多个,需要计算每个子元素的 height + padding + border + margin 所以为了方便使用,滚动目标的子元素有多个的情况下,用一个标签统一包裹

function isBottom(el){
 const child = el.children[0]
 if(el.clientHeight + el.scrollTop >= child.scrollHeight){
 console.log('触底了');
 }
}
Vue.directive('scroll',{
 bind(el){
 el.addEventListener('scroll',function(){
  isBottom(el)
 })
 },
 unbind(el){
 el.removeEventListener(isBottom)
 }
})

总结

以上所述是小编给大家介绍的Vue.directive 实现元素scroll逻辑复用,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
php上传图片并给图片打上透明水印的代码
Jun 07 Javascript
JavaScript高级程序设计(第3版)学习笔记2 js基础语法
Oct 11 Javascript
JS正则中的RegExp对象对象
Nov 07 Javascript
页面使用密码保护代码
Apr 10 Javascript
jquery中交替点击事件的实现代码
Feb 14 Javascript
js实现固定显示区域内自动缩放图片的方法
Jul 18 Javascript
谈谈encodeURI和encodeURIComponent以及escape的区别与应用
Nov 24 Javascript
JavaScript重载函数实例剖析
May 13 Javascript
微信小程序实现瀑布流布局与无限加载的方法详解
May 12 Javascript
Vue安装浏览器开发工具的步骤详解
May 12 Javascript
layui动态绑定事件的方法
Sep 20 Javascript
详解在Vue.js编写更好的v-for循环的6种技巧
Apr 14 Javascript
Vue.js实现大屏数字滚动翻转效果
Nov 29 #Javascript
Vue基础配置讲解
Nov 29 #Javascript
jQuery实现弹幕特效
Nov 29 #jQuery
Vue实现多标签选择器
Nov 28 #Javascript
swiper实现异形轮播效果
Nov 28 #Javascript
Vue请求java服务端并返回数据代码实例
Nov 28 #Javascript
javascript实现异形滚动轮播
Nov 28 #Javascript
You might like
解析php中反射的应用
2013/06/18 PHP
php数值转换时间及时间转换数值用法示例
2017/05/18 PHP
tp框架(thinkPHP)实现三次登陆密码错误之后锁定账号功能示例
2018/05/24 PHP
PHP Trait代码复用类与多继承实现方法详解
2019/06/17 PHP
JS 建立对象的方法
2007/04/21 Javascript
uploadify 3.0 详细使用说明
2012/06/18 Javascript
3分钟写出来的Jquery版checkbox全选反选功能
2013/10/23 Javascript
使用微信内置浏览器点击下拉框出现页面乱跳转现象(iphone),该怎么办
2016/01/04 Javascript
使用bootstrapValidator插件进行动态添加表单元素并校验
2016/09/28 Javascript
深入理解vue2.0路由如何配置问题
2017/07/18 Javascript
JavaScript比较同一天的时间大小实例代码
2018/02/09 Javascript
vue 录制视频并压缩视频文件的方法
2018/07/27 Javascript
JS使用Date对象实时显示当前系统时间简单示例
2018/08/23 Javascript
JS二级菜单不同实现方法分析【4种方法】
2018/12/21 Javascript
Angular 中使用 FineReport不显示报表直接打印预览
2019/08/21 Javascript
vue props default Array或是Object的正确写法说明
2020/07/30 Javascript
Python中实现两个字典(dict)合并的方法
2014/09/23 Python
在Python中的Django框架中进行字符串翻译
2015/07/27 Python
Python实现1-9数组形成的结果为100的所有运算式的示例
2017/11/03 Python
TensorFlow入门使用 tf.train.Saver()保存模型
2018/04/24 Python
pytorch + visdom CNN处理自建图片数据集的方法
2018/06/04 Python
Python弹出输入框并获取输入值的实例
2019/06/18 Python
Django中和时区相关的安全问题详解
2020/10/12 Python
Python ConfigParser模块的使用示例
2020/10/12 Python
10个python爬虫入门基础代码实例 + 1个简单的python爬虫完整实例
2020/12/16 Python
New Balance英国官方网站:始于1906年,百年慢跑品牌
2016/12/07 全球购物
澳大利亚领先的武术用品和健身器材供应商:SMAI
2019/03/24 全球购物
澳大利亚礼品篮网站:Macarthur Baskets
2019/10/14 全球购物
.NET remoting的两种通道是什么
2016/05/31 面试题
保险公司开门红口号
2014/06/21 职场文书
出租房屋协议书
2014/09/14 职场文书
2014银行领导班子群众路线对照检查材料思想汇报
2014/09/17 职场文书
2014年重阳节老干部座谈会上的讲话稿
2014/09/25 职场文书
群众路线自我剖析材料
2014/10/08 职场文书
车辆安全隐患排查制度
2015/08/05 职场文书
python脚本框架webpy的url映射详解
2021/11/20 Python