2017-01-14 5 views
0

Рассмотрим следующий примерJavaScript: есть ли способ инициализировать элементы в живой коллекции автоматически?

// a sample constructor 
var SampleConstructor = function(element,options); 

// a full live collection 
var domCollection = document.getElementsByTagName('*'); 

// bulk init 
for (var i = 0; i < domCollection.length; i++) { 
    if ('some conditions required by component') { 
    new SampleConstructor(domCollection[i], {}); 
    } 
} 

Вопросы

  • Будут вновь добавленные элементы в DOM инициализируются конструктором образца?
  • Если нет, есть ли способ сделать это без jQuery и без циклического перебора через коллекцию?

Примечание

Необходимое решение для IE8 +

+0

Может посмотреть на https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver –

+1

Если вы имеете дело с DOM манипуляции сами легко отслеживать изменения. – leaf

ответ

1
function compare(arr,newarr,callback){ 
    var index=0; 
    var newindex=0; 
    while(newarr.length!=newindex){ 
    if (arr[index] == newarr[newindex]) { 
    index++; newindex++; 
    } else { 
    callback (newarr[newindex]); 
    newindex++; 
    } 
    } 
} 
//onload 
var store=[]; 
compare([],store=document.getElementsByClassName("*"),yourconstructor); 
//regular 
var temp=document.getElementsByClassName("*"); 
compare(store,temp,yourconstructor); 
store=temp; 

Я думаю, что его наиболее эффективным для проверки. Единственное решение, которое я знаю, - это регулярно делать это с помощью setTimeout. Другим способом было бы обнаружить все Js Dóm изменения, что-то вроде:

var add = Element.prototype.appendChild; 
Element.prototype.appendChild=function(el){ 
yourconstructor(el); 
add.call(this,el); 
}; 

Примечание: очень Hacky

+0

Как насчет события 'propertyChange'? Я читаю https://msdn.microsoft.com/en-us/library/ms536956(v=vs.85).aspx – thednp

+0

_Note Изменение внутреннего текста или внутреннегоHTML дочерних элементов не приведет к срабатыванию события onpropertychange для parent element._ –

+0

Я думаю, что событие 'propertyChange' запускается, когда я appendChild, он меняет' document.all.length', помните, что мне интересно найти способ проверки при добавлении новых ITEMS в DOM. – thednp

1

Вот пример кода, чтобы проиллюстрировать мою comment. Однако, поскольку вы можете видеть, что он не отслеживает изменения DOM, действительно, я предпочитаю обратный путь, который широко используется современными фреймворками JavaScript, такими как Angular: наблюдайте структуру необработанных данных и соответствующим образом обновляйте DOM.

// Observable 
 

 
Observable = function() { 
 
    this.observers = []; 
 
}; 
 

 
Observable.prototype.addObserver = function (observer) { 
 
    this.observers.push(observer); 
 
}; 
 

 
Observable.prototype.emit = function (evt, args) { 
 
    var i, n = this.observers.length; 
 
    for (i = 0; i < n; i++) { 
 
    this.observers[i].update(this, evt, args); 
 
    } 
 
}; 
 

 
// Collection 
 

 
Collection = function() { 
 
    this.items = []; 
 
    Observable.call(this); 
 
}; 
 

 
Collection.prototype = new Observable(); 
 

 
Collection.prototype.size = function() { 
 
    return this.items.length; 
 
}; 
 

 
Collection.prototype.add = function (item) { 
 
    this.items.push(item); 
 
    this.emit("added", [item]); 
 
}; 
 

 
Collection.prototype.removeAt = function (i) { 
 
    var items = this.items.splice(i, 1); 
 
    this.emit("removed", [items[0], i]); 
 
}; 
 

 
// program 
 

 
var i, s = "h*e*l*l*o"; 
 
var collection = new Collection(); 
 
var words = document.getElementsByTagName("div"); 
 
var wordA = words[0], wordB = words[1]; 
 

 
collection.addObserver({ 
 
    update: function (src, evt, args) { 
 
    this[evt](args); 
 
    }, 
 
    added: function (args) { 
 
    wordA.appendChild(
 
     this.createSpan(args[0]) 
 
    ); 
 
    wordB.appendChild(
 
     this.createSpan(args[0]) 
 
    ); 
 
    }, 
 
    removed: function (args) { 
 
    wordB.removeChild(
 
     wordB.childNodes[args[1]] 
 
    ); 
 
    }, 
 
    createSpan: function (c) { 
 
    var child; 
 
    child = document.createElement("span"); 
 
    child.textContent = c; 
 
    return child; 
 
    } 
 
}); 
 

 
for (i = 0; i < s.length; i++) { 
 
    collection.add(s[i]); 
 
} 
 

 
for (i = 1; i < 5; i++) { 
 
    collection.removeAt(i); 
 
} 
 

 
function rdm (max) { 
 
    return Math.floor(
 
    Math.random() * max 
 
); 
 
} 
 

 
function addRdmLetter() { 
 
    collection.add(
 
    (rdm(26) + 10).toString(36) 
 
); 
 
} 
 

 
function removeRdmLetter() { 
 
    var n = collection.size(); 
 
    if (n > 0) collection.removeAt(rdm(n)); 
 
} 
 

 
function showLetters() { 
 
    alert(collection.items.join("")); 
 
}
body { 
 
    font-size: 16px; 
 
    font-family: Courier; 
 
} 
 

 
span { 
 
    padding: 5px; 
 
    display: inline-block; 
 
    margin: -1px 0 0 -1px; 
 
    border: 1px solid #999; 
 
} 
 

 
#buttons { 
 
    position: absolute; 
 
    top: 10px; 
 
    right: 10px; 
 
}
<p>wordA</p><div></div> 
 
<p>wordB</p><div></div> 
 
<div id="buttons"> 
 
    <button type="button" onclick="addRdmLetter()">Add letter</button> 
 
    <button type="button" onclick="removeRdmLetter()">Remove letter</button> 
 
    <button type="button" onclick="showLetters()">Show letters</button> 
 
</div>

+0

Этот подход очень интересный. Я заинтересован в том, чтобы сделать их всех счастливыми пользователей AngularJS, независимо от того, что JS, который манипулирует DOM на лету, для моей библиотеки «bootstrap.native», возможно, вы можете помочь обеспечить легкий и быстрый способ сделать это обновление. – thednp

+0

На данный момент я рассматриваю небольшую функцию полезности, чтобы делать 'onpropertychange' | 'DOMAttrModified' | 'DOMNodeInserted', 4-5 строк кода, выполняющих задание. Тем не менее, я открыт для любых предложений, которые могут возникнуть у вас, поскольку я не знаю AngularJS. – thednp

+0

@thednp Здесь нет ничего общего с Angular, кроме известного шаблона привязки данных (данные изменены -> обновление DOM), которые можно воспроизвести разными способами. Я просто хочу показать вам, что было бы лучше, если бы вы могли полностью контролировать манипуляции с DOM, но вы не сможете этого сделать в зависимости от вашей ситуации. Мой вклад здесь останавливается. – leaf

Смежные вопросы