前面的話
前端日問,鞏固基礎,不打烊!!!
解答
基本用法
使用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
});
};