jQuery FlexSlider插件一些使用上的小tips

来源:互联网 发布:怎么汉化英文软件 编辑:程序博客网 时间:2024/04/23 23:27

最近做的一个需求,用到了jQuery FlexSlider这个插件,本以为一个算是已经比较成熟的插件,用起来应该没什么难度,然而真正用起来才发现,其实还是有些坑的,不过好在这个插件源代码写的比较好,比较好看,所以自己多看看也就能弄明白。

网上那些随便一搜就能找到的你抄我我抄你大家互相抄的东西,我就不继续浪费网络资源和自己的时间了,主要是一些网上很难找到的或者比较模棱两可的点,这里以jQuery FlexSlider v2.6.3这个版本为例,总结如下。


回调方法

网上一些提到 flex-slider插件的方法,基本上都是一带而过,而且模棱两可,我估计当时作者不知从哪里看到然后随手 copy下来的时候,连他自己都不知道自己在写些什么。

一共 7个回调函数,如下:

回调函数API

  1. start: function(){}
    源代码里面标注的解释是:当第一个滑块第一次加载完毕后执行。 说白了就是当此组件初始化(init)完成后,然后又当第一个滑块加载完毕后,此函数执行,在当前slider组件的整个生命周期中,只执行一遍。
  2. before: function(){}
    在滑块运动之前的一刻执行,也就是说当你点击切换当前轮播项的时候,此函数会在轮播项开始运动的前一刻执行。
  3. after: function(){}
    和上一个相反,在滑块运动完成的下一刻执行,也就是说当你点击切换当前轮播项的时候,此函数会在轮播项完成运动的下一刻执行。
  4. end: function(){}
    当前整个轮播组件滑动到了最后一个滑块的时候执行,与滑块的运动动作异步并行执行,也就是说是在 beforeafter 函数之间执行,每次到达尾部,此函数都会执行一遍。
  5. added: function(){}
    当新的滑块被追加到轮播组件中后,就会调用此回调函数。
  6. removed: function(){}
    当轮播组件中有滑块被删除掉后,此函数会执行
  7. init: function() {}
    当轮播组件初始化完成后执行,此函数实际上不仅只在开始的时候和执行一遍,如果第一次初始化完后,继续向轮播组件中追加滑块,则此函数还可能会被调用,所以在轮播组件的整个生命周期中,此函数被调用的次数 >= start 函数被调用的次数。

异步获取数据初始化

如果轮播组件的数据是异步获取而来,则很显然在数据尚未获得之前,flex-slider是不能够进行初始化的,否则将会出现异常情况。

对于这种情况,有两种常用的解决手段,一是使用回调函数,二是使用 Promise

通过回调函数初始化组件

首先页面发送获取数据的的请求,当数据成功获取后,再在回调函数中进行 flex-slider的初始化。

如下示例(为了简化代码,使用到了 Jquery库):

