[Vue3] コンポーネントデータの遅延読み込み

コンポーネント データの遅延読み込み - 基本的な使用法

目標: useIntersectionObserver を通じて新鮮な商品と人気のレコメンデーション モジュールを最適化する

電子商取引 Web サイト、特にホームページには複数のコンテンツ画面があり、すべての画面のデータをロードしてすべての画面のコンテンツをレンダリングすると、ホームページの読み込みが非常に遅くなります。

データの遅延読み込み: コンポーネントが正式に表示領域に入ると、コンポーネント内の ajax リクエストが開始されます。それ以外の場合、データはリクエストされません。

(1) 生鮮品の最適化

<script lang="ts" setup>
const {
    
     home } = useStore()
const target = ref(null)
const {
    
     stop } = useIntersectionObserver(target, ([{
    
     isIntersecting }]) => {
    
    
  console.log(isIntersecting)
  // isIntersecting 是否进入可视区域,true是进入 false是移出
  if (isIntersecting) {
    
    
    home.getNewList()
    stop()
  }
})
</script>

<template>
  <div class="home-new">
    <HomePanel ref="target" title="新鲜好物" sub-title="新鲜出炉 品质靠谱">
    </HomePanel>
  </div>
</template>

(2) 人気レコメンデーションの最適化

<script lang="ts" setup>
const {
    
     home } = useStore()
const target = ref(null)
const {
    
     stop } = useIntersectionObserver(target, ([{
    
     isIntersecting }]) => {
    
    
  console.log(isIntersecting)
  // isIntersecting 是否进入可视区域,true是进入 false是移出
  if (isIntersecting) {
    
    
    home.getHotList()
    stop()
  }
})
</script>
<template>
  <HomePanel ref="target" title="人气推荐" sub-title="人气爆款 不容错过">

  </HomePanel>
</template>

コンポーネントタイプをrefに追加

参考リンク:https://staging-cn.vuejs.org/guide/typescript/composition-api.html#typing-component-template-refs

<!-- App.vue -->
<script setup lang="ts">
import MyModal from './MyModal.vue'

const modal = ref<InstanceType<typeof MyModal> | null>(null)

const openModal = () => {
    
    
  modal.value?.open()
}
</script>

コンポーネントデータの遅延読み込み - カプセル化

目標: コンポーネント データの遅延読み込みと再利用可能なロジックをカプセル化する

分析する

ホームページでは、コンポーネントデータの遅延読み込みを多くの場所で使用する必要がありますが、どのモジュールを使用しても、次のコードが繰り返し記述されます。

実際、ビジネス用途で変更される可能性がある唯一のことは、ajax インターフェイスの呼び出しです。

残りを再利用し、再利用可能なロジックに抽出します

コアコード:

(1) 一般的な遅延読み込みデータ API をカプセル化するsrc/utils/hooks.ts

// 自定义一些通用的compositions api
import {
    
     useIntersectionObserver } from '@vueuse/core'
import {
    
     ref } from 'vue'

// 封装通用的数据懒加载api
export function useLazyData(apiFn: () => void) {
    
    
  // 通过 ref 获得组件实例
  const target = ref(null)
  const {
    
     stop } = useIntersectionObserver(
    // target 是观察的目标dom容器,必须是dom容器,而且是vue3.0方式绑定的dom对象
    target,
    // isIntersecting 是否进入可视区域,true是进入 false是移出
    // observerElement 被观察的dom
    ([{
     
      isIntersecting }]) => {
    
    
      // 在此处可根据isIntersecting来判断,然后做业务
      if (isIntersecting) {
    
    
        stop()
        apiFn()
      }
    }
  )
  return target
}

(2) 生鮮品の最適化

<script lang="ts" setup>
const target = useLazyData(() => {
    
    
  home.getNewList()
})
</script>
<template>
  <div class="home-new">
    <HomePanel ref="target" title="新鲜好物" sub-title="新鲜出炉 品质靠谱">
    </HomePanel>
  </div>
</template>

(3) 人気レコメンデーションの最適化

<script lang="ts" setup>
const target = useLazyData(() => {
    
    
  home.getHotList()
})
</script>
<template>
  <HomePanel ref="target" title="人气推荐" sub-title="人气爆款 不容错过">
  </HomePanel>
</template>

小さな知識を広げる: カスタム Lazyhook 型の最適化

export function useLazyApi(apiFn: () => void) {
    
    
  const target = ref<MaybeElementRef | null>(null)
  const {
    
    stop} = useIntersectionObserver(target, ([{
    
    isIntersecting}]) => {
    
    
    if (isIntersecting) {
    
    
      stop()
      apiFn()
    }
  })
  return target
}

ref タイプのヒントを追加しました:MaybeElementRef -> 割り当てタイプが間違っている場合、公開されたターゲットはプロンプトを表示します

ここに画像の説明を挿入

では、MaybeElementRef がどのような型であるかを見てみましょう。

declare type MaybeElementRef<T extends MaybeElement = MaybeElement> = MaybeRef<T>;
declare type MaybeElement = HTMLElement | SVGElement | VueInstance | undefined | null;
declare type MaybeRef<T> = T | Ref<T>;

要約すると、MaybeElementRef 型の型は次のとおりです。

  • MayElement の Ref 型
  • または、MayBeElement タイプに対して直接

ホームページ本体 - 製品のスクロール読み込みのバグ

  • データをロードするには、製品領域をさらにスクロールする必要があります。
  • しきい値 コンテナと表示領域の比率 (入力された領域/コンテナの完全な領域) 値、0 ~ 1、デフォルトは 0 より大きいため、入力イベントをトリガーするにはさらに多くのスクロールが必要です目に見える領域。閾値(進入面積/コンテナ全面積)
const {
    
     stop } = useIntersectionObserver(
  target,
  ([{
     
      isIntersecting }], observerElement) => {
    
    
    if (isIntersecting) {
    
    
      stop()
      // 调用API获取数据
      apiFn().then(data => {
    
    
        result.value = data.result
      })
    }
  },
  {
    
    
    threshold: 0
  }
)
rElement) => {
    
    
    if (isIntersecting) {
    
    
      stop()
      // 调用API获取数据
      apiFn().then(data => {
    
    
        result.value = data.result
      })
    }
  },
  {
    
    
    threshold: 0
  }
)

おすすめ

転載: blog.csdn.net/weixin_46862327/article/details/129114478