ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScript コードの一部によって引き起こされる思考_JavaScript スキル

JavaScript コードの一部によって引き起こされる思考_JavaScript スキル

PHP中文网
リリース: 2016-05-16 18:56:44
オリジナル
1005 人が閲覧しました

这是一个关于Ext, Prototype, JavaScript方面的问题,其实下面遇到的问题本不是问题,都是因为错误的理解造成的,本文的宗旨是希望读者朋友避免我犯的同类错误,遇事三思而后行,同时也体会下发现问题,解决问题,反思问题这种精神活动所带来的快乐!

测试代码

<script type="text/javascript"> 
function init(){ 
var tpl = new Ext.Template(&#39;<p id="p{id}">this is p{id}</p>&#39;); 
tpl.append(&#39;p1&#39;,{id:&#39;2&#39;}); 
tpl.insertAfter(&#39;p2&#39;,{id:&#39;3&#39;}); 
tpl.overwrite(&#39;p1&#39;,{id:&#39;88&#39;}); 
} 
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 を使用してください。
多くの努力は間違った方向に使われ、最終的な結果はゼロです。
ああ、
世の中には何もなく、凡庸な人間が自分自身を邪魔するだけです。 🎜>

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート