【问题标题】:Using Angular to set parent height of ng-if children使用 Angular 设置 ng-if 子级的父级高度
【发布时间】:2016-08-23 22:32:27
【问题描述】:

我觉得我在这里做错了很多事情。我有 3 个状态的视图 - 称它们为介绍、加载和完成。我希望每个状态随着用户的进展从左向右滑动。

这是基本结构:

var app = angular.module('plunker', ['ngAnimate']);

app.controller('MainCtrl', function($scope) {
  $scope.triggered = '';
  
  $scope.loading = false;
  $scope.completed = false;
  
  $scope.one = function() {
    console.log('one');
    $scope.loading = true;
    $scope.completed = false;   
  };
  
  $scope.two = function() {
    $scope.loading = false;
    $scope.completed = true;   
  };
  
}).directive('inheritHeight', ['$window', '$timeout', function($window, $timeout) {
    return {
      restrict: 'A',
      link: function (scope, elm, attrs) {

        scope.$watch("loading", function(newV, oldV) {
          console.log(newV, elm[0]);
          $timeout(function () {
            scope.triggered = scope.triggered + 'triggered ';
            scope.height = elm[0].querySelector('.child').offsetHeight;
            console.log(elm[0].querySelector('.child'));
            console.log(elm[0].querySelector('.child').offsetHeight);
            elm.css('height', elm[0].querySelector('.child').offsetHeight + 'px');
          });
        });

      }
    };
}]);
.parent {
  border: 1px solid red;
  position: relative;
  overflow: hidden;
}

.child {
  width: 100%;
  position: absolute;
  top: 0;
  left: 0; }
  .child.ng-enter, .child.ng-leave {
    -webkit-transition: 800ms cubic-bezier(0.645, 0.045, 0.355, 1) all;
    -moz-transition: 800ms cubic-bezier(0.645, 0.045, 0.355, 1) all;
    -ms-transition: 800ms cubic-bezier(0.645, 0.045, 0.355, 1) all;
    -o-transition: 800ms cubic-bezier(0.645, 0.045, 0.355, 1) all;
    transition: 800ms cubic-bezier(0.645, 0.045, 0.355, 1) all; }
  .child.ng-enter {
    -webkit-transform: translateX(100%);
    -moz-transform: translateX(100%);
    -ms-transform: translateX(100%);
    -o-transform: translateX(100%);
    transform: translateX(100%); }
  .child.ng-enter.ng-enter-active {
    -webkit-transform: translateX(0);
    -moz-transform: translateX(0);
    -ms-transform: translateX(0);
    -o-transform: translateX(0);
    transform: translateX(0); }
  .child.ng-leave {
    -webkit-transform: translateX(0);
    -moz-transform: translateX(0);
    -ms-transform: translateX(0);
    -o-transform: translateX(0);
    transform: translateX(0); }
  .child.ng-leave.ng-leave-active {
    -webkit-transform: translateX(-100%);
    -moz-transform: translateX(-100%);
    -ms-transform: translateX(-100%);
    -o-transform: translateX(-100%);
    transform: translateX(-100%); }
    
.child-a {
  background-color: green;
  height: 100px;
}

.child-b {
  background-color: blue;
  height: 50px;
}

.child-c {
  background-color: yellow;
  height: 30px;
}
<script src="https://code.angularjs.org/1.4.9/angular.js" data-semver="1.4.9"></script>
<script  src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-animate.js"></script>

<div ng-app="plunker" ng-controller="MainCtrl">
  <div class="parent" inherit-height="">
    <div class="child child-a" ng-if="!loading && !completed">
      <button ng-click="one()">Click One</button>
    </div>
    <div class="child child-b" ng-if="loading && !completed">
      <button ng-click="two()">Click Two</button>
    </div>
    <div class="child child-c" ng-if="!loading && completed"></div>
  </div>
  <p>{{ height }}</p>
  <p>{{ triggered }}</p>
</div>

带有inherit-height 指令的父 div 似乎无法在新状态出现时正确更新其高度,即使它在 scope.$watch$timeout 内...

有什么建议吗?谢谢!

【问题讨论】:

    标签: javascript css angularjs angularjs-directive


    【解决方案1】:

    在制作有关动画和 css 的任何内容之前,您需要提前了解两件事:

    1。指令的作用域与控制器的作用域不同。

    在您的示例中,status.loading 指向任何内容。由于您没有为 inherit-height 指令分配隔离范围,因此它的范围将与其父级相同,在您的情况下为 MainCtrl。但是,您永远不会注册像 $scope.status.loading 这样的东西,所以观察者什么都没有看到,这就是为什么您的 $timeout 服务中的所有逻辑都不起作用的原因。

    2。指令的链接函数中的元素参数是元素本身,而不是数组。

    所以elm[0] 没有意义。类似elm.eq(0).height() 这样的目标也可以实现。

    3。 querySelector 只会返回第一个匹配的元素

    所以在你的情况下,它总是会选择child-a,可能不是你想要的。以这种方式获取子元素的高度通常也是一种不好的做法。如果您确实需要,创建另一个指令并从父级请求它会更好。

    我建议您在制作其他复杂的 css 部分之前查看angular document 或其他教程以了解指令范围和链接功能的想法。

    【讨论】:

    • 感谢您的回复 - .status.loading 是从我的原始代码中复制的。继承的范围是有意的 - 更改为“加载”(见上文)会触发监视功能并应用代码。但是 querySelector 仍然针对错误的子 div - 鉴于 ng-if 逻辑,从技术上讲,它应该只针对一个元素
    • 查看更新的代码。另外,elm 不是元素本身,而是一个 jqLit​​e 对象。您需要使用 [0] 获取 DOM 对象并调用 querySelector()
    • @romeboards 是的,你是对的,当我说它自己时,我实际上是指 jQLite 包装的元素本身。因此,为了简化它,您可以通过elm.eq(0).height() 实现相同的目标
    【解决方案2】:

    所以我希望 querySelector 能够工作,因为 ng-if 会从 DOM 中删除元素,但是,情况似乎并非如此。以要过渡的子元素为目标就可以了:

    elm.css('height', elm[0].querySelector('.child.ng-enter').offsetHeight + 'px');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-24
      • 1970-01-01
      相关资源
      最近更新 更多