这是一个关于Ext, Prototype, JavaScript方面的问题,其实下面遇到的问题本不是问题,都是因为错误的理解造成的,本文的宗旨是希望读者朋友避免我犯的同类错误,遇事三思而后行,同时也体会下发现问题,解决问题,反思问题这种精神活动所带来的快乐!
测试代码
<script type="text/javascript">
function init(){
var tpl = new Ext.Template('<p id="p{id}">this is p{id}</p>');
tpl.append('p1',{id:'2'});
tpl.insertAfter('p2',{id:'3'});
tpl.overwrite('p1',{id:'88'});
}
Ext.onReady(init);
</script>
</head>
<body>
<p id="p1">this is p1</p>
</body>
ログイン後にコピー
以下是在IE下的测试.我所期望的结果是(旁白:我已经开始犯错了):
this is div88
this is div2
this is div3
实际结果:
this is div88
问题:
Div2,div3 丢了?
发现问题怎么办?看代码.
Template.js line:197 (Extjs ver 2.2)
append : function(el, values, returnElement){
return this.doInsert('beforeEnd', el, values, returnElement);
}
在看 line201:
doInsert : function(where, el, values, returnEl){
el = Ext.getDom(el);
var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
return returnEl ? Ext.get(newNode, true) : newNode;
}
在在看:DomHelper.js line:267
insertHtml : function(where, el, html){
where = where.toLowerCase();
if(el.insertAdjacentHTML){
if(tableRe.test(el.tagName)){
var rs;
if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
return rs;
}
}
switch(where){
case "beforebegin":
el.insertAdjacentHTML('BeforeBegin', html);
return el.previousSibling;
case "afterbegin":
el.insertAdjacentHTML('AfterBegin', html);
return el.firstChild;
case "beforeend":
el.insertAdjacentHTML('BeforeEnd', html);
return el.lastChild;
case "afterend":
el.insertAdjacentHTML('AfterEnd', html);
return el.nextSibling;
}
throw 'Illegal insertion point -> "' + where + '"';
}
//////后面省略
}
原来还是用的insertAdjacentHTML方法,为什么会有问题呢?
输出中间代码:
var tpl = new Ext.Template('
this is div{id}
');
tpl.append('div1',{id:'2'});
tpl.insertAfter('div2',{id:'3'});
$("result-area").innerText = Ext.getDom("div1").innerHTML;
//.........
结果如下:
this is div1
this is div2
this is div3
?????? 为什么会这样? “this is div1”两边的
标签呢?
在测试:
var tpl = new Ext.Template('
this is div{id}
');
tpl.append('div1',{id:'2'});
tpl.insertAfter('div2',{id:'3'});
$("result-area").innerText = Ext.getDom("div1").outerHTML;
//.........
结果如下:
this is div1
this is div2
this is div3
(旁白:本来到这就已经能发现问题所在了,但执迷不悟,继续犯错)
原来它把div2,div3插到div1的value/text 后边了.所以运行tpl.overwrite('div1',{id:'88'});后div2,div3没了.
在此附上tpl.overwrite源码(innerHTML直接赋值):
overwrite : function(el, values, returnElement){
el = Ext.getDom(el);
el.innerHTML = this.applyTemplate(values);
return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
}
问题知道了,可怎么办呢,改Ext源码?
从做项目的角度来看,最好别改,因为你不清楚原作者的想法,容易把问题扩大化.
改源码不是不行,但那是没有办法的办法,如果能找到其它好的解决方案, 最好别改
(实际上Ext这块没有问题,只是我在参照API使用时,混淆了一些概念)
不改源码,只能找到其它好的解决方案了,用prototype.js看看:
var tpl = new Ext.Template('
this is div{id}
');
//tpl.append('div1',{id:'2'});
//tpl.insertAfter('div2',{id:'3'});
Insertion.After($('div1'),tpl.applyTemplate({id:'2'}));
Insertion.After($('div1'),tpl.applyTemplate({id:'3'}));
结果:
this is div88
this is div2
this is div3
問題は解決しました....................................
考察: なぜ?
コードを見てください (ナレーション: 問題はますます深くなります)
Prototype.js line:4042 (ver 1.6.0.2)
var Insertion = {
Before: function(element, content) ) {
return Element.insert(element, {before:content});
},
Top: function(element, content) {
return Element.insert(element, {top:content) }) ;
},
下: function(element, content) {
return Element.insert(element, {bottom:content});
After: function(element) , content ) {
return Element.insert(element, {after:content});
次に、 line:1616
insert: function(element, inserts) を見てください。 ) {
要素 = $(要素) ................................ .....
for (挿入内の var 位置) {
content = inserts[position]
position = Position.toLowerCase();
insert = Element._insertionTranslations [位置];
....................................
要素を返す
>次を参照: line:2490
Element._insertionTranslations = {
before: function(element, node) {
element.parentNode.insertBefore(node, element);
top : function(要素, ノード) {
element.insertBefore(node, element.firstChild);
},
bottom: function(element, ノード) {
element.appendChild(node); 🎜>},
after: function(element, node) {
element.parentNode.insertBefore(node, element.nextSibling);
},
.... ...
};
違いを参照してください:
拡張:
El.insertAdjacentHTML
プロトタイプ:
El.parentNode.insertBefore
プロトタイプは El.parentNode.insertBefore を使用します。 Mozilla は El.insertAdjacentHTML をサポートしていないため、Ext を使用することは困難です。考慮しませんでしたか (ナレーション: アイデアは完全に滅茶苦茶になり、徐々に喪失の淵に向かっています)
コードの見直し: DomHelper.js 行: 267
insertHtml: function(where, el, html){
.....
switch(where){
case "beforebegin":
el .insertAdjacentHTML('BeforeBegin', html);
return el.previousSibling;
case "afterbegin" :
return el.firstChild; >case "beforeend":
el.insertAdjacentHTML('BeforeEnd', html);
return el .lastChild;
case "afterend":
el.insertAdjacentHTML('AfterEnd', html);
return el.nextSibling;
throw '不正な挿入ポイント ->' where '"';
var range = el.ownerDocument.createRange(); >var frag;
switch(where){
case "beforebegin":
frag = range.createContextualFragment(html); (frag, el);
return el.previousSibling;
case "afterbegin":
if(el.firstChild){
range.setStartBefore(el.firstChild); .createContextualFragment(html);
el.insertBefore(frag, el.firstChild);
el.firstChild;
el.innerHTML = html; ;
}
ケース "beforeend":
if(el.lastChild){
range.setStartAfter(el.lastChild);
frag = range.createContextualFragment(html); el.appendChild(frag);
return el.lastChild;
el .innerHTML = html;
return el.lastChild;
range.setStartAfter(el);
frag = range.createContextualFragment(html);
el.parentNode.insertBefore(frag, el.nextSibling);
throw 'Illegal insert point -> where '"';
}
2 番目の部分 (2 番目の switch ブロック) から、Ext も考慮されていることがわかりますが、IE の場合は
ここで、case ブランチと前のメソッド名との対応をリストします。
insertFirst:' afterBegin'
insertBefore:' beforeBegin'
insertAfter:' afterEnd '
append:' beforeEnd'
上記のコードを比較すると、append、insertAfter を混同していることが問題のようです。append は現在のノードの直後にノードを追加することを意味し、insertAfter はノードを挿入することを意味すると思いました。実際、これが理解されていれば、append と insertAfter は同じ機能を持っています。Ext の作成者は、このメソッドは何のためにあるのかを 2 つ書きました。ああ、私は愚かで、それを分析せずにランダムに使用しました。
抜粋: Ext.Template の append メソッドと insertAfter メソッドの説明
指定された値をテンプレートに適用し、新しいノードを el
に追加します。 指定された値をテンプレートに適用し、新しいノードを el
の後に挿入します。 ヒント:わかりません、入れてください 最初の文の「to」を「in」と理解したほうがわかりやすいでしょうか? また、ページ要素を操作する場合は、上記の挿入および追加機能を持つ Element を使用してください。
多くの努力は間違った方向に使われ、最終的な結果はゼロです。
ああ、
世の中には何もなく、凡庸な人間が自分自身を邪魔するだけです。 🎜>