3 / 28 如何实现一个指令 ?

前面的话

前端日问,巩固基础,不打烊!!!

解答
基本用法

使用Vue.directive()来注册自定义指令:

全局注册

比如制定一个懒加载指令v-lazyLoad

Vue.directive('lazyLoad', {
	// ...指令选项
})
指令选项
  • bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作
  • inserted: 被绑定元素插入父结点时调用。
  • update:被绑定元素所在的模板更新时调用,而不论绑定值是否变化
  • componentUpdated:被绑定元素所在模板完成一次更新周期时调用
  • unbind: 只调用一次,指令与元素解绑时调用
实现一个图片懒加载指令
//Vue 图片懒加载
// 引入节流函数
import { throttle } from './util';

export default (Vue, options = {}) => {
    // 在数组原型上添加remove方法 找到item所在的位置,并删除
    if (!Array.prototype.remove) {
        Array.prototype.remove = function (item) {
            // 如果长度为0 跳出
            if (!this.length) return;
            let index = this.indexOf(item);
            // 否则删除
            if (index > -1) {
                this.splice(index, 1);
                return this;
            }
        };
    }
    // 设置初始值
    let init = {
        // 默认图片
        default: 'http://ps.missyuan.com/uploads/allimg/120703/1F4543522-0.jpg'
    };
    // 要显示的图片列表
    let listenList = [];
    // 已经加载过的图片地址
    let alredyArray = [];
    // 判断是否加载过
    const isAlredyLoad = (imageSrc) => {
        if (alredyArray.indexOf(imageSrc) > -1) {
            return true;
        } else {
            return false;
        }
    };
    //检测图片是否可以加载,如果可以则进行加载
    const isCanLoad = (item) => {
        let ele = item.ele;
        let src = item.src;
        //图片距离页面顶部的距离
        let top = ele.getBoundingClientRect().top;
        //top + 10 已经进入了可视区域10像素
        if (top + 10 < window.innerHeight) {
            let image = new Image();
            image.src = src;
            image.onload = function () {
                ele.src = src;
                alredyArray.push(src);
                listenList.remove(item);
            };
            return true;
        } else {
            return false;
        }
    };
    //Vue 指令最终的方法
    const addListener = (ele, binding) => {
        //绑定的图片地址
        let imageSrc = binding.value;
        //如果已经加载过,则无需重新加载,直接将src赋值
        if (isAlredyLoad(imageSrc)) {
            ele.src = imageSrc;
            return false;
        }
        let item = {
            ele: ele,
            src: imageSrc
        };
        //图片显示默认的图片
        ele.src = init.default;
        //再看看是否可以显示此图片
        if (isCanLoad(item)) {
            return;
        };
        //否则将图片地址和元素均放入监听的lisenList里
        listenList.push(item);

        //然后开始监听页面scroll事件

        window.onscroll = () => {
            let carriedOut = throttle(function () {
                let length = listenList.length;
                for (let i = 0; i < length; i++) {
                    isCanLoad(listenList[i]);
                }
            }, 1000);
            carriedOut();
        };
    };
    Vue.directive('lazyLoad', {
        bind: addListener
    });
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值