2017-01-14 4 views
0

Prenons l'exemple suivantJavaScript: existe-t-il un moyen d'initialiser automatiquement les éléments d'une collection en direct?

// 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], {}); 
    } 
} 

Questions

  • Est-ce que les nouveaux éléments ajoutés dans les DOM initialisées par le constructeur de l'échantillon?
  • Sinon, existe-t-il un moyen de le faire sans jQuery et sans boucler la collection sur une base d'intervalle?

Remarque

La solution est nécessaire pour IE8 +

+0

mai jeter un oeil à https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver –

+1

Si vous traitez avec des manipulations du DOM par vous-même, il est facile de suivi des modifications. – leaf

Répondre

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; 

Je pense que le plus efficace de vérifier. La seule solution que je connaisse est de le faire régulièrement en utilisant setTimeout. Une autre façon serait de détecter tous les changements dom js, quelque chose comme:

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

Note: très hacky

+0

Qu'en est-il de l'événement 'propertyChange'? Je lis https://msdn.microsoft.com/en-us/library/ms536956(v=vs.85).aspx – thednp

+0

_Note Modifier l'innerText ou innerHTML des éléments enfants ne provoquera pas l'événement onpropertychange pour le élément parent._ –

+0

Je pense que l'événement 'propertyChange' se déclenche quand je appendChild, il change le' document.all.length', rappelez-vous que je suis intéressé de trouver un moyen de vérifier quand de nouveaux éléments sont ajoutés au DOM. – thednp

1

Voici un exemple de code pour illustrer mon propos comment. Cependant, comme vous pouvez le voir, il ne garde pas trace des changements DOM, en effet, je préfère le contraire qui est largement utilisé par les frameworks JavaScript modernes comme Angular: observer une structure de données brutes et mettre à jour le DOM en conséquence.

// 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

Cette approche est très intéressante. Je suis intéressé par un moyen de rendre heureux tous les utilisateurs d'AngularJS, quel que soit JS qui manipule le DOM à la volée, pour ma bibliothèque 'bootstrap.native', peut-être vous pouvez aider à fournir une méthode légère et rapide pour faire cette mise à jour. – thednp

+0

À ce stade, je regarde une petite fonction d'utilité pour faire 'onpropertychange' | 'DOMAttrModified' | 'DOMNodeInserted', 4-5 lignes de code qui font le travail. Cependant, je suis ouvert à toute suggestion que vous pourriez avoir, puisque je n'ai aucune idée de AngularJS. – thednp

+0

@thednp Il n'y a rien de commun avec Angular ici, excepté le fameux modèle de liaison de données (data changed -> update DOM) que vous pouvez reproduire de plusieurs façons. Je veux juste vous montrer que ce serait mieux si vous pouviez garder un contrôle complet sur les manipulations DOM, mais vous ne pourrez peut-être pas le faire en fonction de votre situation. Ma contribution s'arrête ici. – leaf