自定义指令directives:防抖,节流,element-ui的无限滚动在el-table上使用的封装

vue官网对于自定义指令的介绍
添加链接描述

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

1.自定义局部指令:在options api选项中的directives中设置

2.自定义全局指令:在app的directive的方法

官网给出的是一个input框聚焦案例,不太明白怎么用的建议去看一下,链接就是上面的那个
钩子函数:

一个指令定义对象可以提供如下几个钩子函数

1.bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置

2.inserted:被绑定元素插入父节点时调用(保证父节点存在,但不一定已被插入文档中)

3.update:所在组件的vnode更新时调用,但是可能发生在其子vnode更新之前,指令的值可能发生了改变,也可能没有,但是你可以通过比较更新前后的值来忽略不必要的模板更新

4.componentUpdated:指令所在组件的vnode及其子vnode全部更新后调用

5.unbind:只调用一次,指令与元素解绑时调用

下面是指令的封装:

1.节流 2.防抖 3.element-ui的无限滚动在el-table上使用的封装
1.节流

javascript 复制代码
// 引入节流插件
import throttleCall from 'lodash/throttle'
export default{
    bind(el,binding,vnode){
        const fn=binding.value // 通过参数拿到click事件触发的函数
        // 节流处理后的函数,默认3000ms
        const throttled=throttleCall(fn,3000,{leading:true,trailing:false})
        el.addEventListener('click',throttled) // 绑定上
        el._throttled=throttled // 把函数赋值到el 对象上,方便其他钩子函数访问
    },
    unbind(el){
        // 指令与元素解绑时,解绑事件
        el.removeEventListener('click',el_debounced)
    }
}

1.全局引入在main.js

javascript 复制代码
import throttleClick from './drectives/throttle-click'
Vue.directive('throttle-click',throttleClick)

然后就可以直接使用

javascript 复制代码
<el-button v-throttle-click="test">节流测试</el-button>

2.局部注册,在用到的组件内注册并使用,使用如上,下面局部注册引用

javascript 复制代码
import throttleClick from '@drectives/throttle-click'
export default{
	directives:{throttleClick}
}

2.基于防抖在按钮不可点击的时候同时置灰按钮

javascript 复制代码
export default {
    inserted(el,binding){
        el.addEventListener('click',(e)=>{
            el.classList.add('is-disabled')
            el.disabled=true
            setTimeout(()=>{
                el.disabled=false
                el.classList.remove('is-disabled')
            },3000)
        })
    }
} 

1.全局引入在main.js

javascript 复制代码
import noMoreClick from './drectives/no-more-click'
Vue.directive('no-more-click',noMoreClick)

然后就可以直接使用

javascript 复制代码
<el-button v-no-more-click="test">节流测试</el-button>

2.局部注册,在用到的组件内注册并使用,使用如上,下面局部注册引用

javascript 复制代码
import noMoreClick from '@drectives/no-more-click'
export default{
	directives:{noMoreClick}
}

3.table-infinite-scroll 对element-ui的无限滚动在el-table使用的封装

table表格实现表格数据动态滚动(无限滚动)

javascript 复制代码
// 对element-ui的无限滚动 在el-table上使用的封装
import elInfiniteScroll from 'element-ui/lib/infinite-scroll'
const elScope ='ElInfiniteScroll'   // scrope name
const msgTitle = `[el-table-infinite-scroll]` // messsage title
const elTableScrollWrapperClass = '.el-table__body-wrapper'

