UI 路由器 - 状态转换延迟(非常慢)

UI Router - State transition delay (very slow)

我在 angular 应用程序中使用 ui-router,在大多数情况下它都没有问题。

在某些情况下 $state.go("my-state") 不会触发立即转换。有时它非常慢(几秒钟后过渡到 "my-state")有时它不会触发,直到我移动鼠标一段时间并触发一些事件处理程序(绝对与事件处理程序无关)触发了过渡)。

这是我的指令中的内容:

// [...]
link: funtcion(scope, elm, attrs){
    elm.on('mouseenter', function(){
            // ...
        })
        .on('mousemove', function($event){
            // ...
        })
        .on('mouseleave', function(){
            // ...
        })
        .on('change', function(){
            // ...
        })
        .on('click', (e) ->

            if(someCondition){
                e.preventDefault()
                e.stopImmediatePropagation()
                e.stopPropagation()

                if(user.level == "visitor"){
                    $rootScope.$broadcast('showLogin')
                }
                else if(user.level == "member") 
                    $('#elementId').remove()
                    // PROBLEM HERE:
                    $state.go("my-state")
            }

            else if(anotherCondition){
                $('#elementId').remove()
            } 
        )
}
// [...]

我是不是漏掉了什么?
我可以对 "force" ui-router 做些什么来开始转换吗?

那是因为 element'on' 事件在 angular 的摘要循环之外。 像这样更新需要重定向的代码:

else if(user.level == "member") {
    scope.$apply(function() {
        $('#elementId').remove()
        // PROBLEM HERE: 
        $state.go("my-state")
    });
}

scope.$apply专门用于像这种需要手动调用angular摘要循环的情况。

还有一件事。 如果发生错误说 "digest loop is already in progress" 您可以将此技术与 $timeout:

一起使用
else if(user.level == "member") {
    $timeout(function() {
        $('#elementId').remove()
        // PROBLEM HERE: 
        $state.go("my-state")
    });
}

但请记住,以这种方式使用 $timeout 被视为一种 hack,最好找到绕过它的方法,但它仍然被广泛使用。

P.S. 不要忘记包含 $timeout 作为指令定义函数的依赖项。

P.P.S。阅读有关摘要循环的更多信息 here and here

如果模板中的 ng-repeat 列表很大,切换路由会出现一个有趣的问题。可以延迟加载新视图。在我的例子中,它长达 7 秒!我找到的一个解决方案是在切换视图之前先删除列表中的 HTML 节点。这样 UI 路由器就不会卸载繁重的 HTML 页面。在这个例子中,clinicList 是一个长列表的父节点。

var clinicList = document.getElementById('clinicList');
if (clinicList) document.getElementById('clinicList').innerHTML = '';
$state.go('selectshiftlistview');