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

    陆陆续续学习ABP框架有一段时间了,阳光铭睿的入门教程和HK Zhang的源码分析文章对我的学习帮助都很大.之所以会花这么大工夫去学习ABP.看ABP的源代码,一是因为本人对于DDD也非常有兴趣,AB ...

  2. window7 下配置python2.7+tornado3.3开发环境

    玩python的人大都在linux下进行开发,由于长期习惯在windows下开发代码,今天蛋疼尝试在window7下配置python2.7+tornado3.3开发环境,必然的中间遇到各种报错,但是最 ...

  3. CHNetRequest网络请求

    Paste JSON as Code • quicktype 软件的使用 iOS开发:官方自带的JSON使用 JSON 数据解析 XML 数据解析 Plist 数据解析 NetRequest 网络数据 ...

  4. Mysql初识数据库《二》数据库管理软件的由来

    数据库管理软件的由来 基于我们之前所学,数据要想永久保存,都是保存于文件中,毫无疑问,一个文件仅仅只能存在于某一台机器上. 如果我们暂且忽略直接基于文件来存取数据的效率问题,并且假设程序所有的组件都运 ...

  5. Jmeter_实现Excel文件导出到本地

    一般而言,对于页面的“导出”操作,主要经历如下两个操作:①根据数据库的内容,将文件导出到应用服务器上:②将服务器上的文件下载到本地电脑: Jmeter同LoadRunner类似,只能记录服务端与客户端 ...

  6. numpy常用功能总结、python格式化输入输出

    #coding:utf-8 #author:徐卜灵 ##################### #由于在各大公司笔试的时候总是会遇到一些格式化输入输出数据,今天就来总结一下. #结合numpy来处理数 ...

  7. Python3入门之软件安装

    获得更多资料欢迎进入我的网站或者 csdn或者博客园 最近将我的Python笔记整理下,希望能对他人有所帮助,这是第一课,安装入门篇: windows下安装Python 1.下载,从这里下载:[下载链 ...

  8. Eclipse中文件夹变成包的解决办法(python版)

    问题展示如下: 如图,框中的三个文件夹都变成了包的样子. 解决方法如下: 1.在项目文件夹上右键,打开属性框 2.将PYTHONPATH中,Source Folders中的文件夹都删除.即可看到包已变 ...

  9. (STM32F4) 精準的Delay不透過Timer

    從一個厲害的國外工程師看來的delay寫法,使用while loop會使用幾個指令去計算,可能會需要多少時間. while(variable--); 這行代碼執行一次預估會消耗MCU 4 clock ...

  10. 扩展jQuery---选中指定索引的文本

    <script type="text/javascript"> //1.扩展jQuery $.fn.selectRange = function (start, end ...