Skip to content
This repository was archived by the owner on Nov 12, 2024. It is now read-only.
This repository was archived by the owner on Nov 12, 2024. It is now read-only.

vframe依赖加载插件 #44

@xinglie

Description

@xinglie

在我们做一个复杂的长列表页面时,我们通常要优先加载主功能,或者滚动到可视区域时才加载相应的view,这时候就可以使用该插件。

源码:

let Magix = require('magix');
let $ = require('$');
let { Vframe, Event: MEvent, mix } = Magix;
let WaitObserver = mix({}, MEvent);
let Base = Vframe.prototype;
let OldMountView = Base.mountView;
Vframe.on('add', e => {
    WaitObserver.fire(e.vframe.id + ':add', e, 1);
});
Vframe.on('remove', e => {
    WaitObserver.off(e.vframe.id + ':add');
});
let WaitVframe = (vfId, callback) => {
    let vf = Vframe.get(vfId);
    if (vf) {
        if (vf.$cr) {
            callback();
        } else {
            let ready = () => {
                vf.off('created', ready);
                callback();
            };
            vf.on('created', ready);
        }
    } else {
        WaitObserver.on(vfId + ':add', e => {
            let vf = e.vframe;
            let ready = () => {
                vf.off('created', ready);
                callback();
            };
            vf.on('created', ready);
        });
    }
};
let Win = $(window);
let ScrollList = [];
let Intersect = (rect1, rect2) => {
    let half1Width = rect1.width / 2,
        half1Height = rect1.height / 2,
        half2Width = rect2.width / 2,
        half2Height = rect2.height / 2,
        cen1 = {
            x: rect1.x + half1Width,
            y: rect1.y + half1Height
        },
        cen2 = {
            x: rect2.x + half2Width,
            y: rect2.y + half2Height
        };

    return Math.abs(cen2.x - cen1.x) <= half1Width + half2Width &&
        Math.abs(cen2.y - cen1.y) <= half1Height + half2Height;
};
let Scrolled = function () {
    let viewport = {
        x: Win.scrollLeft(),
        y: Win.scrollTop(),
        width: Win.width(),
        height: Win.height()
    };
    for (let i = 0; i < ScrollList.length; i++) {
        let one = ScrollList[i];
        let node = $('#' + one.id);
        if (node.length) {
            let offset = node.offset();
            let rect = {
                x: offset.left,
                y: offset.top,
                width: node.width(),
                height: node.height()
            };
            if (Intersect(viewport, rect)) {
                ScrollList.splice(i--, 1);
                one.cb();
            }
        } else {
            ScrollList.splice(i--, 1);
        }
    }
    if (!ScrollList.length) {
        Win.off('scroll', Scrolled);
    }
};
let ScrollWatch = (vfId, callback) => {
    if (!ScrollList.length) {
        Win.on('scroll', Scrolled);
    }
    ScrollList.push({
        id: vfId,
        cb: callback
    });
    Scrolled();
};
Base.mountView = function (viewPath, viewInitParams) {
    let me = this;
    let sign = ++me.$s;
    let node = $('#' + me.id);
    let dep = node.attr('mx-dep');
    if (dep) { //有依赖
        if (dep | 0) { //延时
            setTimeout(() => { //由sign保证正确,所以无须取消setTimeout的执行
                if (sign == me.$s) {
                    OldMountView.call(me, viewPath, viewInitParams);
                }
            }, dep);
        } else { //其它依赖
            if (dep == '@viewport') { //以@开头的表示内置的命令:当vframe节点处在可视区域时加载
                ScrollWatch(me.id, () => {
                    if (sign == me.$s) {
                        OldMountView.call(me, viewPath, viewInitParams);
                    }
                });
            } else { //其它vframe依赖
                //if (IsVframeCreated(dep)) { //如果依赖的已经加载完成
                // oldMountView.call(me, viewPath, viewInitParams, callback);
                //} else {
                WaitVframe(dep, () => { //等待相应的vframe加载
                    if (me.$s == sign) {
                        OldMountView.call(me, viewPath, viewInitParams);
                    }
                });
                //}
            }
        }
    } else {
        OldMountView.call(me, viewPath, viewInitParams);
    }
};

插件使用方式

  1. 把该文件保存成vfdep.js,放在app目录下
  2. 在Magix.boot时,在exts中启用该插件,如
Magix.boot({
    exts: ['vfdep']
});

插件支持的功能

延时加载

通过mx-dep指定一个延时的时间,毫秒为单位

<div mx-view="path/to/view" mx-dep="2000">loading</div>
滚动到可视区域加载

通过mx-dep值为@Viewport来指示view滚动到可视区域时才加载

<div mx-view="path/to/view" mx-dep="@viewport">loading</div>
在其它view加载完成后才加载

通过mx-dep值为其它view的id时,其它view加载渲染完成时才加载该view

<div mx-view="path/to/view-a" mx-dep="@viewport" id="viewa">loading</div>
<div mx-view="path/to/view-b" mx-dep="viewa">loading</div>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions