当我们进入首页时,可能有很多条目需要显示,但是如果条目太多,我们全部将之显示出来就会造成性能的消耗,比如,我在第一条就找到了需要的或者我就看前面两条我就不想看后面的了,所以,这时候如果使用全部加载的方式无疑是不合适的,比较好的做法就是首先显示一面多的内容,当检测到用户快要(或者已经)下拉到页面底部的时候我们再发出ajax请求来请求更多的内容。

  

那么,第一步需要做的工作就是如何判断何时用户将页面拉到了底部。

  body是滚动的wrap,我们可以获得浏览器的高度、body的scrollTop、以及body的scrollHeight, 如果浏览器的高度 + body的scrollTop接近(达到)body的scrollHeight的值得时候,那么说明快要达到底部了。

如何获取浏览器的高度:

function getViewportSize () {
return {
width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
};
}

这里使用 window.innerWidth 可以准确的获取到浏览器的宽度,通过 window.innerHeight 可以准确的获取到浏览器的高度。

但是当用户缩放时window.innerWidth和window.innerHeight的值都会发生变化。其他的也是一样的。

只是我在做微信网页的时候发现,两者的值时不同的,只有 window.innerHeight才能获取到准确的值,

可以看到,这时的body并没有占满一页,所以这时获得的高度必然不是浏览器的高度。 值得注意,至于为什么,后续我会继续研究。

        let windowHeight = window.innerHeight; // 1334px
let scrollTop = $('body')[].scrollTop; // 如果在没有滚动的情况下就是0
let scrollHeight = $('body')[].scrollHeight; // 即总的高度。如果在不超过一整页的情况下得到的也是
console.log(windowHeight + scrollTop);
console.log(scrollHeight); if ((windowHeight + scrollTop) + >= scrollHeight) {
console.log("start");
}

如上所示: 我们使用 window.innerHeight 得到浏览器的高度, 使用 scrollTop 得到滚动被卷起来的高度, 使用 scrollHeight 得到页面的总高度。

如果 windowHeight + scrollTop + 50 大于 scrollHeight 时, 说明到底部了,这里 + 50 是因为这样不会一直到最底下才开始,而是快到的时候就开始,用户体验会好一些。

接下来就是如何监测高度的变化

  即我们怎么知道到达底部呢?

  有两种方法  

方法一:使用setInterval定时器来每个一段时间(比如500ms)就循环一次,获取到各种高度,判断是否达到最底部,然后进行相应的懒加载代码, 优点:对浏览器的支持都比较好,所以用起来不会有太大问题。 缺点1:无论我们是否在滑动,定时器在不断的执行,虽然对性能的影响不是很大,但是很明显,这不是他该发挥的地方。缺点二、setInterval只是对某一段函数的重复执行,但是对于我目前的项目而言(即不同种类下的商品都会滚动)显然是需要写多次的。

方法二: 使用onscroll事件, jqury是支持的,但是zepto不支持,所以说我们直接用原生的更好, window.addEventListener("scroll", function () {}, false);即可。 优点1:语义明确,充分发挥了各自的作用。 比较灵敏。 优点2:因为window.addEventListener() 是将scroll事件绑定到了window上,所以这时全局的,在哪里都可以使用,就像RN的write once , run everywhere。   缺点: 据说,其在ios设备上的触发是在 滑动之后, 而不是滑动一开始就触发, 但对于本项目的懒加载功能是没有影响的。

在移动端,这里使用 ontouchmove 事件处理程序的效果要好一些,因为如果使用scroll,当用户已经拉到了底部的时候,这时候可能就不会触发scroll了,而 touchmove 是一定会触发的。

对,最终选用第二种方法, 如下所示:

   window.addEventListener('scroll', function(e) {
let windowHeight = window.innerHeight; // 1334px
let scrollTop = $('body')[].scrollTop; // 如果在没有滚动的情况下就是0
let scrollHeight = $('body')[].scrollHeight; // 即总的高度。如果在不超过一整页的情况下得到的也是
console.log(windowHeight + scrollTop);
console.log(scrollHeight); if ((windowHeight + scrollTop) + >= scrollHeight) {
console.log("start ajax request");
}
});

注意: 这里加 50 还是加一个别的数字,这是一个技巧,要根据情况进行设定, 比如我们希望还没有到底就可以开始加载更多了,就可以多加一些,如果希望到底部才加载更多,就设置加10或者5甚至不加都是可以的

