最近遇到一个轮播需求:
1. ajax 请求服务器, 返回 json, 判断 json 数据里每一项中 isFix 属性是 0 还是 1,0 表示不轮播, 1 表示需要轮播.
2. 当 isFix 属性为 0 的时候, 表示该图片不轮播, 相反, isFix 为 1 的时候, 表示该图片需要轮播
3. 屏幕最多容纳 6 个图片, 并且每个图片都有边距. 不固定高度, 自适应宽度.
4. 不轮播的图片固定在左边, 轮播的图片需要在右边轮播, 每次轮播的距离为一张图片的宽度和间距
5. 图片宽高不固定, 反正一行最多 6 个.
6. 兼容 IE8
我的思路是:
1. ajax 请求的时候, 分两次把轮播和不轮播的图片 append 到 100% 宽度的 div 中,
2. 从要轮播图片的第一张开始到最后一张, 把这些图片 append 到 100% 减去不轮播图片所占据的宽度的 div 中
3. 最后再用 margin-left 来实现轮播效果.
实现的效果:
总共 10 个图片, 请求到的数据是其中三个不轮播, 剩下 7 个轮播, 由于一行只能显示 6 个, 所以显示的应该是 3 个在轮播.
在实现的过程中, 我需要去获取装轮播图 div 的高度. 而获取高度肯定需要在图片加载完才能正确获取到, 所以我选择了在 window.onload=function(){} 操作获取图片高度.
然而, 遇到了如下的问题:
第一个问题: 第一次运行程序时竟然不执行 window.onload 里面的内容???why???
产生原因: 不管是外链 js 还是页面中的 js, 所有的 window.onload=function(){} 都只有一个且是最后一个生效, 后面的会覆盖前面的. 我其它 js 文件里有 window.onload, 而这个轮播的 js 文件要比另一个先引入, 所以这个不执行.
解决办法: 既然只能有一个 window.onload, 那么我换成 $(window).load(function (){}) 不就行了吗? 真机智......
第二个问题: 换成 $(window).load(function (){}) 之后, 在其它浏览器中能正确获取高度, 而在火狐浏览器中, 有时候能获取到高度, 有时候却给我返回 null...??? 这又是什么鬼
产生原因: 返回 null, 说明并没有找到该元素. 而 ajax 请求是异步, 意思就是在请求成功之前, 还能执行下面的代码. 所以在 ajax 请求成功, 把图片 append 到 div 中之前就已经执行到获取高度的 js 代码了.
解决办法: 把 ajax 的 async 属性设置为 false 即同步请求数据. 啊...... 真个世界清静了.
为了防止 ajax 同步请求时不能执行下面的 js, 所以我把这个 js 文件放到最后, 以免请求时间过长时, 阻塞下面的 js 加载..
总结:
1. window.onload=function(){} 是等待所有的内容都加载完之后执行, 比如图片, 内容, js,CSS 等.
2. $(function(){}), 是等待 DOM 加载完之后执行 (我的理解是标签绘制完毕之后), 图片未加载完时也能执行.
3. $(function(){}) 是 $(document).ready(function(){}) 的简写方式, 功能是一样的.
4. $(window).load(function (){}) 也是等待所有的内容都加载完之后执行.
5. 不管是外链 js 还是页面中的 js 的 window.onload 都只执行最后的一个
6. $(window).load(function (){}) 可以有多个, 而且都是顺序执行.
扩展:
如果要 js 实现多个 window.onload 的方式
1. 在 body 中调用多个函数
<body onload="f1();f2();f3();">
</body>
这种方式和下面这种方式是一样的.
- function f1(){...}
- function f2(){...}
- window.onload=function(){
- f1();
- f2();
- }
显然, 这种方式不太可取. 毕竟不能把所有页面的 function 都聚在一堆.
2. 判断 window.onload 是否已经执行了一次, 如果是的话, 就把原来执行的 window.onload 函数按照方式 1 来处理. 这样就不会覆盖了
- function f1(){...}
- function f2(){...}
- function moreLoad(fn) {
- var winLoad = window.onload;
- if (typeof window.onload != 'function') {
- window.onload = fn;
- } else {
- window.onload = function() {
- winLoad ();
- fn();
- }
- }
- }
- moreLoad(f1)
- moreLoad(f2)
3. 采用事件监听, ie8 以及 ie8 以下为 attachEvent, 其它的为 addEventListener. 这样也不会覆盖
- function f3(){
- alert("f3")
- }
- function f4(){
- alert("f4")
- }
- function win_load(callBack){
- if (window.attachEvent) {
- window.attachEvent("onload", callBack);
- } else if (window.addEventListener) {
- window.addEventListener("load", callBack);
- }
- }
- win_load(f3)
- win_load(f4)
注意:
1. ie 监听加载事件是 onload, 而其它的是 load .addEventListener 本来还有第三个参数, 可选, 表示指定事件是否在捕获或冒泡阶段执行. 默认为 false, 所以这里就不用写上去.
2. ie 的 attachEvent 里面绑定多个事件的执行顺序是不一样的, 如上面的例子, IE 中是先执行 f4 函数, 再执行 f3 函数, 倒着执行的. 而 addEventListener 是正常的
最后说一下加载顺序: 假如我在当前页面引入了两个 js 文件, 一个 a.js 一个 b.js, 分别都有 window.onload,$(function(){}), $(window).load(function (){})
执行的顺序是:
1. 先以 a.js,b.js 的顺序执行 a.js 中未包含在 window.onload 与 $(function(){}) 和 $(window).load(function (){}) 中的代码.
2. 然后再执行 $(function(){}) 里面的代码,
3. 然后以 a.js,b.js 的顺序, 执行 $(window).load(function (){}) 里面的代码,
4. 最后执行最后一个 js 中 window.onload 里面的代码
但是!!! 在火狐和 IE 浏览器中, window.onload 的执行顺序要高于 $(window).load(function (){}), 其它浏览器的加载顺序都是一样的. 这个我就理解不了了......
来源: https://www.cnblogs.com/zjjDaily/p/9077736.html