$(function(){    getData(){        $.getJSON('http://api.example.com&callback=?', (data)=>{            // 这里可以放初始化`flex-slider`的代码            // ...        })    }})

通过 Promise初始化组件

如果不方便在回调函数中执行 flex-slider组件的初始化才做,或者希望以同步的写法来进行组件的初始化,那么 Promise值得一用。

首先依旧是需要首先请求数据,但是回调函数中不执行初始化操作,而是返回一个 Promise对象:

$(function(){    getData(){        return new Promise((resolve, reject)=> {            $.getJSON('http://api.example.com&callback=?', (data)=>{                // 将获取到的数据当成 `Promise`的参数传回去                resolve(data)            })        })    }})

然后就能保证在初始化 组件之前获取到数据了:

let promiseResult = getData()promiseResult.then((data)=>{    // 这里可以放初始化`flex-slider`的代码    // ...})

当然还可以使用 async函数来完成异步操作的同步操作,如果需要兼容不支持 ES6的浏览器,则最后别忘了使用一些工具将 ES6代码转换成 ES5的形式。


异步增删数据项

如果 flex-slider组件的滑块数量是固定的,而且还不用懒加载,是一次性加载初始化完毕的,那么没什么好说的,但是如果在组件第一次完成初始化后,还将会动态地向组件内增加 slider,也就是滑块的数量是动态变化的,那么就需要用到 flex-slider另外的方法了。

动态追加数据

需要用到 flex-slideraddSlide()方法,此方法代码很简单:

addSlide 方法

要做的事情也很清楚:

首先更新组件的滑块数量,然后重新将组件初始化一遍,最后调用 added()这个回调函数。

addSlide()方法中可以看出,动态增加滑块数量,是会引起组件重新初始化的,所以 init:function(){} 回调函数会执行,这也就解释了为什么 init 并不总是只执行一遍的原因。

从上述代码中可以看到,addSlide()方法其实是放在 slider 对象上的,想用addSlide()方法,就必须要有 slider 对象才行,有人可以不清楚这个slider到底是什么鬼,其实这个对象,可以在前面所说的 7个回调函数中获取,因为这个slider就是那 7个回调函数的参数。

例如:

$("#flexSlider").flexslider({    start(slider): function(){        // 这里就可以使用 addSlide()方法        ...        slider.addSlide(obj, pos);    }})

其他 6个回调函数都有 slider这个函数,和 start一样。

至于 addSlide的两个参数,一个是必选参数obj,第二个则是可选的。

  1. obj
    此参数代表的就是你想要动态追加的滑块 HTML字符串,例如 <li></li>,在被传入 addSlide方法中后,会被自动包装成 Jquery对象。
  2. pos
    你可以通过 此参数来选择将动态插入的滑块HTML插入到原有的一些滑块的什么位置,如果你不传入此参数,则默认追加到原有组件的末尾处。
  • 关于 addSlide方法的简单改进

addSlide的实现方法中可以看到,此方法每次只能动态新增一个滑块,数量每次只能加 1,如果你想一次性新增多个滑块,则必须多次调用此函数,也就会多次执行对 flex-slider的初始化操作,这显然很影响性能。

而且据我测试,连续多次调用此函数,flex-slider的初始化会出现异常,例如无法正确计算出每次滑动的距离,导致组件布局崩溃。

所以我就简单对这个方法改进了一下,让其能够一次性插入多个滑块的DOM,但是却仅在最后重新初始化一次,如下:

改进 addSlider方法

此函数只是将原先每次固定的只能追加一个滑块,变成了能够自由选择数量,其余的一些操作依旧不变。

四个参数中 objpos 的含义和作用和原先一样,至于 slider 则和上面的 slider指的是同一个对象,都是那 7个回调函数的参数,这是为了方便通过此对象来调用我们自己重写的 addSlider 方法,number值得就是你需要新增的滑块数量,默认为 1

用法示例如下:

$("#flexSlider").flexslider({    // 这里我们假设当每次组件滑动到最后一个滑块的时候,就追加新的滑块    // 有点类似于懒加载或者预加载的意思    end(slider): function(){        // 假设每一个 `li`元素,就是一个滑块的单位,这里我们一次性追加了三个滑块的 `DOM`        let str = '<li></li><li></li><li></li>'        // 调用我们重写的 addSlide() 方法,这里我们一次性新增了三个滑块,        // 所以传入数字 3        addSlide(slider, str, 3);    }})
  • 追加滑块时出现的问题

如果是理想情况下,新增滑块的数据是通过同步方法一次性顺序获得,那么一切正常。

但不知是不是我用法不太对,如果是通过异步请求数据的方法来取得新增滑块的数据,无论我是通过 flex-slider提供的 addSlide方法,正常地每次新增一个滑块,还是使用自己改进的 addSlide方法来一次性新增多个滑块,亦或是我通过回调函数还是 Promise的方法来请求异步数据,甚至我把新增滑块的动作,在 7个回调函数中都试了一遍,最终的结果,都是 flex-slider 组件无法正常初始化,无法正常计算每次需要滑动的距离。

我明明想让它每次滑动三个滑块的距离,结果它却滑动了一个半,甚至还给我来了个漂移地来回滑动,导致布局崩溃。

最后折腾了好长时间,试了好多种方法,但好在总算是让我找出了一个还算是好用的方法。

道理很简单,既然如果是同步请求数据来追加新的滑块,组件就能够正常初始化,那么我们就假装让组件中追加的新滑块数据是同步得来的就行了:

先用没有任何内容的滑块DOM(例如空的 li标签)来占位,让 flex-slider组件正常新增滑块,这样组件就能正常初始化,能够正确计算每次滑动的距离,一切正常。
然后在此基础上,在稍后获取到异步数据后,将获取到的真正的滑块数据,替换掉之前的占位空滑块,这样对于 flex-slider组件来说,滑块的数量并没有任何变化,也就不会引起其任何的动作,所以替换完成后,组件依旧是正常的。

下面用代码说话。

假设我们异步获取新增滑块数据的方式是通过 Promise,每次到达组件末尾的时候,就自动获取新的数据,追加新的滑块。

$("#flexSlider").flexslider({    // 这里我们假设当每次组件滑动到最后一个滑块的时候,就追加新的滑块    // 有点类似于懒加载或者预加载的意思    end(slider): function(){        // 假设每一个 `li`元素,就是一个滑块的单位,这里我们一次性追加了三个空滑块的 `DOM`,        // 这三个 `DOM`只有一个作用,那就是给将来真正要呈现在这里的滑块占位,        // 以便于 `flex-slider`组件正常的重新初始化,不会产生各种各样的异常,将来是要被替换掉的。        let str = '<li></li><li></li><li></li>'        // 调用我们重写的 addSlide() 方法,这里我们一次性新增了三个滑块,        // 所以传入数字 3        addSlide(slider, str, 3);        let promiseResult = getData()        promiseResult.then((data)=>{            // 假设 data 中有动态追加滑块的数据            // len 指的是新增滑块的数量            let len = data.length            for(let i=0;i<len;i++){                // 在这里组装真正的滑块DOM                let newDOM = ...                // 关键在这里,将原先的占位滑块DOM,替换成真正想要展示的                // 这里假设是追加到 flex-slider 的末尾处                $('#flexSlider .slides li:eq('+(slider.count-j)+')').replaceWith(str)            }        })    }})

动态删减数据

删除数据使用到另外一个方法 :removeSlide

这里写图片描述

此方法做的事情,基本上都是一样的,都重新指定了删减后滑块的数量,以及重新初始化,并且在最后调用了 removed 回调函数。

这个方法只有一个 obj参数,代表的意思与 addSlide相同,没有第二个参数,也就是不能随意指定要删除哪个滑块,只能是最后一个。

不过我们同样可以自己将此方法重写一遍,让其能一次性删除多个滑块,并且能够指定要删除的滑块下标,我没有实际做过,期间可能还会有其他的异常,但大致思路是这样的肯定没错。

removeSlide方法的用法与 addSlide 没有太大区别,就不多说了。

阅读全文
0 0
原创粉丝点击