由于公司产品战略需求,需要开发多个微信公众账号,可以选择使用IONIC作为UI框架,可以说它是一个很好的选择,符合Angular编写规范,但是IONIC的UI组件相对来说要少一些,没有侧栏、时间选择器、图片预览等组件,不能满足产品的一些需求,最后决定用采用SUI作为UI框架,开发框架使用Aangular,进行快速开发,但是在开发过程中遇到以下两个问题:
1.如果用户注册完成后或者登录成功后,跳转到相应的页面,在后退过程中还能后退到注册或者登陆页面,还有一些页面需要在back的时候根据业务逻辑进行控制,跳转到指定页面,并且切换效果也需要调整;
2.由于业务逻辑复杂,一个业务模块页面可能有上千行代码,大小超过150K,还不包括一些资源文件以及数据请求的时间损耗,造成在加载过程中比较缓慢,影响用户体验。
第一个问题解决方案是对SUI路由器的一些方法进行重写,在物理后退过程中进行拦截处理,实现根据业务需求进行一些特殊控制,代码如下:

function smInit(){
            //自定义控制参数
            var CONFIG={
     noAniPage:'blankpage',//$from.attr('id')='blankpage',即首次进入,不进行动画切换效果
                isBack:false//判断是否为back状态,采用不同的切换效果 
            };
            /*捕获返回按钮事件*/
            var DIRECTION = {
                leftToRight: 'from-left-to-right',
                rightToLeft: 'from-right-to-left'
            };
            var EVENTS = {
                pageLoadStart: 'pageLoadStart', // ajax 开始加载新页面前
                pageLoadCancel: 'pageLoadCancel', // 取消前一个 ajax 加载动作后
                pageLoadError: 'pageLoadError', // ajax 加载页面失败后
                pageLoadComplete: 'pageLoadComplete', // ajax 加载页面完成后(不论成功与否)
                pageAnimationStart: 'pageAnimationStart', // 动画切换 page 前
                pageAnimationEnd: 'pageAnimationEnd', // 动画切换 page 结束后
                beforePageRemove: 'beforePageRemove', // 移除旧 document 前(适用于非内联 page 切换)
                pageRemoved: 'pageRemoved', // 移除旧 document 后(适用于非内联 page 切换)
                beforePageSwitch: 'beforePageSwitch', // page 切换前,在 pageAnimationStart 前,beforePageSwitch 之后会做一些额外的处理才触发 pageAnimationStart
                pageInit: 'pageInitInternal' // 目前是定义为一个 page 加载完毕后(实际和 pageAnimationEnd 等同)
            };
            var routerConfig = {
                sectionGroupClass: 'page-group',
                // 表示是当前 page 的 class
                curPageClass: 'page-current',
                // 用来辅助切换时表示 page 是 visible 的,
                // 之所以不用 curPageClass,是因为 page-current 已被赋予了「当前 page」这一含义而不仅仅是 display: block
                // 并且,别的地方已经使用了,所以不方便做变更,故新增一个
                visiblePageClass: 'page-visible',
                // 表示是 page 的 class,注意,仅是标志 class,而不是所有的 class
                pageClass: 'page'
            };
            $.router._back = function (state, fromState) {
                //后退操作
                CONFIG.isBack = true;
                //跳转到第一个页面时,再后退,关闭页面
                if(state.pageId == "blankpage"||fromState.pageId == "firstpage"){
                    wx.closeWindow();
                    return;
                }
                //根据业务逻辑跳转到哪个页面
                if(state.pageId == "secondpage"&&fromState.pageId=="thirdpage"){
                    _goPage("#firstpage",'');
                    return;
                }
                if (this._isTheSameDocument(state.url.full, fromState.url.full)) {
                    var $newPage = $('#' + state.pageId);
                    if ($newPage.length) {
                        var $currentPage = this._getCurrentSection();
                        this._animateSection($currentPage, $newPage, DIRECTION.leftToRight);
                        this._saveAsCurrentState(state);
                    } else {
                        location.href = state.url.full;
                    }
                } else {
                    this._saveDocumentIntoCache($(document), fromState.url.full);
                    this._switchToDocument(state.url.full, false, false, DIRECTION.leftToRight);
                    this._saveAsCurrentState(state);
                }
            };
            $.router._animateSection = function($from, $to, direction) {
                var toId = $to.attr('id');
                $from.trigger(EVENTS.beforePageSwitch, [$from.attr('id'), $from]);

                $from.removeClass(routerConfig.curPageClass);
                $to.addClass(routerConfig.curPageClass);
                //页面初始化不执行动画切换效果
                if($from.attr('id')!=CONFIG.noAniPage){
                    $to.trigger(EVENTS.pageAnimationStart, [toId, $to]);
                    if(CONFIG.isBack){
                        direction=DIRECTION.leftToRight;
                    }else{
                        direction=DIRECTION.rightToLeft;
                    }
                    this._animateElement($from, $to, direction);
                    $to.animationEnd(function() {
                        $to.trigger(EVENTS.pageAnimationEnd, [toId, $to]);
                        // 外层(init.js)中会绑定 pageInitInternal 事件,然后对页面进行初始化
                        $to.trigger(EVENTS.pageInit, [toId, $to]);
                        CONFIG.isBack=false;
                    });
                }
            };
        }

对SUI的$.router._back和._animateSection方法进行重写,在进行物理返回操作时进行拦截,然后根据业务逻辑控制路由跳转和页面切换效果。

第二个问题处理起来比较简单,利用Requirejs进行模板加载,$compile对模板内容进行编译,并且动态绑定scope,实现模板根据路由动态加载,加载后的模板不进行重复加载,在DEMO中会有具体的操作处理,这里就不进行详细解释了,核心代码:

require(['text!'+tplurl],function(html){
                    $(container).append($(html));
                    $compile($(container))($scope);
                    $scope.vm.tplcache.push(tplurl);
                    callback(false);
                })

 据具体产品而定,包括Angular模板动态加载的问题,如果不想使用Angular,也可以用zepto+artTemplate等一些js模板技术搞定,但是路由控制,我觉得基本上已经满足产品的各种需求,如果哪位小伙伴有更好的方案或者架构,可以分享交流。