这可能看起来像一个愚蠢的问题,但我需要知道如何观看页面的整个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,但我首先需要让手表正常工作。有人能指出我做错了吗?
答案 0 :(得分:31)
正如我在上面的评论中所说,做你想做的事情是个坏主意。也就是说,如果你仍然想要这样做,你可以通过将函数作为第一个参数传递来$watch
几乎任何事情。
以下代码将检查<body>
标记内的HTML是否已更改。请注意,这是一个令人难以置信的想法。
$scope.$watch(function () {
return document.body.innerHTML;
}, function(val) {
//TODO: write code here, slit wrists, etc. etc.
});
以上手表会在HTML更改中随时 ANYTHING 时触发。
其他信息:截至目前,在很多浏览器中,监控已加载的新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代码的元素内容的变化时,我遇到了类似的问题。
如何使用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
}
});
};
})
我希望它有所帮助
欢迎提出意见。
拉法