第三步就是需要开始请求更多的数据了

      if ((windowHeight + scrollTop) +  >= scrollHeight) {
console.log("start");
var contentObj = {
id: that.$store.state.items[that.$store.state.curIndex].id,
index: that.$store.state.curIndex,
offset: (that.$store.state.offsets[that.$store.state.curIndex] + )
}
that.getMoreCurContent(contentObj);
}

即当满足某一个条件时,我就可以向后台发送请求了,这里的函数 that.getMoreCurContentactions中的,因为异步请求我们一般都放在actions里。

但是这样存在一个问题: 显然在我向下拉的时候, 满足这个条件的情况不只一次,那么就会导致: that.getMoreCurContent被发送了很多次

所以为了解决这个问题,我们需要立一个flag,判定是否能进行, 比如,在 state 中我们添加一个 process 数组,数组的长度就是分类的长度,每一个都是一个布尔值,我们一旦发送一个请求,就设置这个布尔值为true,设置了之后,直到请求成功,我们再设置为false,并且如果说,我们之前设定的pageSize为10, 而这次获取的数据为10的情况下才能让 process[某个分类的index]设置为false,如果不为10, 说明没有更多的数据了,那么我们同样在else语句下设置为true即可,这样,就不会再请求了。 

这里有一个好处是 --- 一旦我们将 process 设置为一个数组,那么每个分类的请求之间就相互不会影响了, 而到每一个分类下,我们只需要一个 state.curIndex 来处理当前即可。 因为他们用的是不同的函数。

如下所示:

 created () {
var that = this;
window.addEventListener('scroll', function(e) {
let windowHeight = window.innerHeight;
let scrollTop = $('body')[].scrollTop;
let scrollHeight = $('body')[].scrollHeight;
console.log(windowHeight + scrollTop);
console.log(scrollHeight); if ((windowHeight + scrollTop) + >= scrollHeight) {
console.log("start");
var contentObj = {
id: that.$store.state.items[that.$store.state.curIndex].id, index: that.$store.state.curIndex,
offset: (that.$store.state.offsets[that.$store.state.curIndex] + )
}
// 表示正在进行中时,不再请求,
if (that.$store.state.process[that.$store.state.curIndex] == true) {
       // 什么都不做,所以这里不需要这样写,只是这样可能会比较好理解一些。
} else {
that.getMoreCurContent(contentObj);
} }
});
}

即进入之后,我们就开始监控了, 这里的offsets 也是一个数组,他的好处是可以做到互不影响

 getMoreCurContent ({commit, state}, contentObj) {
// 设置 that.$store.state.process == true
var boolObj = {
index: contentObj.index,
bool: true
}
commit(UPDATE_PROCESS, boolObj);
var items = state.items;
var content = {
"isSingle": ,
"sbid": ,
"catalog3": contentObj.id,
"offset": contentObj.offset,
"pageSize":
}; axios.post('/bbg/goods/get_goods_list_wechat', qs.stringify({"data": JSON.stringify(content)}))
.then(function (response) {
if (response.data.code == ) {
if (response.data.data.length > ) {
var a = ;
for (let i = ; i < response.data.data.length; i++) {
var obj = {
index: contentObj.index,
item: response.data.data[i]
};
commit(UPDATE_CONTENT, obj);
a++;
}
if (a == ) {
alert("哈哈");
// 如果等于10,说明还有其他的,那么我们就可以把这个分类的offset增加,继续请求数组,如果说刚好没有数据了,那么就是0,后面也会给出相应的处理的。
var offsetObj = {
index: contentObj.index,
offset: contentObj.offset
}
commit(UPDATE_OFFSET, offsetObj); var boolObj = {
index: contentObj.index,
bool: false
}
commit(UPDATE_PROCESS, boolObj);
} else {
var boolObj = {
index: contentObj.index,
bool: true
}
commit(UPDATE_PROCESS, boolObj);
}
}
}
}).catch(function (error) {
console.log(error);
});
},

两个关键点:

  • 第一: 使用offsets数组作为记录,起到请求更多的作用。
  • 第二: 使用process数组作为记录,起到防止发出多次请求的作用。

