javascript - AngularJs - $watch 仅在 Chrome 开发者工具打开时有效

标签 javascript jquery html css angularjs

我试图将一个 $watch 附加到一个指令,该指令监视元素的高度和宽度何时发生变化,以便它可以使用高度和宽度在图像顶部居中。

这是我的 app.js 代码:

app.directive('centerElement', function ($timeout) {
return function (scope, element, attrs) {
        scope.$watch(function () {
            return { 
                'h': element[0].offsetHeight, 
                'w': element[0].offsetWidth 
            };
        }, 
        function (newValue, oldValue) {
            var elementHeight = newValue.h;
            var elementWidth = newValue.w;

            /*To account for rounding errors and not loop*/
            if(elementHeight % 2 === 0)
            {
                element.css('margin-top', '-' + ((elementHeight) / 2) + 'px');
            }
            else 
            {
                element.css('margin-top', '-' + ((elementHeight + 1) / 2) + 'px');
            }
            if(elementWidth % 2 === 0)
            {
                element.css('margin-left', '-' + ((elementWidth) / 2) + 'px');
            }
            else
            {
                element.css('margin-left', '-' + ((elementWidth + 1) / 2) + 'px');
            }
        }, true);

        element.bind('centerElement', function () {
            scope.$apply();
        });
};
});

这是我的 html 代码:

<div class="row relativePosition">
    <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 noPadding">
        <img id="getStartedGiveGiftImage" ng-src="{{homeCtrl.getHomeImageBySectionName('getStartedGiveGift').url}}"/>
    </div>
    <div id="getStartedGiveGiftCol" class="absolutePosition" center-element>
        <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12">
            <div class="getStartedGiveGiftText headingTitle">
                Swapping, Sharing,
                <div class="getStartedGiveGiftText text-right">
                    and Caring
                </div>
            </div>
        </div>
        <div id="getStartedGiveGiftButtons" class="col-lg-4 col-md-4 col-sm-4 col-xs-12 text-right">
            <div>
                <a id="getStartedGiveGiftButton1" class="btn btn-default text-right redBackgroundGradient" href="{{homeCtrl.getPage('Get Started').route}}">Get Started</a>
            </div>
            <div>
                <a id="getStartedGiveGiftButton2" class="btn btn-default getStartedGiveGiftButton greenBackgroundGradient text-right text-white" href="{{homeCtrl.getPage('Give a Gift').route}}">Give a Gift</a>
            </div>
        </div>
    </div>
</div>

我已经将 .getStartedGiveGiftCol 的 css 设置为

#getStartedGiveGiftCol {
top: 50%;
left: 50%; }

margin-topmargin-left 值添加到高度的一半和宽度的一半会将元素直接放在图像的中心。

当我在未打开开发者工具的情况下在 Google Chrome 中运行应用程序时,在加载图像并调整元素的高度和宽度时不会调用 centerElement 指令监视,但是当我通过单步运行应用程序时Chrome 开发者工具,元素在图像上居中就好了。当我在没有它的情况下运行应用程序后打开开发人员工具时,没有任何错误。
此外,我尝试在 Internet Explorer、Edge 和 Firefox 中运行该应用程序。 Internet Explorer 和 Firefox 都以与 Chrome 相同的方式运行,但是,Edge 是唯一一个按照预期方式将图像居中的浏览器。

我宁愿不使用 $watch,因为它可能有性能问题,但根据我在文档和谷歌上所做的研究,我还没有找到另一种方法来做到这一点,但我非常开放的想法。我试图在等待图像加载然后将元素居中时找到一些东西,但我没有运气。我将在应用程序的其他部分重复此指令,因此不必使用 $watch 会很棒。

我是 angularJS 的新手,所以非常感谢任何帮助。我还不熟悉如何在 stackoverflow 上提问,所以如果您需要更多信息,请告诉我。

谢谢!

编辑: 我为图像创建了另一个指令,它会在加载时调用 scope.$digest() 。好像有帮助,但是当我多次刷新页面时,有时还是不行。有什么想法吗?

这是我添加的指令:

app.directive('imageOnload', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('load', function() {
                scope.$digest();
            });
            element.bind('error', function(){
                alert('image could not be loaded');
            });
        }
    };
});

最佳答案

这是我自己想出来的。我需要将 $timeout(); 添加到我的 centerElement 指令中。这会在当前 $digest 完成时强制执行 $scope.$apply();,以便在 $watch 中所做的更改实际上是应用于页面。

我的指令如下:

app.directive('centerElement', function ($timeout) {
return function (scope, element, attrs) {
        scope.$watch(function () {
            $timeout();
            return { 
                'h': element[0].offsetHeight, 
                'w': element[0].offsetWidth 
            };
        }, 
        function (newValue, oldValue) {
            var elementHeight = newValue.h;
            var elementWidth = newValue.w;

            /*To account for rounding errors and not loop*/
            if(elementHeight % 2 === 0)
            {
                element.css('margin-top', '-' + ((elementHeight) / 2) + 'px');
            }
            else 
            {
                element.css('margin-top', '-' + ((elementHeight + 1) / 2) + 'px');
            }
            if(elementWidth % 2 === 0)
            {
                element.css('margin-left', '-' + ((elementWidth) / 2) + 'px');
            }
            else
            {
                element.css('margin-left', '-' + ((elementWidth + 1) / 2) + 'px');
            }
        }, true);

        element.bind('centerElement', function () {
            scope.$apply();
        });
};
});

如果有人对如何避免使用 $watch 有任何想法,请告诉我。我不能只使用 CSS,因为 rowposition: relative 而元素是 position: absolute 所以我必须使用 top: 50%, left: 50%, margin-top 负值和元素高度的一半以及 margin-left 负值和宽度的一半(即 margin-top: -100px 当元素高度为 200px 和 margin-left: -50px 当元素宽度为 100px 时)顺序使元素在图像上居中。我需要找出元素的宽度和高度,而不是将其硬编码到 CSS 中,这在将来出于维护目的可能会很乏味,因为我必须计算出所有屏幕尺寸的尺寸以进行引导。这就是我使用 $watch 的原因。 我也在使用 Bootstrap ,所以 CSS3 flexbox 是不可能的,因为它会扰乱 Bootstrap 网格的响应能力。

因此,如果有人对如何摆脱 $watch 有任何想法,请告诉我。

关于javascript - AngularJs - $watch 仅在 Chrome 开发者工具打开时有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35532183/

相关文章:

javascript - 那里出了什么问题? textarea 什么都不显示,但值是

javascript - 渐变背景 UL

javascript - jQuery.extend(true, …) 的逆函数

javascript - 如何隐藏Iframe src?

html - Iframe,嵌入 youtube 不适用于 firefox

javascript - 将数据从 jQueryUI 对话框表单传递到 Controller

javascript - 模拟拖放文件事件

javascript - 如何将 form.serialize 值重复保存到变量中

javascript - 如何在 jQuery 中使用正则表达式

javascript - Firefox 第二列有一个换行符