js渐渐入门之懒人框架- laz.js
一 前言
js 是一門神奇的語言。我們在使用js過程中,難免會使用到自己封裝的小接口,即使我們已經(jīng)有了完備的jquery框架。因此我準(zhǔn)備記錄下來laz.js 框架的編寫過程, 也是記錄自己的學(xué)習(xí)過程。
框架編寫除了有好的抽象思維和恰當(dāng)?shù)氖褂铆h(huán)境之外,自然需要最簡單的接口。而正如水里的鴨子,表面平靜水下抓狂,一個(gè)接口越簡單,那么實(shí)現(xiàn)這個(gè)接口的方法就越復(fù)雜。難免的,就要接觸到關(guān)于傳出參數(shù)的種種處理。
<body>
<ul>
<li>1</li>
<li>
<div class="div_class">
<div class = "part0">1</div>
<div class = "part1">2</div>
<div class = "part2">3</div>
</div>
</li>
</ul>
</body>
<!-- 一段這樣的html代碼 使用laz.js 可以這樣: -->
<body>
<ul>
<li>1</li>
<li>
<script>
$$Div
(
{class:"div_class"}
$$Div({class:"part0"}).setHTML('1'),
$$Div({class:"part1"}).setHTML('2'),
$$Div({class:"part2"}).setHTML('3')
).addToNext();
</script>
</li>
</ul>
</body>
二 進(jìn)入正題
1.關(guān)于參數(shù)
javascript的每一個(gè)方法都支持不定參數(shù):
function params_test()
{
// arguments 就是該方法的參數(shù)列表
var argList = arguments;
};
因?yàn)檫@種參數(shù)列表的存在,我們可以玩出很多花樣。比如默認(rèn)參數(shù)的實(shí)現(xiàn):
function default_param()
{
//設(shè)置默認(rèn)參數(shù)
var param0 = arguments[0]==undefined?'default value':arguments[0];
}
*注意這里 arguments[0]==undefined?a:b 而不是 arguments[0]?a:b 是因?yàn)閍rguments[0] 也就是這個(gè)默認(rèn)參數(shù)很有可能是一個(gè)boolean值并且是一個(gè)false 也有可能是一個(gè)number類型的0,這些都會導(dǎo)致程序選擇默認(rèn)值而不是傳入?yún)?shù),
我們之后在編寫類型判斷方法的時(shí)候也會提到。
或者不定參數(shù)的實(shí)現(xiàn):
function lot_params()
{
for(var i in arguments)
{
// 遍歷參數(shù)
}
}
2. 關(guān)于類型判斷
我不認(rèn)為js是一種無類型的語言,準(zhǔn)確的說,對于類型,我們不用操心的就是它那自由的 var 變量聲明和賦值操作吧。
Object 是 javascript語言的基本類型。 我們可以說數(shù)組是Array 類型 也可以說數(shù)組是Object 類型,同理String等等也是。因此在類型判斷的時(shí)候,我會將是否是Object的類型判斷放在最后,因?yàn)榈糠智闆r下,判斷一個(gè)參數(shù)是否是Object的,意義并不太大。
以下是因?yàn)閼校约尤脒M(jìn)laz.js中的類型判斷方法。
//判斷是否是一個(gè)數(shù)組類型 用法如 is_array(tmp)
function is_array()
{
return !arguments[0] ? false : arguments[0].constructor == Array;
};
// 判斷是否是一個(gè)字符串類型 用法如上。
function is_string()
{
return !arguments[0] ? false : arguments[0].constructor == String;
};
// 判斷是否是一個(gè)數(shù)字 int類型
function is_number()
{
return (arguments[0] != 0 && !arguments[0]) ? false : (arguments[0].constructor == Number || typeof arguments[0] == "number" || (!isNaN(arguments[0])));
};
//判斷是否是bool類型
// 正如上文提到的:和is_number一樣 數(shù)字0 和bool 的false 都會被認(rèn)為是'非'邏輯
// 因此在處理這種類型時(shí) 絕對不能簡單的if(param)
function is_bool()
{
return (arguments[0] == undefined) ? false : arguments[0].constructor == Boolean
};
//是否是element 節(jié)點(diǎn)類型
function is_element()
{
return !arguments[0]?false:(arguments[0] instanceof Element);
};
//是否是Text 文字文本類型
function is_text(){return !arguments[0]?false:(arguments[0] instanceof Text);};
//是否是一個(gè)function/ 方法
function is_function(){return !arguments[0] ? false : typeof arguments[0] == "function";};
// 這里用到統(tǒng)一的consturtor 用法如 is_type(param,MyClass)
function is_type(p1,p2){return !p1?:false:p1.constructor?p1.constructor == p2:false;};
*constructor 屬性返回對創(chuàng)建此對象的數(shù)組函數(shù)的引用 -- W3School 我的理解就是一個(gè)類的構(gòu)造函數(shù)。 我們可以通過自己編寫的is_type方法 傳入?yún)?shù)1 一個(gè)對象 參數(shù)2 一個(gè)類/類型 進(jìn)行判斷
3.關(guān)于HTML 節(jié)點(diǎn)的獲得和創(chuàng)建
document 下element節(jié)點(diǎn)的獲得 有很多種方式 因?yàn)樵陧?xiàng)目中 如果只獲得幾個(gè)節(jié)點(diǎn) 我會直接采用id的形式 而多個(gè)節(jié)點(diǎn)的獲取 ,我會直接通過下面要介紹的laz.js 創(chuàng)建html 節(jié)點(diǎn) 同時(shí)保留相對應(yīng)的js對象 來直接獲取,
再加上jquery的選擇器已經(jīng)相當(dāng)出色的,所以在懶人框架laz.js中并沒有加入節(jié)點(diǎn)選擇器的相關(guān)方法。下面主要說說創(chuàng)建節(jié)點(diǎn)。
<div class="div_class">
<div class = "part0">1</div>
<div class = "part1">2</div>
<div class = "part2">3</div>
</div>
<!-- Html 編寫大概是這樣的>
使用xml形式來描述一個(gè)樹狀結(jié)構(gòu),可能再恰當(dāng)不過了。在寫laz.js之初,我就在想 如何能讓js寫的像xml一樣。= = 于是就有了下面的樣式:
<script>
$$Div
(
{class:"div_class"}
$$Div({class:"part0"}).setHTML('1'),
$$Div({class:"part1"}).setHTML('2'),
$$Div({class:"part2"}).setHTML('3')
).addToNext();
</script>
是的,使用懶人js laz.js 這樣寫 就可以實(shí)現(xiàn)跟上面html一樣的內(nèi)容。$$Div 是一個(gè)方法名 主要用來創(chuàng)建 document.createElement('div'),同時(shí)通過參數(shù)類型判斷,給這個(gè)節(jié)點(diǎn)加入子節(jié)點(diǎn)和加入attributes。
當(dāng)然 也就是說 你要想創(chuàng)建一個(gè)h3節(jié)點(diǎn)對象 那么你必須要有$$H3方法。 開始我是通過一個(gè)配置表 使用eval 生成 常用的一些html 節(jié)點(diǎn)方法 但是奈何使用eval生成方法 編輯器的代碼提示不夠只能,所以就把臟活一口氣干完了。
function $$Ul(){ return _cook_node('ul',arguments)};
function $$Text(){ return _cook_node('text',arguments)};
function $$Li(){ return _cook_node('li',arguments)};
function $$Div(){ return _cook_node('div',arguments)};
function $$Input(){ return _cook_node('input',arguments)};
function $$P(){ return _cook_node('p',arguments)};
function $$H1(){ return _cook_node('h1',arguments)};
function $$H2(){ return _cook_node('h2',arguments)};
function $$H3(){ return _cook_node('h3',arguments)};
function $$Button(){ return _cook_node('button',arguments)};
function $$Iframe(){ return _cook_node('iframe',arguments)};
function $$Form(){ return _cook_node('form',arguments)};
function $$Label(){ return _cook_node('label',arguments)};
function $$Thead(){ return _cook_node('thead',arguments)};
function $$Tr(){ return _cook_node('tr',arguments)};
function $$Td(){ return _cook_node('td',arguments)};
function $$Th(){ return _cook_node('th',arguments)};
function $$Tbody(){ return _cook_node('tbody',arguments)};
function $$Thead(){ return _cook_node('thead',arguments)};
function $$Nav(){ return _cook_node('bav',arguments)};
function $$Table(){ return _cook_node('table',arguments)};
function $$A(){ return _cook_node('a',arguments)};
function $$Span(){ return _cook_node('span',arguments)};
function $$Br(){ return _cook_node('br',arguments)};
function $$I(){ return _cook_node('i',arguments)};
function $$B(){ return _cook_node('b',arguments)};
function $$Ol(){ return _cook_node('ol',arguments)};
function $$Img(){ return _cook_node('img',arguments)};
function $$Strong(){ return _cook_node('strong',arguments)};
function $$H4(){ return _cook_node('h4',arguments)};
function $$H3(){ return _cook_node('h3',arguments)};
function $$Article(){ return _cook_node('Article',arguments)};
嗯。 這是我目前能想到的最好的方法。 如果有更好的建議,請留言給我~ 接下來放上_cook_node 方法:
function _cook_node(tag,arr){
if (tag == "text"){
//如果是純文本
if (is_string(arr)){return document.createTextNode(arr);}else{console.log("純文本只支持字符串作為參數(shù)");}
}else{
var element = document.createElement(tag);
for(var i in arr){
var tmp = arr[i];
// 類型判斷 如果是element 或者text 就把它 加入到節(jié)點(diǎn)中
// 如果不是, 那就作為系欸但的屬性參數(shù)
if (is_element(tmp) || is_text(tmp)){
element.appendChild(tmp);
}else {
for (var key in tmp) {element.setAttribute(key, tmp[key]);};
}
}
return element;
}
};
我們通過以上的方法創(chuàng)建出節(jié)點(diǎn)對象 ,然后需要把這個(gè)對象添加到父節(jié)點(diǎn)中。
因?yàn)楦鷍q不同, 我們放回的是一個(gè)純element對象, 因此 可以直接調(diào)用element的方法。
最常用的可能是下面幾種情況:
1. 添加到當(dāng)前javascript標(biāo)簽的前面或者后面 比如:
<body> <div> <ul> <li>1</li> <li>2</li> <!-- 我想創(chuàng)建一個(gè)li對象 并且放到這里 --> <li>4</li> </ul> </div> </body>
在不通過id class tag name等情況下, 將自己創(chuàng)建的element的對象插入到指定位置,該如何實(shí)現(xiàn)呢?
我的思路是這樣的。 首先我們知道html 和js 包括css 是至上而下依次加載的,我們就通過這一特性,開始展開。
<body>
<div>
<ul>
<li>1</li>
<li>2</li>
<!-- 我想創(chuàng)建一個(gè)li對象 并且放到這里 -->
<script>
//我們此時(shí)獲取的script標(biāo)簽 其實(shí)是html頁面加載到這個(gè)位置的所有script
// 也可以理解為 這個(gè)列表的最后一個(gè) 就是當(dāng)前的這個(gè)script標(biāo)簽
var slist = document.getElementsByTagName('script');
</script>
<li>4</li>
</ul>
</div>
</body>
注意這句:也可以理解為 這個(gè)列表的最后一個(gè) 就是當(dāng)前的這個(gè)script標(biāo)簽。
因此我們可以獲得當(dāng)前的script標(biāo)簽的節(jié)點(diǎn) 也可以獲得當(dāng)前script標(biāo)簽的父節(jié)點(diǎn)。 那么我們創(chuàng)建的子節(jié)點(diǎn)就自然而然‘找到爸爸’了。下面是針對Element對應(yīng)的做的擴(kuò)展。
//在script節(jié)點(diǎn)之前插入
Element.prototype.addToNext = function()
{
var slist = document.getElementsByTagName('script');
if (slist.length > 0)
{
var s = slist[slist.length - 1];
var p = s.parentNode;
p.appendChild(this);
}
return this;
};
//在script節(jié)點(diǎn)之后插入
Element.prototype.addToLast = function()
{
var slist = document.getElementsByTagName('script');
if (slist.length > 0)
{
var s = slist[slist.length - 1];
var p = s.parentNode;
p.insertBefore(this,s);
}
return this;
};
當(dāng)然 為了在編寫js的時(shí)候 可以實(shí)現(xiàn)‘不間斷調(diào)用方法’ 比如a.to1().to2().... 我習(xí)慣在沒有返回值的方法后面return this。 也因此針對element 擴(kuò)展了其他方法,大多都是為了可以連續(xù)調(diào)用接口而寫的:
Element.prototype.addChildElement = function () {
this.appendChild(arguments[0]);
return this;
};
Element.prototype.addTo = function () {
arguments[0].appendChild(this);
return this;
};
Element.prototype.addToBody = function () {
this.appendTo(document.body);
return this;
};
Element.prototype.setHTML = function ()
{
if (arguments[0] == undefined)
return this;
var t = ""+arguments[0];
if (t.indexOf('<') == -1 && t.indexOf('>') == -1 )
{
this.appendChild(document.createTextNode(t));
}else
{
this.innerHTML = this.innerHTML + t;
}
return this;
};
2. 通過選擇器獲得某個(gè)節(jié)點(diǎn)的對象 然后直接appendChild()
3. 插入到body
4 等等
4. 關(guān)于動畫
碎覺了。。 希望明天能堅(jiān)持記錄下來。。
總結(jié)
以上是生活随笔為你收集整理的js渐渐入门之懒人框架- laz.js的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Struts 2杂谈(2):如何向标签文
- 下一篇: Idea 全局替换指定字符