Framework7 索引列表插件的异步加载实现

前言

Framework7 作为移动端的开发框架的优良之处已经无需多言。现在已经有了 React 和 Vue 版本,之前在项目中用过 F7 + vue 的开发方式,无论是效率还是产出都近乎完美。有时间的话可以单独写篇文章详细介绍 Framework7,并与其它框架做对比。

插件的问题

对于 Framework7 插件的开发我就不多言了,官方文档很详细。Framework7 的插件开发确实很简单,但有些需要特殊对待的问题,我想通过索引插件这个例子简单说说我的解决方法。

索引列表在移动端算是比较常见的需求,我在工作中也遇到了这个需求,框架选用的是 Framework7,所以就直接用这个现成的插件了。插件代码如下:

Framework7.prototype.plugins.indexedlist = function (app, params) {
    var $ = window.Dom7;

    function initIndexedList(page) {
        var eventsTarget = $(page.container).find('.list-index');
        if (eventsTarget.length === 0) return;

        var pageContent = $(page.container).find('.page-content');

        ... 

    }

    return { 
        hooks: {
            pageInit: initIndexedList, 
        }
    }; 
};    

 初始化 Framework7:

var myApp = new Framework7({
    modalTitle: 'My App',
    pushState: true,
    ...
});

Framework7 的插件都是在 F7 初始化之后立即执行,所以动态生成的数据就有问题了。虽然官方文档提供了很多钩子,但都不太合适。整个列表应该是获取接口数据之后动态生成的,所以为了保证先载入数据再执行 Framework7,我最初想到的方法就是等到页面所有数据都请求完成之后再初始化 Framework7,不过这种方式稍微有些不友好。

$.when(ajax1,ajax2,ajax3).done(function(res1,res2,res3){

    new Framework7({
    ...
    });

});

插件改造

最后的办法只能是修改插件,最终尝试了很长时间才找到办法。初始化 F7 时可以给插件传递参数,如下:

var myApp = new Framework7({
    modalTitle: 'My App',
    pushState: true,
    /* 
    Here comes your plugin parameters that will be passed to your plugin in case of parameter name is the same as plugin name:
    */
    myPlugin: {
        foo: 'bar'
    }
});

这样的话我们可以在插件函数执行之前加一个判断:

Framework7.prototype.plugins.indexedlist = function (app, params) {
    var $ = window.Dom7;

    // the plugin will not initialize automaticly
    if (!params.init) return;

    function initIndexedList(page) {
      var eventsTarget = $(page.container).find('.list-index');
        if (eventsTarget.length === 0) return;

        var pageContent = $(page.container).find('.page-content');

      ...
}
return { hooks: { pageInit: initIndexedList, } }; };

其次插件的钩子函数也要删除,简单说一下,插件的返回值是一个钩子函数,表示页面加载完成立即执行initIndexedList() 函数,其参数是一个 page 对象,其中 page.container 就表示 .page 元素。删除钩子函数之后我们可以通过 params 参数来传递 container ,这样反而可以增加插件的灵活性。

Framework7.prototype.plugins.indexedlist = function (app, params) {
    var $ = window.Dom7;

    // the plugin will not initialize automaticly
    if (!params.init) return;

    function initIndexedList(page) {
      var eventsTarget = $(page.container).find('.list-index');
        if (eventsTarget.length === 0) return;

        var pageContent = $(page.container).find('.page-content');

      ...

    }

    initIndexedList(params);
};

插件修改后的调用方式,初始化 F7 时可以将插件的 init 设为 false

var indexedlist = new Framework7({
    indexedlist:{
        init:true,
        container:'.page'
    }
});

这样就可以在动态获取数据之后的回调函数中调用插件了。

Github: https://github.com/nzbin/Framework7-Indexed-List-plugin

posted @ 2017-07-30 23:09  叙帝利  阅读(2339)  评论(1编辑  收藏  举报