深入理解javascript動(dòng)態(tài)插入技術(shù)
最近發(fā)現(xiàn)各大類庫(kù)都能利用div.innerHTML=HTML片斷來(lái)生成節(jié)點(diǎn)元素,再把它們插入到目標(biāo)元素的各個(gè)位置上。這東西實(shí)際上就是insertAdjacentHTML,但是IE可惡的innerHTML把這優(yōu)勢(shì)變成劣勢(shì)。首先innerHTML會(huì)把里面的某些位置的空白去掉,見(jiàn)下面運(yùn)行框的結(jié)果:
<!doctype html>
<html dir="ltr" lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>
IE的innerHTML By 司徒正美
</title>
<script type="text/javascript">
window.onload = function() {
var div = document.createElement("div");
div.innerHTML = " <td> <b>司徒</b>正美 </td> "
alert("|" + div.innerHTML + "|");
var c = div.childNodes;
alert("生成的節(jié)點(diǎn)個(gè)數(shù) " + c.length);
for(var i=0,n=c.length;i<n;i++){
alert(c[i].nodeType);
if(c[i].nodeType === 1){
alert(":: "+c[i].childNodes.length);
}
}
}
</script>
</head>
<body>
<p id="p">
</p>
</body>
</html>
另一個(gè)可惡的地方是,在IE中以下元素的innerHTML是只讀的:col、 colgroup、frameset、html、 head、style、table、tbody、 tfoot、 thead、title 與 tr。為了收拾它們,Ext特意弄了個(gè)insertIntoTable。insertIntoTable就是利用DOM的insertBefore與appendChild來(lái)添加,情況基本同jQuery。不過(guò)jQuery是完全依賴這兩個(gè)方法,Ext還使用了insertAdjacentHTML。為了提高效率,所有類庫(kù)都不約而同地使用了文檔碎片?;玖鞒潭际峭ㄟ^(guò)div.innerHTML提取出節(jié)點(diǎn),然后轉(zhuǎn)移到文檔碎片上,然后用insertBefore與appendChild插入節(jié)點(diǎn)。對(duì)于火狐,Ext還使用了createContextualFragment解析文本,直接插入其目標(biāo)位置上。顯然,Ext的比jQuery是快許多的。不過(guò)jQuery的插入的不單是HTML片斷,還有各種節(jié)點(diǎn)與jQuery對(duì)象。下面重溫一下jQuery的工作流程吧。
append: function() {
//傳入arguments對(duì)象,true為要對(duì)表格進(jìn)行特殊處理,回調(diào)函數(shù)
return this.domManip(arguments, true, function(elem){
if (this.nodeType == 1)
this.appendChild( elem );
});
},
domManip: function( args, table, callback ) {
if ( this[0] ) {//如果存在元素節(jié)點(diǎn)
var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
//注意這里是傳入三個(gè)參數(shù)
scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
first = fragment.firstChild;
if ( first )
for ( var i = 0, l = this.length; i < l; i++ )
callback.call( root(this[i], first), this.length > 1 || i > 0 ?
fragment.cloneNode(true) : fragment );
if ( scripts )
jQuery.each( scripts, evalScript );
}
return this;
function root( elem, cur ) {
return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
(elem.getElementsByTagName("tbody")[0] ||
elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
elem;
}
}
//elems為arguments對(duì)象,context為document對(duì)象,fragment為空的文檔碎片
clean: function( elems, context, fragment ) {
context = context || document;
// !context.createElement fails in IE with an error but returns typeof 'object'
if ( typeof context.createElement === "undefined" )
//確保context為文檔對(duì)象
context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
// If a single string is passed in and it's a single tag
// just do a createElement and skip the rest
//如果文檔對(duì)象里面只有一個(gè)標(biāo)簽,如<div>
//我們大概可能是在外面這樣調(diào)用它$(this).append("<div>")
//這時(shí)就直接把它里面的元素名取出來(lái),用document.createElement("div")創(chuàng)建后放進(jìn)數(shù)組返回
if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
if ( match )
return [ context.createElement( match[1] ) ];
}
//利用一個(gè)div的innerHTML創(chuàng)建眾節(jié)點(diǎn)
var ret = [], scripts = [], div = context.createElement("div");
//如果我們是在外面這樣添加$(this).append("<td>表格1</td>","<td>表格1</td>","<td>表格1</td>")
//jQuery.each按它的第四種支分方式(沒(méi)有參數(shù),有l(wèi)ength)遍歷aguments對(duì)象,callback.call( value, i, value )
jQuery.each(elems, function(i, elem){//i為索引,elem為arguments對(duì)象里的元素
if ( typeof elem === "number" )
elem += '';
if ( !elem )
return;
// Convert html string into DOM nodes
if ( typeof elem === "string" ) {
// Fix "XHTML"-style tags in all browsers
elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
all :
front + "></" + tag + ">";
});
// Trim whitespace, otherwise indexOf won't work as expected
var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
var wrap =
// option or optgroup
!tags.indexOf("<opt") &&
[ 1, "<select multiple='multiple'>", "</select>" ] ||
!tags.indexOf("<leg") &&
[ 1, "<fieldset>", "</fieldset>" ] ||
tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
[ 1, "<table>", "</table>" ] ||
!tags.indexOf("<tr") &&
[ 2, "<table><tbody>", "</tbody></table>" ] ||
// <thead> matched above
(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
!tags.indexOf("<col") &&
[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
// IE can't serialize <link> and <script> tags normally
!jQuery.support.htmlSerialize &&//用于創(chuàng)建link元素
[ 1, "div<div>", "</div>" ] ||
[ 0, "", "" ];
// Go to html and back, then peel off extra wrappers
div.innerHTML = wrap[1] + elem + wrap[2];//比如"<table><tbody><tr>" +<td>表格1</td>+"</tr></tbody></table>"
// Move to the right depth
while ( wrap[0]-- )
div = div.lastChild;
//處理IE自動(dòng)插入tbody,如我們使用$('<thead></thead>')創(chuàng)建HTML片斷,它應(yīng)該返回
//'<thead></thead>',而IE會(huì)返回'<thead></thead><tbody></tbody>'
if ( !jQuery.support.tbody ) {
// String was a <table>, *may* have spurious <tbody>
var hasBody = /<tbody/i.test(elem),
tbody = !tags.indexOf("<table") && !hasBody ?
div.firstChild && div.firstChild.childNodes :
// String was a bare <thead> or <tfoot>
wrap[1] == "<table>" && !hasBody ?
div.childNodes :
[];
for ( var j = tbody.length - 1; j >= 0 ; --j )
//如果是自動(dòng)插入的里面肯定沒(méi)有內(nèi)容
if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
tbody[ j ].parentNode.removeChild( tbody[ j ] );
}
// IE completely kills leading whitespace when innerHTML is used
if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
//把所有節(jié)點(diǎn)做成純數(shù)組
elem = jQuery.makeArray( div.childNodes );
}
if ( elem.nodeType )
ret.push( elem );
else
//全并兩個(gè)數(shù)組,merge方法會(huì)處理IE下object元素下消失了的param元素
ret = jQuery.merge( ret, elem );
});
if ( fragment ) {
for ( var i = 0; ret[i]; i++ ) {
//如果第一層的childNodes就有script元素節(jié)點(diǎn),就用scripts把它們收集起來(lái),供后面用globalEval動(dòng)態(tài)執(zhí)行
if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
} else {
//遍歷各層節(jié)點(diǎn),收集script元素節(jié)點(diǎn)
if ( ret[i].nodeType === 1 )
ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
fragment.appendChild( ret[i] );
}
}
return scripts;//由于動(dòng)態(tài)插入是傳入三個(gè)參數(shù),因此這里就返回了
}
return ret;
},
真是復(fù)雜的讓人掉眼淚!不過(guò)jQuery的實(shí)現(xiàn)并不太高明,它把插入的東西統(tǒng)統(tǒng)用clean轉(zhuǎn)換為節(jié)點(diǎn)集合,再把它們放到一個(gè)文檔碎片中,然后用appendChild與insertBefore插入它們。在除了火狐外,其他瀏覽器都支持insertAdjactentXXX家族的今日,應(yīng)該好好利用這些原生API。下面是Ext利用insertAdjactentHTML等方法實(shí)現(xiàn)的DomHelper方法,官網(wǎng)給出的數(shù)據(jù):
這數(shù)據(jù)有點(diǎn)老了,而且最新3.03早就解決了在IE table插入內(nèi)容的詬?。╰able,tbody,tr等的innerHTML都是只讀,insertAdjactentHTML,pasteHTML等方法都無(wú)法修改其內(nèi)容,要用又慢又標(biāo)準(zhǔn)的DOM方法才行,Ext的早期版本就在這里遭遇滑鐵盧了)??梢钥闯?,結(jié)合insertAdjactentHTML與文檔碎片后,IE6插入節(jié)點(diǎn)的速度也得到難以置信的提升,直逼火狐?;谒?,Ext開(kāi)發(fā)了四個(gè)分支方法insertBefore、insertAfter、insertFirst、append,分別對(duì)應(yīng)jQuery的before、after、prepend與append。不過(guò),jQuery還把這幾個(gè)方法巧妙地調(diào)換了調(diào)用者與傳入?yún)?shù),衍生出insertBefore、insertAfter、prependTo與appendTo這幾個(gè)方法。但不管怎么說(shuō),jQuery這樣一刀切的做法實(shí)現(xiàn)令人不敢苛同。下面是在火狐中實(shí)現(xiàn)insertAdjactentXXX家族的一個(gè)版本:
(function() {
if ('HTMLElement' in this) {
if('insertAdjacentHTML' in HTMLElement.prototype) {
return
}
} else {
return
}
function insert(w, n) {
switch(w.toUpperCase()) {
case 'BEFOREEND' :
this.appendChild(n)
break
case 'BEFOREBEGIN' :
this.parentNode.insertBefore(n, this)
break
case 'AFTERBEGIN' :
this.insertBefore(n, this.childNodes[0])
break
case 'AFTEREND' :
this.parentNode.insertBefore(n, this.nextSibling)
break
}
}
function insertAdjacentText(w, t) {
insert.call(this, w, document.createTextNode(t || ''))
}
function insertAdjacentHTML(w, h) {
var r = document.createRange()
r.selectNode(this)
insert.call(this, w, r.createContextualFragment(h))
}
function insertAdjacentElement(w, n) {
insert.call(this, w, n)
return n
}
HTMLElement.prototype.insertAdjacentText = insertAdjacentText
HTMLElement.prototype.insertAdjacentHTML = insertAdjacentHTML
HTMLElement.prototype.insertAdjacentElement = insertAdjacentElement
})()
我們可以利用它設(shè)計(jì)出更快更合理的動(dòng)態(tài)插入方法。下面是我的一些實(shí)現(xiàn):
//四個(gè)插入方法,對(duì)應(yīng)insertAdjactentHTML的四個(gè)插入位置,名字就套用jQuery的
//stuff可以為字符串,各種節(jié)點(diǎn)或dom對(duì)象(一個(gè)類數(shù)組對(duì)象,便于鏈?zhǔn)讲僮鳎。?
//代碼比jQuery的實(shí)現(xiàn)簡(jiǎn)潔漂亮吧!
append:function(stuff){
return dom.batch(this,function(el){
dom.insert(el,stuff,"beforeEnd");
});
},
prepend:function(stuff){
return dom.batch(this,function(el){
dom.insert(el,stuff,"afterBegin");
});
},
before:function(stuff){
return dom.batch(this,function(el){
dom.insert(el,stuff,"beforeBegin");
});
},
after:function(stuff){
return dom.batch(this,function(el){
dom.insert(el,stuff,"afterEnd");
});
}
它們里面都是調(diào)用了兩個(gè)靜態(tài)方法,batch與insert。由于dom對(duì)象是類數(shù)組對(duì)象,我仿效jQuery那樣為它實(shí)現(xiàn)了幾個(gè)重要迭代器,forEach、map與filter等。一個(gè)dom對(duì)象包含復(fù)數(shù)個(gè)DOM元素,我們就可以用forEach遍歷它們,執(zhí)行其中的回調(diào)方法。
batch:function(els,callback){
els.forEach(callback);
return els;//鏈?zhǔn)讲僮?
},
insert方法執(zhí)行jQuery的domManip方法相應(yīng)的機(jī)能(dojo則為place方法),但insert方法每次處理一個(gè)元素節(jié)點(diǎn),不像jQuery那樣處理一組元素節(jié)點(diǎn)。群集處理已經(jīng)由上面batch方法分離出去了。
insert : function(el,stuff,where){
//定義兩個(gè)全局的東西,提供內(nèi)部方法調(diào)用
var doc = el.ownerDocument || dom.doc,
fragment = doc.createDocumentFragment();
if(stuff.version){//如果是dom對(duì)象,則把它里面的元素節(jié)點(diǎn)移到文檔碎片中
stuff.forEach(function(el){
fragment.appendChild(el);
})
stuff = fragment;
}
//供火狐與IE部分元素調(diào)用
dom._insertAdjacentElement = function(el,node,where){
switch (where){
case 'beforeBegin':
el.parentNode.insertBefore(node,el)
break;
case 'afterBegin':
el.insertBefore(node,el.firstChild);
break;
case 'beforeEnd':
el.appendChild(node);
break;
case 'afterEnd':
if (el.nextSibling) el.parentNode.insertBefore(node,el.nextSibling);
else el.parentNode.appendChild(node);
break;
}
};
//供火狐調(diào)用
dom._insertAdjacentHTML = function(el,htmlStr,where){
var range = doc.createRange();
switch (where) {
case "beforeBegin"://before
range.setStartBefore(el);
break;
case "afterBegin"://after
range.selectNodeContents(el);
range.collapse(true);
break;
case "beforeEnd"://append
range.selectNodeContents(el);
range.collapse(false);
break;
case "afterEnd"://prepend
range.setStartAfter(el);
break;
}
var parsedHTML = range.createContextualFragment(htmlStr);
dom._insertAdjacentElement(el,parsedHTML,where);
};
//以下元素的innerHTML在IE中是只讀的,調(diào)用insertAdjacentElement進(jìn)行插入就會(huì)出錯(cuò)
// col, colgroup, frameset, html, head, style, title,table, tbody, tfoot, thead, 與tr;
dom._insertAdjacentIEFix = function(el,htmlStr,where){
var parsedHTML = dom.parseHTML(htmlStr,fragment);
dom._insertAdjacentElement(el,parsedHTML,where)
};
//如果是節(jié)點(diǎn)則復(fù)制一份
stuff = stuff.nodeType ? stuff.cloneNode(true) : stuff;
if (el.insertAdjacentHTML) {//ie,chrome,opera,safari都已實(shí)現(xiàn)insertAdjactentXXX家族
try{//適合用于opera,safari,chrome與IE
el['insertAdjacent'+ (stuff.nodeType ? 'Element':'HTML')](where,stuff);
}catch(e){
//IE的某些元素調(diào)用insertAdjacentXXX可能出錯(cuò),因此使用此補(bǔ)丁
dom._insertAdjacentIEFix(el,stuff,where);
}
}else{
//火狐專用
dom['_insertAdjacent'+ (stuff.nodeType ? 'Element':'HTML')](el,stuff,where);
}
}
insert方法在實(shí)現(xiàn)火狐插入操作中,使用了W3C DOM Range對(duì)象的一些罕見(jiàn)方法,具體可到火狐官網(wǎng)查看。下面實(shí)現(xiàn)把字符串轉(zhuǎn)換為節(jié)點(diǎn),利用innerHTML這個(gè)偉大的方法。Prototype.js稱之為_(kāi)getContentFromAnonymousElement,但有許多問(wèn)題,dojo稱之為_(kāi)toDom,mootools的Element.Properties.html,jQuery的clean。Ext沒(méi)有這東西,它只支持傳入HTML片斷的insertAdjacentHTML方法,不支持傳入元素節(jié)點(diǎn)的insertAdjacentElement。但有時(shí),我們需要插入文本節(jié)點(diǎn)(并不包裹于元素節(jié)點(diǎn)之中),這時(shí)我們就需要用文檔碎片做容器了,insert方法出場(chǎng)了。
parseHTML : function(htmlStr, fragment){
var div = dom.doc.createElement("div"),
reSingleTag = /^<(\w+)\s*\/?>$/;//匹配單個(gè)標(biāo)簽,如<li>
htmlStr += '';
if(reSingleTag.test(htmlStr)){//如果str為單個(gè)標(biāo)簽
return [dom.doc.createElement(RegExp.$1)]
}
var tagWrap = {
option: ["select"],
optgroup: ["select"],
tbody: ["table"],
thead: ["table"],
tfoot: ["table"],
tr: ["table", "tbody"],
td: ["table", "tbody", "tr"],
th: ["table", "thead", "tr"],
legend: ["fieldset"],
caption: ["table"],
colgroup: ["table"],
col: ["table", "colgroup"],
li: ["ul"],
link:["div"]
};
for(var param in tagWrap){
var tw = tagWrap[param];
switch (param) {
case "option":tw.pre = '<select multiple="multiple">'; break;
case "link": tw.pre = 'fixbug<div>'; break;
default : tw.pre = "<" + tw.join("><") + ">";
}
tw.post = "</" + tw.reverse().join("></") + ">";
}
var reMultiTag = /<\s*([\w\:]+)/,//匹配一對(duì)標(biāo)簽或多個(gè)標(biāo)簽,如<li></li>,li
match = htmlStr.match(reMultiTag),
tag = match ? match[1].toLowerCase() : "";//解析為<li,li
if(match && tagWrap[tag]){
var wrap = tagWrap[tag];
div.innerHTML = wrap.pre + htmlStr + wrap.post;
n = wrap.length;
while(--n >= 0)//返回我們已經(jīng)添加的內(nèi)容
div = div.lastChild;
}else{
div.innerHTML = htmlStr;
}
//處理IE自動(dòng)插入tbody,如我們使用dom.parseHTML('<thead></thead>')轉(zhuǎn)換HTML片斷,它應(yīng)該返回
//'<thead></thead>',而IE會(huì)返回'<thead></thead><tbody></tbody>'
//亦即,在標(biāo)準(zhǔn)瀏覽器中return div.children.length會(huì)返回1,IE會(huì)返回2
if(dom.feature.autoInsertTbody && !!tagWrap[tag]){
var ownInsert = tagWrap[tag].join('').indexOf("tbody") !== -1,//我們插入的
tbody = div.getElementsByTagName("tbody"),
autoInsert = tbody.length > 0;//IE插入的
if(!ownInsert && autoInsert){
for(var i=0,n=tbody.length;i<n;i++){
if(!tbody[i].childNodes.length )//如果是自動(dòng)插入的里面肯定沒(méi)有內(nèi)容
tbody[i].parentNode.removeChild( tbody[i] );
}
}
}
if (dom.feature.autoRemoveBlank && /^\s/.test(htmlStr) )
div.insertBefore( dom.doc.createTextNode(htmlStr.match(/^\s*/)[0] ), div.firstChild );
if (fragment) {
var firstChild;
while((firstChild = div.firstChild)){ // 將div上的節(jié)點(diǎn)轉(zhuǎn)移到文檔碎片上!
fragment.appendChild(firstChild);
}
return fragment;
}
return div.children;
}
嘛,基本上就是這樣,運(yùn)行起來(lái)比jQuery快許多,代碼實(shí)現(xiàn)也算優(yōu)美,至少?zèng)]有像jQuery那樣亂成一團(tuán)。jQuery還有四個(gè)反轉(zhuǎn)方法。下面是jQuery的實(shí)現(xiàn):
jQuery.each({
appendTo: "append",
prependTo: "prepend",
insertBefore: "before",
insertAfter: "after",
replaceAll: "replaceWith"
}, function(name, original){
jQuery.fn[ name ] = function( selector ) {//插入物(html,元素節(jié)點(diǎn),jQuery對(duì)象)
var ret = [], insert = jQuery( selector );//將插入轉(zhuǎn)變?yōu)閖Query對(duì)象
for ( var i = 0, l = insert.length; i < l; i++ ) {
var elems = (i > 0 ? this.clone(true) : this).get();
jQuery.fn[ original ].apply( jQuery(insert[i]), elems );//調(diào)用四個(gè)已實(shí)現(xiàn)的插入方法
ret = ret.concat( elems );
}
return this.pushStack( ret, name, selector );//由于沒(méi)有把鏈?zhǔn)讲僮鞯拇a分離出去,需要自行實(shí)現(xiàn)
};
});
我的實(shí)現(xiàn):
dom.each({
appendTo: 'append',
prependTo: 'prepend',
insertBefore: 'before',
insertAfter: 'after'
},function(method,name){
dom.prototype[name] = function(stuff){
return dom(stuff)[method](this);
};
});
大致的代碼都給出,大家可以各取所需。
- JavaScript動(dòng)態(tài)插入CSS的方法
- JavaScript動(dòng)態(tài)插入script的基本思路及實(shí)現(xiàn)函數(shù)
- 得到文本框選中的文字,動(dòng)態(tài)插入文字的js代碼
- 如何讓動(dòng)態(tài)插入的javascript腳本代碼跑起來(lái)。
- Javascript基于AJAX回調(diào)函數(shù)傳遞參數(shù)實(shí)例分析
- js自定義回調(diào)函數(shù)
- 談?wù)凧avaScript自定義回調(diào)函數(shù)
- js的回調(diào)函數(shù)詳解
- 告訴你什么是javascript的回調(diào)函數(shù)
- js中回調(diào)函數(shù)的學(xué)習(xí)筆記
- JS動(dòng)態(tài)插入并立即執(zhí)行回調(diào)函數(shù)的方法
相關(guān)文章
JavaScript使用FileReader實(shí)現(xiàn)圖片上傳預(yù)覽效果
這篇文章主要為大家詳細(xì)介紹了JavaScript使用FileReader實(shí)現(xiàn)圖片上傳預(yù)覽效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09javascript數(shù)組中的concat方法和splice方法
這篇文章主要介紹了javascript數(shù)組中的concat方法和splice方法,concat方法作用合并數(shù)組,可以合并一個(gè)或多個(gè)數(shù)組,會(huì)返回合并數(shù)組之后的數(shù)據(jù),不會(huì)改變?cè)瓉?lái)的數(shù)組,更多相關(guān)內(nèi)容需要的小伙伴可以參考下面文章內(nèi)容2022-03-03JavaScript創(chuàng)建對(duì)象的寫(xiě)法
JavaScript 有Date、Array、String等這樣的內(nèi)置對(duì)象,功能強(qiáng)大使用簡(jiǎn)單,人見(jiàn)人愛(ài),但在處理一些復(fù)雜的邏輯的時(shí)候,內(nèi)置對(duì)象就很無(wú)力了,往往需要開(kāi)發(fā)者自定義對(duì)象2013-08-08用javascript動(dòng)態(tài)注釋掉HTML代碼
用javascript動(dòng)態(tài)注釋掉HTML代碼...2006-09-09自適應(yīng)布局meta標(biāo)簽中viewport、content、width、initial-scale、minimum-sca
這篇文章主要介紹了移動(dòng)客戶端手機(jī)頁(yè)面布局時(shí)各標(biāo)簽元素作用和適用情景,通過(guò)詳解幾種屬性讓讀者更明確自適應(yīng)布局的注意點(diǎn),具體操作步驟大家可查看下文的詳細(xì)講解,感興趣的小伙伴們可以參考一下。2017-08-08js格式化貨幣數(shù)據(jù)實(shí)現(xiàn)代碼
貨幣數(shù)據(jù)想要一某種形式在頁(yè)面中顯示的話,首先是必須要格式化的,下面為大家介紹下具體的格式化代碼,感興趣的朋友可以參考下2013-09-09OpenLayers3實(shí)現(xiàn)鼠標(biāo)移動(dòng)顯示坐標(biāo)
這篇文章主要為大家詳細(xì)介紹了OpenLayers3實(shí)現(xiàn)鼠標(biāo)移動(dòng)顯示坐標(biāo),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09