【发布时间】:2017-04-05 15:14:00
【问题描述】:
我正在尝试在一个组件中设置 angulartics,该组件用于在横幅中向用户显示错误/重要信息。但是,我遇到了一个问题,尽管横幅按预期运行,但控制器内部的值似乎没有按预期更新或运行。
发生了什么:ctrl.isBannerVisible 在测试页面加载时被定义为 true,触发横幅,但在切换可见性时值不会更新,尽管横幅实际上消失并重新出现。尽管被多次打开和关闭,“横幅可见”在控制台中只打印一次。
预期内容:每次ctrl.isBannerVisible 被评估为 true 时,都应在控制台中打印“横幅可见”。
有人可以解释为什么会这样吗?
下面是相关代码:
core.component.js:
(function () {
'use strict';
/** @ngInject */
function bannerCtrl($scope, $analytics) {
var ctrl = this;
ctrl.showCloseIcon = false;
if (angular.isDefined(ctrl.hasCloseIcon)) {
ctrl.showCloseIcon = true;
}
ctrl.bannerStyle = ctrl.bannerStyle || 'alert';
ctrl.$onDestroy = function () {
if (ctrl.onClosed) {
ctrl.onClosed();
}
}
$scope.$watch('isBannerVisible',
function(previousValue, currentValue) {
if(currentValue){
console.log('Banner is visible');
}
}
);
ctrl.onCloseClicked = function() {
ctrl.isBannerVisible = false;
if (ctrl.onClosed) {
ctrl.onClosed();
}
}
}
var BannerComponent = {
templateUrl: 'components/core/banner.tpl.html'
, transclude: true
, controller: bannerCtrl
, bindings: {
// Use 'has-close-icon' attribute (no values necessary) to display the close icon.
iconName: '@?'
, hasCloseIcon: '@?'
, bannerStyle: '@?'
, isBannerVisible: '='
, onClosed: '&?'
}
};
angular.module('mi.banner.core').component('miBanner', BannerComponent);
BannerComponent.$inject = [
'$scope', '$analytics'
];
}());
模板:
<div layout="row" layout-align="start center">
<div flex="100" ng-class="'mi-uam-banner--' + $ctrl.bannerStyle" ng-if="$ctrl.isBannerVisible">
<div flex="none" class="mi-icat-icon">
<div class="{{$ctrl.iconName}}"></div>
</div>
<div flex="grow" class="mi-icat-content" ng-transclude></div>
<div layout layout-align="center center" flex="none" class="mi-icat-action" ng-if="$ctrl.showCloseIcon">
<a class="mi-icon-action-close" ng-click="$ctrl.onCloseClicked()"></a>
</div>
</div>
</div>
示例实现:
<button id="toggleBannerVisibility" ng-click="main.toggleBannerVisibility()">Toggle banner visibility</button>
<mi-banner banner-style="global" icon-name="mi-icon-add-filled-circle" has-close-icon is-banner-visible="main.isBannerVisible">
<span>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</span>
<p>
<a id="asdf" href="" ng-click="main.wow()">RETRY</a>
</p>
</mi-banner>
测试控制器:
(function () {
'use strict';
/** @ngInject */
function MainController() {
var ctrl = this;
ctrl.isBannerVisible = true;
ctrl.destroyed = false;
function toggleBannerVisibility() {
ctrl.isBannerVisible = !ctrl.isBannerVisible;
}
function wow() {
window.alert('WOW!');
}
ctrl.wow = wow;
ctrl.toggleBannerVisibility = toggleBannerVisibility;
}
angular
.module('mi.banner.test-page')
.controller('MainController', MainController);
}());
注意:我已经删除了 $analytics 事件跟踪代码,因为它对于我所面临的问题实际上并不是必需的。
【问题讨论】:
-
查看您的代码(并且在相当长的一段时间内没有使用 angular)在我看来,好像您的 bannerCtrl 函数仅在您连接控制器时执行一次。它贯穿 if 块等等,正如您期望的那样,为您提供控制台输出。当您切换横幅可见性时,您不会再次执行整个控制器,而是更改控制器中的绑定布尔值。
-
啊,这很有道理。
-
Daniel Lane 是对的,如果你想让它在每次你的 item 变化时被调用,你需要使用 $scope.$watch('isBannerVisible', function (){ console.log('Banner可见'); });
-
@Groben。
$scope.$watch('isBannerVisible', function (){ console.log('Banner is visible'); });仅告诉您isBannerVisible是否从true更改为false。如果它是真的,你只需要log to console。在下面检查我的答案: -
@raneshu 公平地说,Groben 和您的解决方案现在都不适合我。我实现了这两个,但最多我在加载时打印了“横幅可见”,没有其他内容(使用 Groben 的建议时)。
标签: javascript angularjs angularjs-components