Vue_カスタム命令実践百科事典

 v-権限

背景:一部のバックグラウンド管理システムでは、ユーザーの役割に応じて一部の操作権限を判断する必要がある場合があり、大まかに v-if / v-show 表示・非表示の要素を追加することが多いですが、判断条件が煩雑で複数箇所の判断が必要な場合このようなコードは、洗練されていないだけでなく、冗長でもあります。この状況については、グローバル カスタム ディレクティブを通じて処理できます。

要件: 権限判定が必要な Dom を表示/非表示にする権限コマンドをカスタマイズします。

アイデア:

  1. 権限配列をカスタマイズする
  2. ユーザーの権限がこの配列にあるかどうかを判断し、存在する場合はそれを表示し、そうでない場合は 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 などの販売者リストのヘッダー画像など、多数の画像が使用されることがよくあります。画像が多すぎたり、画像が大きすぎたりすると、ページの読み込み速度に影響し、ユーザー エクスペリエンスが低下することが多いため、画像の遅延読み込みを最適化することが不可欠です。

要件: ブラウザーの表示領域に画像のみを読み込む遅延画像読み込みコマンドを実装します。

アイデア:

  1. 画像の遅延読み込みの原理は、主に、現在の画像が表示領域に到達したかどうかを判断するコア ロジックによって実現されます。
  2. すべての画像を取得します。Dom、各画像を走査して、現在の画像が表示領域の範囲内にあるかどうかを判断します。
  3. 到着した場合は、 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" />

おすすめ

転載: blog.csdn.net/qq_41916378/article/details/111298391