2017-01-14 2 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

を見ている可能性があり変更を追跡します。 – 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を使って定期的に行うことです。

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

注:すべてのDOMの変更をJS、何かのように検出することであろうもう一つの方法はここで非常にハック

+0

'propertyChange'イベントはどうですか?私はhttps://msdn.microsoft.com/en-us/library/ms536956(v=vs.85).aspxを読んでいる – thednp

+0

_Note子要素のinnerTextまたはinnerHTMLを変更しても、onpropertychangeイベントは発生しません。親要素です._ –

+0

私はappendChildを呼び出すと 'propertyChange'イベントが発生すると思います。これは' document.all.length'を変更します。新しいITEMSがDOMに追加されたときにチェックする方法を探しています。 – thednp

1

は私commentを説明するためのサンプルコードです。しかし、DOMの変更を追跡することはできませんが、実際にはAngularのような現代のJavaScriptフレームワークで広く使われている逆の方法が好まれます。生データ構造を観察し、それに従ってDOMを更新します。自分で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

このアプローチは非常に興味深いです。私は 'bootstrap.native'ライブラリのためにDOMをその場で操作するどんなJSであれ、AngularJSのユーザを皆に喜ばせる方法に興味があります。このアップデートを行うための軽くて速いメソッドを提供するのに役立つかもしれません。 – thednp

+0

この時点で、私は 'onpropertychange'を行う小さなユーティリティ関数を見ています。 'DOMAttrModified' | 'DOMNodeInserted'、ジョブを行う4-5行のコード。私はAngularJSのことを知らないので、あなたが持っているかもしれない提案にはまだ開いています。 – thednp

+0

@thednpここではAngularと共通点はありませんが、多くの方法で再現できる有名なデータバインディングパターン(データ変更 - >更新DOM)は例外です。 DOM操作を完全に制御できるのであれば、あなたの状況に応じてそれを行うことができない場合があります。私の貢献はここでも終わります。 – leaf

関連する問題