如何观察 DOM 的变化 AngularJS

How to watch the DOM for changes AngularJS

本文关键字:DOM 变化 AngularJS 观察 何观察      更新时间:2023-09-26

这似乎是一个愚蠢的问题,但我需要知道如何观察页面的整个 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替换控制台.log但我首先需要让手表工作。 有人可以指出我做错了什么吗?

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

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

下面的代码将检查 <body> 标记中的 HTML 是否已更改。请注意,这是一个可怕的想法

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

上面的手表将在 HTML 中的任何内容更改时触发。

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

附加信息:截至目前,在很多浏览器中,还没有一种很好的方法来监视已加载的新 DOM 元素。最好的方法仍然是在添加新的 DOM 元素时触发一些东西。

正如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
            });
        }
    };
});

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

这是代码

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());
            }
        }
    }
}

如此处所述(突变事件(,您可以为 DOM 突变事件添加侦听器,例如 DOMSubtreeModified

例如 element.addEventListener("DOMSubtreeModified", function (ev) {...}, false)

更新

实际上,他们建议使用突变观察者。

我知道

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

使用 jqLite 的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
            }
        });
    };
})

我希望它有所帮助。
欢迎评论。
  拉法