v-権限
背景:一部のバックグラウンド管理システムでは、ユーザーの役割に応じて一部の操作権限を判断する必要がある場合があり、大まかに v-if / v-show
表示・非表示の要素を追加することが多いですが、判断条件が煩雑で複数箇所の判断が必要な場合このようなコードは、洗練されていないだけでなく、冗長でもあります。この状況については、グローバル カスタム ディレクティブを通じて処理できます。
要件: 権限判定が必要な Dom を表示/非表示にする権限コマンドをカスタマイズします。
アイデア:
- 権限配列をカスタマイズする
- ユーザーの権限がこの配列にあるかどうかを判断し、存在する場合はそれを表示し、そうでない場合は 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
用途:
v-permission
課題判定を与えるだけ<div class="btns"> <!-- 显示 --> <button v-permission="'1'">权限按钮1</button> <!-- 不显示 --> <button v-permission="'10'">权限按钮2</button> </div>
v-LazyLoad
背景: 電子商取引プロジェクトでは、バナー広告画像、メニュー ナビゲーション画像、Meituan などの販売者リストのヘッダー画像など、多数の画像が使用されることがよくあります。画像が多すぎたり、画像が大きすぎたりすると、ページの読み込み速度に影響し、ユーザー エクスペリエンスが低下することが多いため、画像の遅延読み込みを最適化することが不可欠です。
要件: ブラウザーの表示領域に画像のみを読み込む遅延画像読み込みコマンドを実装します。
アイデア:
- 画像の遅延読み込みの原理は、主に、現在の画像が表示領域に到達したかどうかを判断するコア ロジックによって実現されます。
- すべての画像を取得します。Dom、各画像を走査して、現在の画像が表示領域の範囲内にあるかどうかを判断します。
- 到着した場合は、
src
画像のプロパティを設定します。それ以外の場合は、デフォルトの画像を表示します。
画像の遅延読み込みを実現するには、イベントをバインドして監視する方法と、画像が表示領域に到達したかどうかを判断するためにsrcoll
使用する方法の 2 つの方法があります が、ブラウザの互換性の問題があります。IntersectionObserver
以下は、ブラウザが IntersectionObserver
API をサポートしているかどうかを判断するために、2 つのメソッドと互換性のある遅延ロード命令をカプセル化しています。サポートしている場合は、それを使用して IntersectionObserver
遅延ロードを実装し、そうでない場合は、 srcoll
イベント監視 + スロットルの方法を使用します。
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
コンポーネント内のラベルを src
次のように 置き換えて使用します。v-LazyLoad
<img v-LazyLoad="xxx.jpg" />