遇到的坑:

  • 使用 document.body.clientHeight 和 document.documentElement.clientHeight 得到的高度并不是浏览器的高度(我在vue中确实是这样)。所以使用window.innerHeight 更好一些。 解决方法: 设置 html,body{width: 100%; height: 100%} 可以解决此问题。
  • 使用zepto时,我用$("body").scroll(function () { // doSomeThing }) 时,发现并不奏效,这是因为通过查询api发现zepto并没有支持这个事件, 所以使用zepto时要注意: zepto并没有完全支持jquery的东西。

获取高度。

var pageWidth = window.innerWidth,
pageHeight = window.innerHeight; if ( typeof pageWidth != 'number' ) {
if (document.compatMode == 'CSS1Compat') {
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
} else {
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}

vue懒加载 && 浏览器高度的更多相关文章

  1. 关于Vue懒加载问题

    有关Vue懒加载其实并不是想象的那么难和复杂: 首先引入 import  VueLazyLoad from 'vue-lazyload'; 其次是使用 Vue.use(VueLazyLoad,{ er ...

  2. vue懒加载

    vue懒加载(白屏或者加载慢的解决方法) 懒加载:也叫延迟加载,即在需要的时候进行加载,随用随载. 为什么需要懒加载? 像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异 ...

  3. vue懒加载 路由 router 的编写(resolve)

    如果用import引入的话,当项目打包时路由里的所有component都会打包在一个js中,造成进入首页时,需要加载的内容过多,时间相对比较长.当你用require这种方式引入的时候,会将你的comp ...

  4. vue-lazyload 的vue 懒加载的使用

    vue-lazyload vue 图片懒加载的使用 下载 vue-lazyload npm i vue-lazyload -S 使用 vue-lazyload 在 src 下面的 main.js 的文 ...

  5. 使用Webpack的代码分离实现Vue懒加载(译文)

    当一个Vue的项目体积变得十分庞大的时候,使用Webpack的代码分离功能将Vue Components,routes或Vuex的代码进行分离并按需加载,会极大的提高App的首屏加载速度. 在Vue的 ...

  6. 使用Webpack的代码分离实现Vue懒加载

    当一个Vue的项目体积变得十分庞大的时候,使用Webpack的代码分离功能将Vue Components,routes或Vuex的代码进行分离并按需加载,会极大的提高App的首屏加载速度. 在Vue的 ...

  7. vue懒加载实现

  8. 原生js开发,无依赖、轻量级的现代浏览器图片懒加载插件,适合在移动端开发使用

    优势 1.原生js开发,不依赖任何框架或库 2.支持将各种宽高不一致的图片,自动剪切成默认图片的宽高 比如说你的默认图片是一张正方形的图片,则各种宽度高度不一样的图片,自动剪切成正方形. 完美解决移动 ...

  9. vue 路由懒加载 使用,优化对比

    vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,时间过长,会出啊先长时间的白屏,即使做了loading也是不利于用户体验,而运 ...

随机推荐

  1. Ubuntu16.04修改静态ip地址

    https://blog.csdn.net/mdw5521/article/details/79270035

  2. DOM--sql server

    public List<LianHeData> select(int ID) { List<LianHeData> list = new List<LianHeData& ...

  3. 关于CS0016: Could not write to output file ‘c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Temporary AS

    1.添加用户"Network Service” 和 “IIS_IUSERS” 读下面目录的读写权限 a) C:\Windows\Temp b) C:\Windows\Microsoft.NE ...

  4. C#Task学习

    简介: Task 对象是一种的中心思想基于任务的异步模式首次引入.NET Framework 4 中. 因为由执行工作Task对象通常以异步方式执行线程池线程上而不是以同步方式在主应用程序线程中,可以 ...

  5. subset子集全排序问题

    思路一 可以用递推的思想,观察S=[], S =[1], S = [1, 2] 时解的变化. 可以发现S=[1, 2] 的解就是 把S = [1]的所有解末尾添上2,然后再并上S = [1]里面的原有 ...

  6. PLSQL Developer连接远程Oracle

    注:内容来网络 (一)不安装客户端的解决办法. 第一种方法: 1.在安装ORACLE服务器的机器上搜索下列文件, oci.dll ocijdbc10.dll ociw32.dll orannzsbb1 ...

  7. 微信小程序设计稿pt怎么转rpx

    什么是逻辑分辨率? 什么是物理分辨率? 什么是DPI?(Dots Per Inch) 最早的时候,这个单位是用来描述打印机的性能的,意思是每英寸能打多少个墨点,毫无疑问,DPI越高,打印出来的东西就会 ...

  8. Xcode打包提交至itunes connect后,提交审核成功,随后出现二进制文件无效

    1.问题描述 Xcode打包提交至itunes connect后,提交审核成功,应用处于待审核状态,过了大概半个小时状态更改为二进制文件无效 2.原因分析 2.1 登陆在苹果中预留的邮箱 ---- 邮 ...

  9. JVM之类加载机制

    JVM之类加载机制 JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 类加载五部分 加载 加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这 ...

  10. BZOJ4650/UOJ219 [Noi2016]优秀的拆分

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...