15.Home-图片懒加载指令实现

发布于:2025-08-09 ⋅ 阅读:(18) ⋅ 点赞:(0)

场景和指令用法

实现思路和步骤

1.熟悉指令语法

2.3.4判断图片是否进入视口并测试

过程

用法

<script setup lang="ts">
import { useIntersectionObserver } from '@vueuse/core'
import { shallowRef, useTemplateRef } from 'vue'

const target = useTemplateRef<HTMLDivElement>('target')
const targetIsVisible = shallowRef(false)

const { stop } = useIntersectionObserver(
  target,
  ([entry], observerElement) => {
    targetIsVisible.value = entry?.isIntersecting || false
  },
)
</script>

<template>
  <div ref="target">
    <h1>Hello world</h1>
  </div>
</template>

指令用法

<script setup lang="ts">
import { vIntersectionObserver } from '@vueuse/components'
import { shallowRef, useTemplateRef } from 'vue'

const root = useTemplateRef<HTMLDivElement>('root')

const isVisible = shallowRef(false)

function onIntersectionObserver([entry]: IntersectionObserverEntry[]) {
  isVisible.value = entry?.isIntersecting || false
}
</script>

<template>
  <div>
    <p>
      Scroll me down!
    </p>
    <div v-intersection-observer="onIntersectionObserver">
      <p>Hello world!</p>
    </div>
  </div>

  <!-- with options -->
  <div ref="root">
    <p>
      Scroll me down!
    </p>
    <div v-intersection-observer="[onIntersectionObserver, { root }]">
      <p>Hello world!</p>
    </div>
  </div>
</template>
代码
import {createApp} from 'vue'
import {createPinia} from 'pinia'
import App from 'App.vue'
import router from './router'

//引入初始化样式文件
import '@/styles/common.scss'

//先导入进来
import { useIntersectionObserver } from '@vueuse/core'
const app = createApp(App)

app.use(createPinia())
app.use(router)
app.mount('#app')

//定义全局指令
app.directive('img-lazy',{
  mounted(el,binding) {
    //el:指令绑定的元素 img
    //binding:binding.value 指令等于号后面绑定的表达式的值 图片url
    console.log(el,binding.value)
    useIntersectionObserve(
      el,
      //isIntersecting是一个布尔值
      ([{isIntersecting}]) => {
        console.log(isIntersecting)
      },
      )
  
    
  }
})

判断出来了

5.如果图片进入视口,发送图片资源请求

import {createApp} from 'vue'
import {createPinia} from 'pinia'
import App from 'App.vue'
import router from './router'

//引入初始化样式文件
import '@/styles/common.scss'

//先导入进来
import { useIntersectionObserver } from '@vueuse/core'
const app = createApp(App)

app.use(createPinia())
app.use(router)
app.mount('#app')

//定义全局指令
app.directive('img-lazy',{
  mounted(el,binding) {
    //el:指令绑定的元素 img
    //binding:binding.value 指令等于号后面绑定的表达式的值 图片url
    console.log(el,binding.value)
    useIntersectionObserve(
      el,
      //isIntersecting是一个布尔值
      ([{isIntersecting}]) => {
        console.log(isIntersecting)
        if(isIntersecting) {
          //进入视口区域
          el.src=binding.value
        }
      },
      )
    
  }
})
<script setup>
  import HomePanel from './HomePanel.vue'
  import {findNewAPI} from '@/apis/home'

//获取数据
const newlist = ref([])

const getNewList = async() => {
  const res = await findNewAPI()
    newList.value = res.result
}
  onMounted(() => getNewList())
</script>

<template>
  <homePanel title="新鲜好物" sub-title="新鲜出炉 品质靠谱">
    <ul class="goods-list">
    <li v-for="item in newList" :key="item.id">
      <RouterLink to="/">
        <img v-img-lazy="item.picture"  alt="" />
        <p class="name">{{ item.name }}</p>
        <p class="price">&yen;{{ item.price }}</p>
      </RouterLink>
    </li>
  </ul>
  </HomePanel>
  // <!-- 下面是插槽主体内容模版
  // <ul class="goods-list">
  //   <li v-for="item in newList" :key="item.id">
  //     <RouterLink to="/">
  //       <img :src="item.picture" alt="" />
  //       <p class="name">{{ item.name }}</p>
  //       <p class="price">&yen;{{ item.price }}</p>
  //     </RouterLink>
  //   </li>
  // </ul>
  // -->
</template>


<style scoped lang='scss'>
.goods-list {
  display: flex;
  justify-content: space-between;
  height: 406px;

  li {
    width: 306px;
    height: 406px;

    background: #f0f9f4;
    transition: all .5s;

    &:hover {
      transform: translate3d(0, -3px, 0);
      box-shadow: 0 3px 8px rgb(0 0 0 / 20%);
    }

    img {
      width: 306px;
      height: 306px;
    }

    p {
      font-size: 22px;
      padding-top: 12px;
      text-align: center;
      text-overflow: ellipsis;
      overflow: hidden;
      white-space: nowrap;
    }

    .price {
      color: $priceColor;
    }
  }
}
</style>

回顾核心步骤代码


网站公告

今日签到

点亮在社区的每一天
去签到