Angularjs 将多个ui视图动画化为一个视图的最佳实践

Angularjs 将多个ui视图动画化为一个视图的最佳实践,angularjs,angular-ui-router,transition,ng-animate,Angularjs,Angular Ui Router,Transition,Ng Animate,我有一个应用程序,基本上看起来像这样 <div ui-view="header"> <div ui-view="main"> <div ui-view="footer"> 到目前为止,一切顺利。但问题是。在转换过程中,我希望将所有ui视图作为一个视图设置动画。在我的例子中,为了使事情看起来有凝聚力(这是一个淡入动画),我想把它们放在一个包装div中,让该div进行淡出/淡入(在每个不同的ui视图上进行淡出/淡入将导致各种各样的丑陋) 这种情况下的最佳实践是什

我有一个应用程序,基本上看起来像这样

<div ui-view="header">
<div ui-view="main">
<div ui-view="footer">
到目前为止,一切顺利。但问题是。在转换过程中,我希望将所有
ui视图作为一个视图设置动画。在我的例子中,为了使事情看起来有凝聚力(这是一个淡入动画),我想把它们放在一个包装div中,让该div进行淡出/淡入(在每个不同的
ui视图上进行淡出/淡入将导致各种各样的丑陋)

这种情况下的最佳实践是什么

我是否将它们包装在
ui视图中
并以某种方式连接到
$stateProvider
中(嵌套
ui视图
s?)。 还有其他方法吗?我可以收听
$stateChange
并像
ngAnimate
那样使用
ui视图将类应用于我的包装器吗?(淡出,然后等待,直到完全淡出并成功解决,然后淡入)

从我的谷歌搜索结果来看,在处理过渡类型的动画时,
ui视图
似乎更受欢迎

。。。在转换过程中,我希望将所有ui视图作为一个动画。使 在我的情况下(这是一个淡入淡出的动画),事情看起来有凝聚力,我想 把它们放在包装袋里,让包装袋做淡出/淡出 在中(在每个不同的ui视图上执行此操作将导致各种 丑陋)

这种情况下的最佳实践是什么

选项1:使用事件挂钩
$stateChangeStart
$statechangesuccessuccess

正如@David在评论中提到的,这种方法会有一些副作用。所以,在
uirouter
想出一种更好的方法来管理状态转换之前,不要使用它。目前,它依靠
event.preventDefault()
来防止转换的发生

基本上,
ui路由器
将在中的传入视图的同时触发您的
ui视图
路由更改视图。因此,当下一个
ui视图
渲染时,您得到的是上一个
ui视图
仍然可见,如果您正在为视图设置动画,则旧视图和新视图之间将存在重叠的过渡持续时间。在旧的ui视图完成动画制作之前(在中为新的ui视图制作动画之前),您应该考虑推迟渲染新的ui视图

出于类似的原因,将它们包装到另一个
ui视图
中,并将它们连接到
$stateProvider
中是不明智的

选项2:(推荐)基于CSS的动画

我主要使用基于CSS的转换,您可以通过

  • 为每个
    ui视图
    分配一个公共CSS类,并在该类上应用动画
  • 或者将三个
    ui视图
    封装在
    中(如果确实需要),并在其上应用动画
无论哪种方式,您都会将所有的
ui视图
视为一个单独的实体,对它们进行动画处理将使它们看起来更加内聚

HTML:

这是一个基于您的用例的工作,其中,我有一个抽象状态
root
和三个嵌套状态
root.home
root.artist
root.band
。虽然
ui-view='main'
在所有州都会更改,
ui-view='footer'
在任何州都不会更改,
ui-view='header'
会更改状态“root.artist”。 事实上,您使用基于css的
.ng enter
.ng leave
类来触发动画,您在技术上克服了以前方法的问题

  $stateProvider
        .state('root',{
          abstract:true,
            views:{
              'header':{  //absolutely targets the 'header' view in root unnamed state.
                templateUrl:'header.html'
              },
              'footer':{  //absolutely targets the 'footer' view in root unnamed state.
                templateUrl:'footer.html'
              }
            }
        })
        .state('root.home',{
            views:{
              'main@':{
                templateUrl:'main.html'
              },
            }          
        })
        .state('root.artist',{
            views:{
              'header@':{
                templateUrl:'artist-header.html'
              },
              'main@':{
                templateUrl:'artist-main.html'
              },
            }          
        })
        .state('root.band',{
            views:{
              'main@':{
                templateUrl:'band-main.html'
              },
            }          
        })

$stateChangeStart
$statechangesuccessuccess
事件中的动画有一些奇怪的副作用,所以(目前)要避免它们。除非ui路由器有更好的方法来管理转换承诺,而不是
event.preventDefault()
通过JS的动画,否则将很棘手。运行三个
ui视图
并同步设置它们的动画,通过纯CSS应该不会有问题。在ui路由器常见问题部分中,有一个部分专门用于设置过渡动画。虽然动画确实是同步的,但它会导致设计问题,因为在滚动期间,
标题固定在视口顶部。当淡出开始时,它将显示下方不需要的
main
内容。使用包装器,这显然不是问题,因为它将作为单个元素淡出..嘿@NLN,感谢您的广泛回复!我已经更新了一点你的plunkr,以更好地反映我面临的问题:随着淡出,你还必须绝对定位div,这使得使用页脚有点困难。因此,我希望能够设置父div的动画,而不是单个div的动画(正如您可以看到的那样,红色和蓝色div重叠,当不透明度开始时,看起来一点也不好)。
<div ui-view="header" ></div>    
<div ui-view="main" ></div>
<div ui-view="footer" ></div>
[ui-view].ng-enter { 
   animation: fadein 2s;
}

@keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}
  $stateProvider
        .state('root',{
          abstract:true,
            views:{
              'header':{  //absolutely targets the 'header' view in root unnamed state.
                templateUrl:'header.html'
              },
              'footer':{  //absolutely targets the 'footer' view in root unnamed state.
                templateUrl:'footer.html'
              }
            }
        })
        .state('root.home',{
            views:{
              'main@':{
                templateUrl:'main.html'
              },
            }          
        })
        .state('root.artist',{
            views:{
              'header@':{
                templateUrl:'artist-header.html'
              },
              'main@':{
                templateUrl:'artist-main.html'
              },
            }          
        })
        .state('root.band',{
            views:{
              'main@':{
                templateUrl:'band-main.html'
              },
            }          
        })