如何观察DOM更改AngularJS

时间:2013-10-10 19:27:17

标签: javascript dom angularjs

这可能看起来像一个愚蠢的问题,但我需要知道如何观看页面的整个DOM并在其更改时重新编译它。基本上这是AngularJS默认使用数据绑定所做的事情,但我需要在DOM中的任何内容发生更改时发生,而不仅仅是绑定。原因是我有一个完全用HTML,Javascript和PHP构建的应用程序。它是一个单页面应用程序,它有一个主页面,并将PHP注入到该页面内的DIV包装器中。

我想对它进行一些修改,但希望将我的代码与原始代码完全分开。为此,我需要能够在注入具有自己的DOM结构的新PHP文件时重新编译DOM。到目前为止,我似乎没有工作。

app.directive("watch", function () {
    return function (scope, element, attr) {
        scope.$watch("watch", function(oldValue, newValue) {
            if(newValue) {
                console.log("there is a new value");
                console.log("the new value is " + newValue);
             }
         });
     }
});

我将监视属性添加到<body>标记,但它似乎不起作用,当更改dom时,不会记录任何内容。最后我想用$ compile替换console.log,但我首先需要让手表正常工作。有人能指出我做错了吗?

5 个答案:

答案 0 :(得分:31)

这是一个坏主意,但我会幽默你。

正如我在上面的评论中所说,做你想做的事情是个坏主意。也就是说,如果你仍然想要这样做,你可以通过将函数作为第一个参数传递来$watch几乎任何事情。

以下代码将检查<body>标记内的HTML是否已更改。请注意,这是一个令人难以置信的想法

$scope.$watch(function () {
   return document.body.innerHTML;
}, function(val) {
   //TODO: write code here, slit wrists, etc. etc.
});

以上手表会在HTML更改中随时 ANYTHING 时触发。

  • 当输入值发生变化时
  • 选择在下拉列表中更改时
  • 当属性在html中的任何元素中发生更改时。

其他信息:截至目前,在很多浏览器中,监控已加载的新DOM元素并不是一个好方法。最好的方法是在添加新的DOM元素时触发某些东西。

答案 1 :(得分:7)

如Steinway Wu所述,MutationObserver是最佳选择。这是一个片段:

.directive('myDirective', function() {
    return {
        ...
        link: function(scope, element, attrs) {
            var observer = new MutationObserver(function(mutations) {
                // your code here ...
            });
            observer.observe(element[0], {
                childList: true,
                subtree: true
            });
        }
    };
});

答案 2 :(得分:1)

我创建了一个小型实用程序服务

这是代码

GenericService.js中,我们有这个

angular.module('GenericServiceModule', [])
    .factory('$utilsService', function () {

        var utilService = {};

        utilService.observeDomChange = function (domElement, doThisOnChange, observationOptions) {
            var defaultOptions = {
                // attributes: true, // attribute changes will be observed | on add/remove/change attributes
                // attributeOldValue: true, // will show oldValue of attribute | on add/remove/change attributes | default: null
                // we need this because in .find() sizzle modifies id temporarily, https://github.com/jquery/jquery/issues/2620
                //attributeFilter: ['style'], // filter for attributes | array of attributes that should be observed, in this case only style

                // characterData: true, // data changes will be observed | on add/remove/change characterData
                // characterDataOldValue: true, // will show OldValue of characterData | on add/remove/change characterData | default: null

                childList: true, // target childs will be observed | on add/remove
                subtree: true // target childs will be observed | on attributes/characterData changes if they observed on target

            };
            var options = observationOptions || defaultOptions;

            var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
            var observer = new MutationObserver(function anElementIWatchChanged(mutations) {
                doThisOnChange();
            });

            // removing the dom element won't be triggered
            observer.observe(domElement, options);
        };

        return utilService;
    });

您只需像

一样使用它
$utilsService.observeDomChange($element[0], doSomething());

这是用法示例

angular.module(
...
.directive('myCustomDirective', function ($utilsService) {
    return {
        restrict: 'A',
        //...
        controller: function ($scope, $element) {
            //...
            $scope.$on('$viewContentLoaded', function (event, viewName) {
                $utilsService.observeDomChange($element[0], doSomething());
            }
        }
    }
}

答案 3 :(得分:0)

如上所述here (Mutation Events),您可以为{0}等DOM变异事件添加侦听器。

e.g。 DOMSubtreeModified

<强>更新

实际上他们建议改用Mutation Observer

答案 4 :(得分:0)

我知道这是一个古老的主题,但在尝试使用ng-bind-html从模型中动态检测填充HTML代码的元素内容的变化时,我遇到了类似的问题。

如何使用jqLit​​e的data()将一些自定义数据与ng-bind-html元素的子元素相关联,以检测内容是否已被替换(因此自定义数据丢失)?。

这将是directive的代码,用于观看使用ng-bind-html填充的元素的更改:

.directive("myOnDomContentChanges", function($window) {
    var DATA_KEY_NAME = "myOnDomContentChangesKey";
    return function(scope, element, attrs){
        scope.$watch(function(){
            var res = null;
            var children = element.children();
            if(children && children.length > 0){
                var childData = children.data(DATA_KEY_NAME);
                res = (typeof childData !== "undefined" ? childData : false );
            }
            return res;
        }, function(watchData){
            if(watchData === false){ //Only run when false
                var children = element.children();
                if(children && children.length > 0){
                    children.data(DATA_KEY_NAME, true); //Set custom data to true
                }
                //New HTML binding detected
                //Write your code here
            }
        });
    };
})

我希望它有所帮助 欢迎提出意见。
拉法