github项目地址: github.com/murongg/vue…

求star 与 issues

我文采不好,可能写的文章不咋样,有什么问题可以在留言区评论,我会尽力解答

本项目已经发布到npm

安装:

$ npm i vue3-lazyload
# or
$ yarn add vue3-lazyload

需求分析

  • 支持自定义 loading 图片,图片加载状态时使用此图片
  • 支持自定义 error 图片,图片加载失败后使用此图片
  • 支持 lifecycle hooks,类似于 vue 的生命周期,并同时在 img 标签绑定 lazy 属性,类似于
<img src="/UploadFiles/2021-04-02/...">

并支持:

 img[lazy=loading] {
  /*your style here*/
 }
 img[lazy=error] {
  /*your style here*/
 }
 img[lazy=loaded] {
  /*your style here*/
 }

支持使用 v-lazy 自定义指令,指定可传入 string/object ,当为 string 时,默认为需要加载的 url,当为 object 时,可传入

  • src: 当前需要加载的图片 url
  • loading: 加载状态时所用到的图片
  • error: 加载失败时所用到的图片
  • lifecycle: 本次 lazy 的生命周期,替换掉全局生命周期

目录结构

- src
---- index.ts 入口文件,主要用来注册插件
---- lazy.ts 懒加载主要功能
---- types.ts 类型文件,包括 interface/type/enum 等等
---- util.ts 共享工具文件

编写懒加载类

懒加载主要通过 IntersectionObserver对象实现,可能有些浏览器不支持,暂未做兼容。

确定注册插件时传入的参数

export interface LazyOptions {
 error"_blank" href="https://v3.vuejs.org/guide/custom-directive.html#intro" rel="external nofollow" >Custom Directives,支持以下 Hook Functions:beforeMountmountedbeforeUpdateupdatedbeforeUnmountunmounted,具体释义可以去 vue3 文档查看,目前仅需要用到mountedupdatedunmounted,这三个 Hook。

Lazy 类基础框架代码,lazy.ts

export default class Lazy {
 public options: LazyOptions = {
  loading: DEFAULT_LOADING,
  error: DEFAULT_ERROR,
  observerOptions: DEFAULT_OBSERVER_OPTIONS,
  log: true,
  lifecycle: {}
 };
 constructor(options"htmlcode">
 /**
  * mount
  *
  * @param {HTMLElement} el
  * @param {DirectiveBinding<string>} binding
  * @memberof Lazy
  */
 public mount(el: HTMLElement, binding: DirectiveBinding<string | ValueFormatterObject>): void {
  this._image = el
  const { src, loading, error, lifecycle } = this._valueFormatter(binding.value)
  this._lifecycle(LifecycleEnum.LOADING, lifecycle)
  this._image.setAttribute('src', loading || DEFAULT_LOADING)
  if (!hasIntersectionObserver) {
   this.loadImages(el, src, error, lifecycle)
   this._log(() => {
    throw new Error('Not support IntersectionObserver!')
   })
  }
  this._initIntersectionObserver(el, src, error, lifecycle)
 }
 
 /**
  * force loading
  *
  * @param {HTMLElement} el
  * @param {string} src
  * @memberof Lazy
  */
 public loadImages(el: HTMLElement, src: string, error"htmlcode">
 /**
  * update
  *
  * @param {HTMLElement} el
  * @memberof Lazy
  */
 public update(el: HTMLElement, binding: DirectiveBinding<string | ValueFormatterObject>): void {  
  this._observer.unobserve(el)
  const { src, error, lifecycle } = this._valueFormatter(binding.value)
  this._initIntersectionObserver(el, src, error, lifecycle)
 }

编写 unmount hook

 /**
  * unmount
  *
  * @param {HTMLElement} el
  * @memberof Lazy
  */
 public unmount(el: HTMLElement): void {
  this._observer.unobserve(el)
 }

在 index.ts 编写注册插件需要用到的 install 方法

import Lazy from './lazy'
import { App } from 'vue'
import { LazyOptions } from './types'

export default {
 /**
  * install plugin
  *
  * @param {App} Vue
  * @param {LazyOptions} options
  */
 install (Vue: App, options: LazyOptions): void {
  const lazy = new Lazy(options)

  Vue.config.globalProperties.$Lazyload = lazy
  // 留着备用,为了兼容$Lazyload
  // 选项api,可以通过this.$Lazyload获取到Lazy类的实例,组合api我还不知道怎么获取
  // 所以通过 provide 来实现此需求
  // 使用方式 const useLazylaod = inject('Lazyload')
  Vue.provide('Lazyload', lazy)
  Vue.directive('lazy', {
   mounted: lazy.mount.bind(lazy),
   updated: lazy.update.bind(lazy),
   unmounted: lazy.unmount.bind(lazy)
  })
 }
}

使用插件

import { createApp } from 'vue'
import App from './App.vue'
import VueLazyLoad from '../src/index'

const app = createApp(App)
app.use(VueLazyLoad, {
 log: true,
 lifecycle: {
  loading: () => {
   console.log('loading')
  },
  error: () => {
   console.log('error')
  },
  loaded: () => {
   console.log('loaded')
  }
 }
})
app.mount('#app')

App.vue:

<template>
 <div class="margin" />
 <img v-lazy="'/example/assets/logo.png'" alt="Vue logo" width="100">
 <img v-lazy="{src: errorlazy.src, lifecycle: errorlazy.lifecycle}" alt="Vue logo" class="image" width="100"> 
 <button @click="change">
  change
 </button>
</template>

<script>
import { reactive } from 'vue'
export default {
 name: 'App',
 setup() {
  const errorlazy = reactive({
   src: '/example/assets/log1o.png',
   lifecycle: {
    loading: () => {
     console.log('image loading')
    },
    error: () => {
     console.log('image error')
    },
    loaded: () => {
     console.log('image loaded')
    }
   }
  })
  const change = () => {
   errorlazy.src = 'http://t8.baidu.com/it/u=3571592872,3353494284&fm=79&app=86&size=h300&n=0&g=4n&f=jpeg?sec=1603764281&t=bedd2d52d62e141cbb08c462183601c7'
  }
  return {
   errorlazy,
   change
  }
 }
}
</script>

<style>
.margin {
 margin-top: 1000px;
}
.image[lazy=loading] {
 background: goldenrod;
}
.image[lazy=error] {
 background: red;
}
.image[lazy=loaded] {
 background: green;
}
</style>

以上就是vue3+typescript实现图片懒加载插件的详细内容,更多关于vue3 图片懒加载的资料请关注其它相关文章!

广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!

稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!

昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。

这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。

而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?