众所周知,对于页面内容比较丰富的网站,dom的解析会很复杂,这样就会致使首屏加载过慢,对于图片很丰富的网站,咱们知道可使用图片懒加载来提升网站的响应速度,我在个人另一篇文章中写过,有兴趣的点击这里。像淘宝、京东等等的首页都是通过懒加载处理的,他们会先渲染出骨架,而后懒加载的区域出如今了可视范围的时候再把骨架替换为真实的内容。vue
骨架: node
真实内容:api
这样就避免首页一次性加载过多的内容浏览器须要渲染过多的dom致使的卡慢, 同时图片也懒加载了,避免下载图片致使的dom渲染阻塞,可谓一举而两得,那么在vue中,咱们怎么作懒加载呢?这里分享下我作的项目当中,利用vue的mixin作的懒加载。浏览器
关于vue mixin,我想你们都知道vue mixin的做用,我的以为它最大的用处就是共享一些数据data
和方法methods
,从而实现代码重用。居于它的做用,我选择mixin做为实现懒加载的手段,全部须要懒加载的模块,都导入懒加载所须要的mixin。bash
咱们知道vue的v-if
能够决定是否要渲染该组件,因此咱们利用v-if来控制懒加载的组件,若是这个组件不在可视区域,则将其设为false,或者让它渲染骨架,当组件出如今可视区域的时候再去渲染真实的dom。dom
判断组件是否出如今可视区域有两种手段:
1、是利用元素的getBoundingClientRect
方法获取元素所处的位置,而后判断top属性是否大于0到window.innerHeight之间,而且须要监听页面的scroll事件,不断进行上述判断,想要了解更多的,请阅读我开头说的图片懒加载实现方式。
2、利用新特性IntersectionObserver
,这个特性不须要咱们去监听滚动事件,只要元素出如今视线,就会触发可见的事件post
if ("IntersectionObserver" in window) {
let lazyCompObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
// 元素可见
if (entry.intersectionRatio > 0) {
// TODO 进行一些元素可见后的一些操做,同时该元素不须要被observe了
lazyCompObserver.unobserve(entry.target)
}
})
})
if(this.$el.nodeType === 1) {
// 须要observe的元素
lazyCompObserver.observe(this.$el)
}
}
复制代码
综上所述,咱们实现懒加载的mixin是这样写的网站
// lazy-load mixin
import {throttle, getClientHeight} from 'tool/tool'
export default {
data() {
return {
isShow: false,
_throttleFn: null
}
},
methods: {
inViewShow() {
if(this.isShow) {
document.removeEventListener('scroll', this._throttleFn, false)
return
}
// 不支持IntersectionObserver api的状况下判断图片是否出如今可视区域内
let { $el } = this
const rect = $el.getBoundingClientRect()
// 出如今视野的时候加载元素
if(0 < rect.top && rect.top < getClientHeight()) {
this.isShow = true
}
}
},
mounted() {
// 支持IntersectionObserver的使用这个api
if ("IntersectionObserver" in window) {
let lazyCompObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.intersectionRatio > 0) {
this.isShow = true
lazyCompObserver.unobserve(entry.target)
// 当元素可见时,若是须要回调,则执行
this.onVisible && this.onVisible()
}
})
})
if(this.$el.nodeType === 1) {
lazyCompObserver.observe(this.$el)
}
} else {
// 不支持的使用getBoundingClientRect和scroll来判断
this.inViewShow()
this._throttleFn = throttle(this.inViewShow)
document.addEventListener('scroll', this._throttleFn, false)
}
}
}
// 调用
<template>
<li v-if="isShow">
.....
</li>
</template>
<script>
import lazyLoad from 'mixins/lazy-load'
export default {
mixins: [lazyLoad],
methods: {
onVisible() {
console.log('元素可见了')
}
}
}
</script>
复制代码
效果就是这样 第一个li是可见的,第二个li不可见,因此不渲染。ui
有不对或者改正的地方,忘各位留言指正。this