export default{
    inserted(el,binding,vnode,oldVnode){
        // 获取 table的滚动层
        const scrollElem =el.querySelector(elTableScrollWrapperClass)
        // 如果没找到元素,返回错误
        if(!scrollElem){
            throw new Error(`${mesTitle}找不到 ${elTableScrollWrapperClass}容器`)
        }
        // 设置自动滚动
        scrollElem.style.overflowY='auto'
        // dom渲染后
        setTimeout(()=>{
            if(!el.style.height){
                scrollElem.style.height='400px'
                console.warn(`${msgTitle}请尽量设置 el-table的高度,可以设置为auto/100%(自适应高度),为设置会取400px的默认值,不然会导致一直加载`)
            }
            asyncElOptions(vnode,el,scrollElem)
            // 绑定 infinote-scroll
            elInfiniteScroll.inserted(scrollElem,binding,vnode,oldVnode)

            // 将子集的引入放入el上,用于 unbind中销毁事件
            el[elScope]=scrollElem[elScope]
        },0)
    },
    componentUpdated(el,binding,vnode){
        asyncElOptions(vnode,el,el.querySelector(elTableScrollWrapperClass))
    },
    unbind:elInfiniteScroll.unbind
}

/**
 * 同步 el-infinite-scroll 的配置项
 * @param sourceVnode
 * @param sourceElem
 * @param targetElem
 */
function asyncElOptions(sourceVnode,sourceElem,targetElem){
    const context =sourceVnode.context
    let value
    ['diasble','delay','immediate'].forEach((name)=>{
        const myName='infinite-scroll-'+name
        value= sourceElem.getAttribute(myName)
        if(value!==null){
            targetElem.setAttribute(myName,context[value] || value)
        }
    })
    // 问题解决: window/chrome 的scrollTop+clientHeight 与scrollHeight 不一致的bug
    const name = 'infinite-scroll-distance'
    value= sourceElem.getAttribute(name)
    value =context[value] || value
    targetElem.setAttribute(name,value<1?1:value)
}

局部注册并使用

javascript 复制代码
<template>
	<el-table v-table-infinite-scroll="loadMore" :data='scrolllist' height="500px">
	<el-table-column prop='data' label="日期" align='center'></el-table-column>
	<el-table-column prop='grade' label="班级" align='center'></el-table-column>
	<el-table-column prop='name' label="姓名" align='center'></el-table-column>
	<p v-if="isLoading" align='center'>加载中...</p>
	<p v-if="noMore" align='center'>没有更多了...</p>
</template>


export default{
	directives:{tableInfiniteScroll}
	data(){
		return {
			scrolllist:[], // 具体调接口赋值不再展示
			loading:false,
			noMore:false
		}
	},
	methods:{
		// 上拉刷新加载
		loadMore(){
			if(this.isLoading){
				return
			}
			if(this.noMore){
				// 数组已加载完毕
				return
			}
			this.isLoading=true
			setTimeout(()=>{
				// 调接口更新数据,如果接口没有数据会设置this.noMore状态
				this.isLoading=false
			},100)
		}
	}
}
相关推荐
界面开发小八哥15 小时前
DevExpress WPF中文教程:Grid - 如何移动和调整列大小?(二)
ui·.net·wpf·界面控件·devexpress·ui开发
生产队队长1 天前
项目练习:element-ui的valid表单验证功能用法
前端·vue.js·ui
~央千澈~2 天前
优雅草央千澈-关于蓝湖如何快速的标注交互原型是如何使用的-如何使用蓝湖设计交互原型和整个软件项目的流程逻辑-实践项目详细说明
ui·交互·蓝湖
军训猫猫头2 天前
20.抽卡只有金,带保底(WPF) C#
ui·c#·wpf
wuningw2 天前
ant-design-ui的Select选择器多选时同时获取label与vaule值
ui·arcgis
SoraLuna2 天前
「Mac畅玩鸿蒙与硬件47」UI互动应用篇24 - 虚拟音乐控制台
开发语言·macos·ui·华为·harmonyos
晓纪同学3 天前
QT创建一个模板槽和信号刷新UI
开发语言·qt·ui
程序视点4 天前
【安全漏洞】Vue UI库Vant组件遭恶意投毒,字节RspacK也中招!请紧急修复!
前端·vue.js·ui
m0_748238784 天前
前端使用 Konva 实现可视化设计器(20)- 性能优化、UI 美化
前端·ui·性能优化
m0_748239334 天前
随手记录第十四话 -- 在 Spring Boot 3.2.3 中使用 springdoc-openapi-starter-webmvc-ui
spring boot·后端·ui