Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SUI-mobile Router浅析 #1

Open
EasonYou opened this issue Jan 19, 2018 · 0 comments
Open

SUI-mobile Router浅析 #1

EasonYou opened this issue Jan 19, 2018 · 0 comments

Comments

@EasonYou
Copy link
Owner

SUI-mobile Router浅析

本文写于2016.12.25,当时实习公司要实现手动返回,故看源码寻找解决方案

封装方式

SUI-mobile基于Framework7实现的,这一点从Router模块与其他模块的封装方式可以看得出来。

Picker模块

var Picker = function(params) {
    var p = this;
    var defaults={
    //基本设置
    }
    p.setValue = function(arrValues, transition) {
        // setValue 代码块
    }
}

以Picker模块为例,所有的封装都基于this来实现,其他模块类似

Router模块

 var EVENTS = {
    // 事件名称
 }
 // 一些获取路径以及检测函数
 var Util = {
    getUrlFragment: function(url) {
        // getUrlFragment 代码块
    },
    // 以下类似
 }
// Router 的构造函数
 var Router = function(){}

// 通过prototype来进行Router封装
Router.prototype._init = function () {}

// 以下雷同_

Router 的封装是通过prototype,最后通过

  var  router = $.router =new Router();

绑定在了zepto上

返回和前进的实现(重点)

在这,先讲的是在SUI中,返回和前进的实现。
在Router构造函数中,有一段代码

window.addEventListener('popstate', this._onPopState.bind(this));

在这句代码中,注册了一个popstate事件,SUI的回退和前进都是基于这个实现的

在讲popstate,先来说明下返回前进按钮,它其实是简单封装了history.backhistory.go,并没有什么特殊。

但是在触发history.backhistory.go的时候,就会触发popstate事件

Router.prototype._onPopState = function(event) {
    var state = event.state;
    //代码忽略
    if (state.id < lastState.id) {
        this._back(state, lastState);
     } else {
        this._forward(state, lastState);
    }
}

popstate触发的_onPopState方法里,有一个event的回调,如果你进入一个页面在按返回触发这个方法然后log出来,是这样的

{
    id:3,
    pageId:"page-home",
    url: [obj]// 存储各种路径
}

那么这些数据是怎么来的呢,就是不管是内嵌页面切换还是外链页面切换都会进入一个_pushNewState

Router.prototype._pushNewState = function(url, sectionId) {
        var state = {
            id: this._getNextStateId(),
            pageId: sectionId,
            url: Util.toUrlObject(url)
        };

        theHistory.pushState(state, '', url);
        this._saveAsCurrentState(state);
        this._incMaxStateId();
    };

通过theHistory.pushState(state, '', url);window.history.pushState把信息存入state,这个state的信息只有在触发history.backhistory.go才会从回调中取得。

内嵌页面和外链页面的实现与区别

在SUI中,规定要把页面放在page-group类下。
在点击外链的时候,跳入_switchToDocument,会触发Ajax,获取链接页面,并取得其中的page-group类的内容,然后跳入_doSwitchDocument渲染在新的页面,刷新href,然后pushState
因此,其实整个的“跳转”并不是传统意义上的跳转页面,只是同个页面Ajax请求后刷新的假象。

点击链接后,跳入Router.prototype.load,并传入url

Router.prototype.load

Router.prototype.load = function(url, ignoreCache, $link) {
        // 默认使用缓存
        if (ignoreCache === undefined) {
            ignoreCache = false;
        }
        // 检查base url是否相同,相同则锚点切换, 否则 Ajax 切换
        if (this._isTheSameDocument(location.href, url)) {
            this._switchToSection(Util.getUrlFragment(url), $link);
        } else {
            // 在外链切换,多了这么一项动作,是存储当前的页面和地址
            this._saveDocumentIntoCache($(document), location.href);
            this._switchToDocument(url, ignoreCache);
        }
    };

_saveDocumentIntoCache

     Router.prototype._saveDocumentIntoCache = function(doc, url) {
        // 代码忽略
        this.cache[urlAsKey] = {
            $doc: $doc,
            $content: $doc.find('.' + routerConfig.sectionGroupClass)
        };
    }

在这里,点击外链的时候,把整个旧页面存入了$.router.cache中,在返回的时候就会调用里面的dom渲染旧页面。这一点加上SUI对于页面回退的实现方法,是整个滑动返回实现的难点所在。

加载完页面紧接着是获取当前页面$currentDoc为然后渲染新页面为$newDoc,接着进入_animateDocument
如果是返回的话,$newDoc则在$.router.cache中获取,然后渲染为$newDoc

// 四个参数为 当前页面,新页面,可见块,切换方向
this._animateDocument($currentDoc, $newDoc, $visibleSection, direction);

内嵌页面切换

内嵌页面的切换就没有那么多的步骤,只是获取id拿到那段section渲染为newPage,当前页面为currentPage然后传入_animateSection接着再传入_animateElement做class切换就结束了。

back&&forward

在上面所述的back和forward,其实动画的实现方式也是一样,只是多了一层判断是否为外链之间的切换,其他的也是通过渲染成newPagecurrentPage作为参数传入_animateSection或者_animateDocument处理就能形成切换了。

滑动返回实现评估

之前见过Framework7的滑动返回,它都是基于内嵌页面的层叠关系来实现的,并且没有路由跳转,单纯在本页面的切换。
在SUI中,想要实现滑动返回需要解决的最大的是路由state。基于SUI做的话,除了解决CSS方面的问题,还有保留路由state去实现的话,暂时还没有想到很好的办法。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant