v-permission
Background: In some background management systems, we may need to judge some operation permissions according to the user role. In many cases, we roughly add an element to v-if / v-show
display and hide, but if the judgment conditions are cumbersome and multiple places need to be judged, this The code in this way is not only inelegant but also redundant. For this situation, we can handle it through global custom directives.
Requirement: Customize a permission command to display and hide Dom that needs permission judgment.
Ideas:
- Customize a permission array
- Determine whether the user's permissions are in this array, if so, display it, otherwise remove the Dom
function checkArray(key) { let arr = ['1', '2', '3', '4'] let index = arr.indexOf(key) if (index > -1) { return true // 有权限 } else { return false // 无权限 } } const permission = { inserted: function (el, binding) { let permission = binding.value // 获取到 v-permission的值 if (permission) { let hasPermission = checkArray(permission) if (!hasPermission) { // 没有权限 移除Dom元素 el.parentNode && el.parentNode.removeChild(el) } } }, } export default permission
Use:
v-permission
Just give the assignment judgment<div class="btns"> <!-- 显示 --> <button v-permission="'1'">权限按钮1</button> <!-- 不显示 --> <button v-permission="'10'">权限按钮2</button> </div>
v-LazyLoad
Background: In e-commerce projects, there are often a large number of pictures, such as banner advertisement pictures, menu navigation pictures, and merchant list header pictures such as Meituan. Too many pictures and too large pictures often affect the loading speed of the page, resulting in a bad user experience, so it is imperative to optimize the lazy loading of pictures.
Requirements: Implement a lazy image loading command, which only loads images in the visible area of the browser.
Ideas:
- The principle of lazy loading of pictures is mainly realized by the core logic of judging whether the current picture has reached the visible area
- Get all the picture Dom, traverse each picture to judge whether the current picture is within the range of the visible area
- If it arrives, set
src
the properties of the picture, otherwise display the default picture
There are two ways to achieve lazy loading of images. One is to bind srcoll
events to monitor, and the other is to use it IntersectionObserver
to judge whether the image has reached the visible area, but there are browser compatibility issues.
The following encapsulates a lazy loading instruction compatible with the two methods to determine whether the browser supports IntersectionObserver
the API. If it supports it, use it IntersectionObserver
to implement lazy loading, otherwise use srcoll
the method of event monitoring + throttling.
const LazyLoad = {
// install方法
install(Vue, options) {
const defaultSrc = options.default
Vue.directive('lazy', {
bind(el, binding) {
LazyLoad.init(el, binding.value, defaultSrc)
},
inserted(el) {
if (IntersectionObserver) {
LazyLoad.observe(el)
} else {
LazyLoad.listenerScroll(el)
}
},
})
},
// 初始化
init(el, val, def) {
el.setAttribute('data-src', val)
el.setAttribute('src', def)
},
// 利用IntersectionObserver监听el
observe(el) {
var io = new IntersectionObserver((entries) => {
const realSrc = el.dataset.src
if (entries[0].isIntersecting) {
if (realSrc) {
el.src = realSrc
el.removeAttribute('data-src')
}
}
})
io.observe(el)
},
// 监听scroll事件
listenerScroll(el) {
const handler = LazyLoad.throttle(LazyLoad.load, 300)
LazyLoad.load(el)
window.addEventListener('scroll', () => {
handler(el)
})
},
// 加载真实图片
load(el) {
const windowHeight = document.documentElement.clientHeight
const elTop = el.getBoundingClientRect().top
const elBtm = el.getBoundingClientRect().bottom
const realSrc = el.dataset.src
if (elTop - windowHeight < 0 && elBtm > 0) {
if (realSrc) {
el.src = realSrc
el.removeAttribute('data-src')
}
}
},
// 节流
throttle(fn, delay) {
let timer
let prevTime
return function (...args) {
const currTime = Date.now()
const context = this
if (!prevTime) prevTime = currTime
clearTimeout(timer)
if (currTime - prevTime > delay) {
prevTime = currTime
fn.apply(context, args)
clearTimeout(timer)
return
}
timer = setTimeout(function () {
prevTime = Date.now()
timer = null
fn.apply(context, args)
}, delay)
}
},
}
export default LazyLoad
Use, replace the label inside the component src
with v-LazyLoad
<img v-LazyLoad="xxx.jpg" />