【问题标题】:ngShow don't work as expected when using custom directive使用自定义指令时,ngShow 无法按预期工作
【发布时间】:2014-05-07 10:49:57
【问题描述】:

我有这个角度的代码:

<span ng-mouseover="item.show_description=true" ng-mouseleave="item.show_description=false" pointer="{x: item.x, y: item.y}">
    {{item.label}}
</span>
<div class="description-popup" ng-show="!!item.description && item.show_description"
     style="left: {{item.x}}px; top: {{item.y}}px">
    <h2>{{item.label}}</h2>
    <p>{{item.description}}</p>
    <p>{{!!item.description && item.show_description}}</p>
</div>

它正确显示弹出窗口,但如果描述为空或空字符串,弹出窗口仍然显示。在这种情况下,最后一个表达式显示为 false。我在这里做错了什么?或者那里可能有错误。我正在使用 Angular 1.0.6(目前无法升级)。

更新

我已经创建了 JSFiddle 并且似乎 ng-show 按预期工作,但当我使用指针指令时,使用 mousemove 事件时却没有。该指令的代码如下:

app.directive('pointer', function($parse) {
    function objectParser(expr) {
        var strip = expr.replace(/\s*\{\s*|\s*\}\s*/g, '');
        var pairs = strip.split(/\s*,\s*/);
        if (pairs.length) {
            var getters = {};
            var tmp;
            for (var i=pairs.length; i--;) {
                tmp = pairs[i].split(/\s*:\s*/);
                if (tmp.length != 2) {
                    throw new Error(expr + " is Invalid Object");
                }
                getters[tmp[0]] = $parse(tmp[1]);
            }
            return {
                assign: function(context, object) {
                    for (var key in object) {
                        if (object.hasOwnProperty(key)) {
                            if (getters[key]) {
                                getters[key].assign(context, object[key]);
                            }
                        }
                    }
                }
            }
        }
    }



    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var expr = objectParser(attrs.pointer);
            element.mousemove(function(e) {
                var offest = element.offset();
                scope.$apply(function() {
                    expr.assign(scope, {
                        x: e.pageX - offest.left,
                        y: e.pageY - offest.top
                    });
                });
            });
        }
    };

});

【问题讨论】:

  • item.description前面放两个!正常吗?
  • @R3tep 这就是在 JS 中将值转换为布尔值的方式。我想确保它获得布尔值。
  • 如果去掉!!,会有同样的行为吗?
  • @R3tep 是的,我得到了相同的结果。
  • 是否可以创建现场演示(例如使用 jsfiddle)?因为你的代码看起来不错。

标签: javascript angularjs angularjs-directive dom-events


【解决方案1】:

隔离范围

问题是ng-show 使用它所在元素的范围。如果它位于具有隔离范围指令的元素上,那么它将使用该隔离范围,并且无法访问外部范围。

在这种特殊情况下,我怀疑 description-popup 具有隔离范围,这意味着 ng-show 只能访问该指令的范围,而该指令可能没有您要测试的 item反对。

什么是隔离范围?

隔离范围意味着指令有自己的范围,它不从周围的范围继承。普通作用域继承自周围作用域,因此它们可以访问该周围作用域上的数据。隔离范围没有。

为什么会有人想要使用隔离作用域?!

重复使用。如果一个指令打算在很多地方重用,在很多不同的范围内使用各种属性,你不希望指令范围内的属性与周围范围的属性发生冲突。而且由于该指令应该是完全独立的并且根本不使用周围的范围,因此给它一个隔离范围通常是个好主意。这样做的缺点很少。确实,唯一可能出错的是有人想在该元素上放置 ng-showng-hide

解决方案

description-popup 周围加上一个额外的&lt;div&gt; ng-show

<div ng-show="!!item.description && item.show_description">
    <div class="description-popup"
         style="left: {{item.x}}px; top: {{item.y}}px">
        <h2>{{item.label}}</h2>
        <p>{{item.description}}</p>
        <p>{{!!item.description && item.show_description}}</p>
    </div>
</div>

这是假设 JSFiddle 中的行为是你想要的。

这可能只适用于 Angular https://docs.angularjs.org/guide/migration#isolate-scope-only-exposed-to-directives-with-scope-property

【讨论】:

  • 我发现我的代码可以在 Angular 1.2 上运行,但不能在之前的版本上运行。
  • 您提供的 JSFiddle(我已更改)使用 Angular 1.0.6。在我的 JSFiddle 中,弹出窗口的出现和消失取决于鼠标光标的位置。这不是你想要的吗?
  • 您的代码可以工作,但我认为它与隔离范围无关,因为它在第一个元素上工作。如果 ng-show 无法访问它根本不会显示的项目,它将始终返回 false。
  • 我对 1.2 版的评论是针对我的原始代码而不是您的。它在那个版本中工作,所以它是 Angular 中的一个错误,你的代码以某种方式解决了这个问题。
  • 我认为隔离作用域在 1.2 之后仍然表现得像这样,但似乎我错了。更多信息:docs.angularjs.org/guide/…
猜你喜欢
  • 1970-01-01
  • 2015-04-12
  • 2021-02-15
  • 1970-01-01
  • 2012-01-20
  • 2016-07-20
  • 2017-05-04
  • 2017-09-19
  • 1970-01-01
相关资源
最近更新 更多