Home > Web Front-end > JS Tutorial > Thoughts caused by a piece of javascript code_javascript skills

Thoughts caused by a piece of javascript code_javascript skills

PHP中文网
Release: 2016-05-16 18:56:44
Original
1006 people have browsed it

这是一个关于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>
Copy after login

以下是在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

Problem solved......................................
Reflection: Why?
Look at the code (Narration: the problem gets deeper and deeper)
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}) ;
},
Bottom: function(element, content) {
return Element.insert(element, {bottom:content});
},
After: function(element, content ) {
return Element.insert(element, {after:content});
}
};
Then look at: line:1616
insert: function(element, insertions) {
element = $(element);
.............................................
for (var position in insertions) {
content = insertions[position];
position = position.toLowerCase();
insert = Element._insertionTranslations[position];
.......... .....................
return element;
}
See next: line:2490
Element._insertionTranslations = {
before: function(element, node) {
element.parentNode.insertBefore(node, element);
},
top: function(element, node) {
element.insertBefore(node, element.firstChild);
},
bottom: function(element, node) {
element.appendChild(node);
},
after: function(element, node) {
element.parentNode.insertBefore(node, element.nextSibling);
},
.............
};
See the difference:
Ext:
El. insertAdjacentHTML
Prototype:
El.parentNode.insertBefore
Protoype uses El.parentNode.insertBefore to consider compatibility issues. Mozilla does not support El. insertAdjacentHTML, so it is difficult to use Ext Didn’t you consider it? (Narration: The idea is completely messed up and gradually heading towards the abyss of loss)
Reviewing the code: DomHelper.js line: 267
insertHtml: function(where, el, html){
. .....
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 '"';
}
var range = el.ownerDocument.createRange();
var frag;
switch(where){
case "beforebegin":
range. setStartBefore(el);
frag = range.createContextualFragment(html);
el.parentNode.insertBefore(frag, el);
return el.previousSibling;
case "afterbegin":
if(el.firstChild){
range.setStartBefore(el.firstChild);
frag = range.createContextualFragment(html);
el.insertBefore(frag, el.firstChild);
return el .firstChild;
}else{
el.innerHTML = html;
return el.firstChild;
}
case "beforeend":
if(el.lastChild){
range.setStartAfter(el.lastChild);
frag = range.createContextualFragment(html);
el.appendChild(frag);
return el.lastChild;
}else{
el .innerHTML = html;
return el.lastChild;
}
case "afterend":
range.setStartAfter(el);
frag = range.createContextualFragment(html);
el.parentNode.insertBefore(frag, el.nextSibling);
return el.nextSibling;
}
throw 'Illegal insertion point -> "' where '"';
}
From the second part (the second switch block), we can see that Ext is also considered, but if it is IE, the code cannot go to the second part.
Now list the correspondence between the case branch and the previous method name:
insertFirst:' afterBegin'
insertBefore:' beforeBegin'
insertAfter:' afterEnd'
append:' beforeEnd'
Comparing the above code, it seems that the problem is that I am confused append, insertAfter. I thought that append means appending a node directly after the current node, and insertAfter means inserting the node after the current node. In fact, if this is understood, append and insertAfter have the same functions. Then the author of Ext wrote two What is this method for?., Alas, I am stupid, I used it randomly without analyzing the code carefully, and it led to this long series of things.
Excerpt: Explanation on the append and insertAfter methods in Ext.Template
Applies the supplied values ​​to the template and appends the new node(s) to el
Applies the supplied values ​​to the template and inserts the new node(s) after el
Tip: For those who don’t understand, please put Wouldn’t it be much clearer if “to” in the first sentence is understood as “in”? In addition, if you operate on page elements, please use Element, which has the insert and append functions above.
So much effort is used in the wrong way In the direction, the final result is zero!
Alas,
There is nothing in the world, and it is only for mediocre people to disturb themselves.

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template