js渐渐入门之懒人框架- laz.js
一 前言
js 是一門神奇的語言。我們在使用js過程中,難免會使用到自己封裝的小接口,即使我們已經有了完備的jquery框架。因此我準備記錄下來laz.js 框架的編寫過程, 也是記錄自己的學習過程。
框架編寫除了有好的抽象思維和恰當的使用環境之外,自然需要最簡單的接口。而正如水里的鴨子,表面平靜水下抓狂,一個接口越簡單,那么實現這個接口的方法就越復雜。難免的,就要接觸到關于傳出參數的種種處理。
<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>
二 進入正題
1.關于參數
javascript的每一個方法都支持不定參數:
function params_test()
{
// arguments 就是該方法的參數列表
var argList = arguments;
};
因為這種參數列表的存在,我們可以玩出很多花樣。比如默認參數的實現:
function default_param()
{
//設置默認參數
var param0 = arguments[0]==undefined?'default value':arguments[0];
}
*注意這里 arguments[0]==undefined?a:b 而不是 arguments[0]?a:b 是因為arguments[0] 也就是這個默認參數很有可能是一個boolean值并且是一個false 也有可能是一個number類型的0,這些都會導致程序選擇默認值而不是傳入參數,
我們之后在編寫類型判斷方法的時候也會提到。
或者不定參數的實現:
function lot_params()
{
for(var i in arguments)
{
// 遍歷參數
}
}
2. 關于類型判斷
我不認為js是一種無類型的語言,準確的說,對于類型,我們不用操心的就是它那自由的 var 變量聲明和賦值操作吧。
Object 是 javascript語言的基本類型。 我們可以說數組是Array 類型 也可以說數組是Object 類型,同理String等等也是。因此在類型判斷的時候,我會將是否是Object的類型判斷放在最后,因為但部分情況下,判斷一個參數是否是Object的,意義并不太大。
以下是因為懶,所以加入進laz.js中的類型判斷方法。
//判斷是否是一個數組類型 用法如 is_array(tmp)
function is_array()
{
return !arguments[0] ? false : arguments[0].constructor == Array;
};
// 判斷是否是一個字符串類型 用法如上。
function is_string()
{
return !arguments[0] ? false : arguments[0].constructor == String;
};
// 判斷是否是一個數字 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一樣 數字0 和bool 的false 都會被認為是'非'邏輯
// 因此在處理這種類型時 絕對不能簡單的if(param)
function is_bool()
{
return (arguments[0] == undefined) ? false : arguments[0].constructor == Boolean
};
//是否是element 節點類型
function is_element()
{
return !arguments[0]?false:(arguments[0] instanceof Element);
};
//是否是Text 文字文本類型
function is_text(){return !arguments[0]?false:(arguments[0] instanceof Text);};
//是否是一個function/ 方法
function is_function(){return !arguments[0] ? false : typeof arguments[0] == "function";};
// 這里用到統一的consturtor 用法如 is_type(param,MyClass)
function is_type(p1,p2){return !p1?:false:p1.constructor?p1.constructor == p2:false;};
*constructor 屬性返回對創建此對象的數組函數的引用 -- W3School 我的理解就是一個類的構造函數。 我們可以通過自己編寫的is_type方法 傳入參數1 一個對象 參數2 一個類/類型 進行判斷
3.關于HTML 節點的獲得和創建
document 下element節點的獲得 有很多種方式 因為在項目中 如果只獲得幾個節點 我會直接采用id的形式 而多個節點的獲取 ,我會直接通過下面要介紹的laz.js 創建html 節點 同時保留相對應的js對象 來直接獲取,
再加上jquery的選擇器已經相當出色的,所以在懶人框架laz.js中并沒有加入節點選擇器的相關方法。下面主要說說創建節點。
<div class="div_class">
<div class = "part0">1</div>
<div class = "part1">2</div>
<div class = "part2">3</div>
</div>
<!-- Html 編寫大概是這樣的>
使用xml形式來描述一個樹狀結構,可能再恰當不過了。在寫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 這樣寫 就可以實現跟上面html一樣的內容。$$Div 是一個方法名 主要用來創建 document.createElement('div'),同時通過參數類型判斷,給這個節點加入子節點和加入attributes。
當然 也就是說 你要想創建一個h3節點對象 那么你必須要有$$H3方法。 開始我是通過一個配置表 使用eval 生成 常用的一些html 節點方法 但是奈何使用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("純文本只支持字符串作為參數");}
}else{
var element = document.createElement(tag);
for(var i in arr){
var tmp = arr[i];
// 類型判斷 如果是element 或者text 就把它 加入到節點中
// 如果不是, 那就作為系欸但的屬性參數
if (is_element(tmp) || is_text(tmp)){
element.appendChild(tmp);
}else {
for (var key in tmp) {element.setAttribute(key, tmp[key]);};
}
}
return element;
}
};
我們通過以上的方法創建出節點對象 ,然后需要把這個對象添加到父節點中。
因為跟jq不同, 我們放回的是一個純element對象, 因此 可以直接調用element的方法。
最常用的可能是下面幾種情況:
1. 添加到當前javascript標簽的前面或者后面 比如:
<body> <div> <ul> <li>1</li> <li>2</li> <!-- 我想創建一個li對象 并且放到這里 --> <li>4</li> </ul> </div> </body>
在不通過id class tag name等情況下, 將自己創建的element的對象插入到指定位置,該如何實現呢?
我的思路是這樣的。 首先我們知道html 和js 包括css 是至上而下依次加載的,我們就通過這一特性,開始展開。
<body>
<div>
<ul>
<li>1</li>
<li>2</li>
<!-- 我想創建一個li對象 并且放到這里 -->
<script>
//我們此時獲取的script標簽 其實是html頁面加載到這個位置的所有script
// 也可以理解為 這個列表的最后一個 就是當前的這個script標簽
var slist = document.getElementsByTagName('script');
</script>
<li>4</li>
</ul>
</div>
</body>
注意這句:也可以理解為 這個列表的最后一個 就是當前的這個script標簽。
因此我們可以獲得當前的script標簽的節點 也可以獲得當前script標簽的父節點。 那么我們創建的子節點就自然而然‘找到爸爸’了。下面是針對Element對應的做的擴展。
//在script節點之前插入
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節點之后插入
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;
};
當然 為了在編寫js的時候 可以實現‘不間斷調用方法’ 比如a.to1().to2().... 我習慣在沒有返回值的方法后面return this。 也因此針對element 擴展了其他方法,大多都是為了可以連續調用接口而寫的:
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. 通過選擇器獲得某個節點的對象 然后直接appendChild()
3. 插入到body
4 等等
4. 關于動畫
碎覺了。。 希望明天能堅持記錄下來。。
總結
以上是生活随笔為你收集整理的js渐渐入门之懒人框架- laz.js的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Struts 2杂谈(2):如何向标签文
- 下一篇: 三八节疯狂购物