前端demo組織優(yōu)化(進階思路)

最近在看老項目的代碼,一個客戶端的js代碼粗仓,幾千行的代碼,全是function(){} var...的垂直布局,真的是要感動的哭了借浊。哈哈

一開始都是這樣塘淑,想實現(xiàn)什么功能,不管三七二十一蚂斤,function走起存捺,最終堆起無數(shù)個變量和函數(shù)來完成一個畫面的js。我也是橡淆,但過段時間自己去改代碼bug或者加功能的時候召噩,我的天,這是我寫的嗎逸爵,什么時候?qū)懙木叩危趺蠢聿磺逅悸妨?而且,修改一個地方其他地方也得改师倔,改完了還容易出新bug构韵,偶爾都會忘了是自己寫的

慢慢的代碼看多了點,了解了些js的模塊封裝的一些方式趋艘,面向?qū)ο蟮南嚓P(guān)思想疲恢,越來越覺得易讀、易改的代碼應(yīng)該需要更好的組織形式

下面來看看平時寫代碼瓷胧,面向過程到面向?qū)ο笙匀崂砬岸碎_發(fā)思路

首先需要知道你要做什么需求得明白再來分析代碼怎么寫

功能需求

如下圖,功能比較簡易:

選擇之后添加搓萧,展示區(qū)便陳列:

展示區(qū)點擊‘X’的時候去除當(dāng)前內(nèi)容杂数,選擇區(qū)相應(yīng)也取消對應(yīng)的勾選:

優(yōu)化前代碼


<!DOCTYPE html>
 <html>
 
 <head>
     <meta charset="UTF-8">
     <title>多選框問題</title>
 </head>
 
 <body>
     <!--<input type="text" data-bind-content="name" />
         <span data-bind-content='name'></span>-->
 
     <h4>選擇區(qū)</h4>
     <div>
         
         <ul id="ul1">
             <li>全選<input type="checkbox" name="checkall" /></li>
             <li><input type="checkbox" name="checkthis" /><span>1</span></li>
             <li><input type="checkbox" name="checkthis" /><span>2</span></li>
             <li><input type="checkbox" name="checkthis" /><span>3</span></li>
             <li><input type="checkbox" name="checkthis" /><span>4</span></li>
             <li><input type="checkbox" name="checkthis" /><span>5</span></li>
         </ul>
     </div>
     
     <button id="add">添加</button>
     <h4>展示區(qū)</h4>
     <ul id="ul2"></ul>
 </body>
 <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
 <script type="text/javascript">
     //封裝
     var checkBox = (function () {
         var globalV = [];
         var yourChose = function (tableId, addClickId, showId) {
             console.log($('#' + tableId + ' input[name=checkall]'));
             //全選
             $('#' + tableId + ' input[name=checkall]').click(function () {
                 //如果選擇全選, 所有的選擇框都選中,去除全選,所有的選擇框去除選中    
                 if ($(this).prop('checked')) {
                     $('#' + tableId + ' input[name=checkthis]').prop('checked', true);
                     //全選的時候,將所有選框的數(shù)據(jù)取出來傳給全局變量globalV
                     $('#' + tableId + ' input[name=checkthis]').each(function (i, ele) {
                         var choseDate = {};
                         choseDate.isChecked = true;
                         choseDate.id = $(ele).parent().children('span').html();
                         globalV.push(choseDate);
                     });
                 } else {
                     $('#' + tableId + ' input[name=checkthis]').prop('checked', false);
                 }
                 console.log(globalV);
             })
             //對各個選擇框綁定事件
             $('#' + tableId).on('change', 'input[name=checkthis]', function () {
                 var arr = [];//存儲每個選擇框的狀態(tài)
                 var choseDate = {};//存儲被選中的選擇框的數(shù)據(jù)
                 //<li><input type="checkbox" name="check-this" /><span>3</span></li>獲取span里面的值
                 var this_value = $(this).parent().children('span').html();
                 //遍歷每個選擇框取選擇的狀態(tài)
                 $('#' + tableId + ' input[name=checkthis]').each(function (i, ele) {
                     arr.push($(ele).prop('checked'));
                 });
                 //如果有未選中的狀態(tài),去除全選框的選中狀態(tài),否則保留添加全選框的的選中狀態(tài)
                 if (arr.indexOf(false) == -1) {
                     $('#' + tableId + ' input[name=checkall]').prop('checked', true);
                 } else {
                     $('#' + tableId + ' input[name=checkall]').prop('checked', false);
                 }
                 //對應(yīng)每個選擇框的change事件,如果這個選擇框選中,則存儲這個選擇框的數(shù)據(jù),否則遍歷存儲數(shù)據(jù)的變量,移除這個取消選中的的選擇框的數(shù)據(jù)
                 if ($(this).is(':checked')) {
                     choseDate.isChecked = true;
                     choseDate.id = this_value;
                     globalV.push(choseDate);
                 } else {
                     for (var i = 0; i < globalV.length; i++) {
                         if (this_value == globalV[i].id) {
                             globalV.splice(i, 1);
                         }
                     }
                 }
                 console.log(globalV);
             });
             //點擊添加按鈕的事件
             $('#'+addClickId).click(function (e) {
                 e.preventDefault();
                 $('#'+showId).empty();//清空展示區(qū)里面的內(nèi)容
                 console.log(globalV);
                 //如果沒有選中任何選擇框,則彈出提示
                 if (globalV.length == 0) {
                     alert('請先選擇!');
                 } else {
                     //如果選中了一些選擇框,則全局變量數(shù)據(jù)不為空,開始遍歷全局變量
                     for (var j = 0; j < globalV.length; j++) {
                         //按照全局變量globalV,給展示區(qū)創(chuàng)建元素;(包含了刪除按鈕)
                         var liElement = '<li>\
                                             <span>'+ globalV[j].id + '</span>\
                                             <p style="display:inline-block;width:20px;height:20px;background-color:red;border-radius:50%;text-align:center">X</p>\
                                         </li>';
                         $('#'+showId).append(liElement);
                     }
                     //給刪除按鈕添加點擊事件
                     $('#'+showId).on('click', 'p', function () {
                         //var findAndChangeState=$(this).parent('li').children('span').html();
                         //找到這個刪除按鈕對應(yīng)的父級標(biāo)簽li下面的span標(biāo)簽的內(nèi)容;注意:這個是簡化;就放在了標(biāo)簽里面,實際情況可能是個屬性,獲取的這個值對應(yīng)一個選擇框
                         //由這個值來查找對應(yīng)的選擇框,從而改變選擇框的狀態(tài);
                         //這里是點擊了刪除按鈕,那么與他對應(yīng)的選擇框的選中狀態(tài)也會被去除
                         var findAndChangeState = $(this).parent('li').children('span').html();
                         //遍歷選擇框找到與刪除按鈕對應(yīng)的選擇框,將其狀態(tài)改為未選中,同時將全選的選擇框也改為未選中
                         $('#' + tableId + ' input[name=checkthis]').each(function (i, ele) {
                             if ($(this).parent().children('span').html() == findAndChangeState) {
                                 $(this).parent().children('input').prop('checked', false);
                                 $('#' + tableId + ' input[name=checkall]').prop('checked', false);
                             }
                         });
                         //改完之后這個刪除按鈕對應(yīng)的父級標(biāo)簽
                         $(this).parent('li').remove();
                     })
                 }
             })
         };
         return {
             globalV:globalV,
             yourChose:yourChose
         }
     })()
     checkBox.yourChose('ul1', 'add', 'ul2')
 </script>
 
 </html>

優(yōu)化后代碼

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>多選框問題</title>
</head>

<body>
    <!--<input type="text" data-bind-content="name" />
        <span data-bind-content='name'></span>-->

    <h4>選擇區(qū)</h4>
    <div>

        <ul id="ul1">
            <li>全選<input type="checkbox" name="checkall" /></li>
            <li><input type="checkbox" name="checkthis" /><span>1</span></li>
            <li><input type="checkbox" name="checkthis" /><span>2</span></li>
            <li><input type="checkbox" name="checkthis" /><span>3</span></li>
            <li><input type="checkbox" name="checkthis" /><span>4</span></li>
            <li><input type="checkbox" name="checkthis" /><span>5</span></li>
        </ul>
    </div>

    <button id="add">添加</button>
    <h4>展示區(qū)</h4>
    <ul id="ul2"></ul>
</body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript">
    //封裝
    var checkBox = (function () {

        var globalV = [];
        var yourChose = function (tableId, addClickId, showId) {
            //負責(zé)更新數(shù)據(jù)
            var updateData = function () {
                globalV = [];
                $('#' + tableId + ' input[name=checkthis]').each(function () {
                    if ($(this).is(':checked')) {
                        var choseDate = {};
                        var this_value = $(this).parent().children('span').html();
                        choseDate.isChecked = true;
                        choseDate.id = this_value;
                        globalV.push(choseDate);
                    }
                });

            }

            //負責(zé)更新畫面
            //checkBox狀態(tài)
            function fun1() {
                if ($(this).attr("name") == "checkthis") {
                    var arr = [];//存儲每個選擇框的狀態(tài)
                    var choseDate = {};//存儲被選中的選擇框的數(shù)據(jù)
                    //<li><input type="checkbox" name="check-this" /><span>3</span></li>獲取span里面的值
                    var this_value = $(this).parent().children('span').html();
                    //遍歷每個選擇框取選擇的狀態(tài)
                    $('#' + tableId + ' input[name=checkthis]').each(function (i, ele) {
                        arr.push($(ele).prop('checked'));
                    });
                    //如果有未選中的狀態(tài),去除全選框的選中狀態(tài),否則保留添加全選框的的選中狀態(tài)
                    if (arr.indexOf(false) == -1) {
                        $('#' + tableId + ' input[name=checkall]').prop('checked', true);
                    } else {
                        $('#' + tableId + ' input[name=checkall]').prop('checked', false);
                    }
                } else {
                    //如果選擇全選, 所有的選擇框都選中,去除全選,所有的選擇框去除選中
                    if ($(this).prop('checked')) {
                        $('#' + tableId + ' input[name=checkthis]').prop('checked', true);
                    } else {
                        $('#' + tableId + ' input[name=checkthis]').prop('checked', false);
                    }
                }
            }
            //展示區(qū)狀態(tài)(新增)
            function fun2() {
                $('#' + showId).empty();//清空展示區(qū)里面的內(nèi)容
                updateData();
                //如果沒有選中任何選擇框,則彈出提示
                if (globalV.length == 0) {
                    alert('請先選擇!');
                } else {
                    //如果選中了一些選擇框,則全局變量數(shù)據(jù)不為空,開始遍歷全局變量
                    for (var j = 0; j < globalV.length; j++) {
                        //按照全局變量globalV,給展示區(qū)創(chuàng)建元素;(包含了刪除按鈕)
                        var liElement = '<li>\
                                             <span>'+ globalV[j].id + '</span>\
                                             <p style="display:inline-block;width:20px;height:20px;background-color:red;border-radius:50%;text-align:center">X</p>\
                                         </li>';
                        $('#' + showId).append(liElement);
                    }
                    //給刪除按鈕添加點擊事件
                    bindEvent('#' + showId + ' p', "click", event.removeLi);
                }
            }
            //展示區(qū)狀態(tài)(刪除)
            function fun3() {
                //var findAndChangeState=$(this).parent('li').children('span').html();
                //找到這個刪除按鈕對應(yīng)的父級標(biāo)簽li下面的span標(biāo)簽的內(nèi)容;注意:這個是簡化;就放在了標(biāo)簽里面,實際情況可能是個屬性,獲取的這個值對應(yīng)一個選擇框
                //由這個值來查找對應(yīng)的選擇框,從而改變選擇框的狀態(tài);
                //這里是點擊了刪除按鈕,那么與他對應(yīng)的選擇框的選中狀態(tài)也會被去除
                var findAndChangeState = $(this).parent('li').children('span').html();
                //遍歷選擇框找到與刪除按鈕對應(yīng)的選擇框,將其狀態(tài)改為未選中,同時將全選的選擇框也改為未選中
                $('#' + tableId + ' input[name=checkthis]').each(function (i, ele) {
                    if ($(this).parent().children('span').html() == findAndChangeState) {
                        $(this).parent().children('input').prop('checked', false);
                        $('#' + tableId + ' input[name=checkall]').prop('checked', false);
                    }
                });
                //改完之后這個刪除按鈕對應(yīng)的父級標(biāo)簽
                $(this).parent('li').remove();
            }

            //負責(zé)注冊事件
            var event = {
                select: fun1,
                add: fun2,
                removeLi: fun3
            };
            var bindEvent = function (selector, type, fun) {
                $(selector).bind(type, fun);
            };
            //對各個選擇框綁定事件
            bindEvent('#' + tableId + ' input[type=checkbox]', "click", event.select);
            //點擊添加按鈕的事件
            bindEvent('#' + addClickId, "click", event.add);
        };

        return {
            globalV: globalV,
            yourChose: yourChose
        }
    })()
    checkBox.yourChose('ul1', 'add', 'ul2');
</script>

</html>

更改后的版本里的代碼其實都是原來的代碼,但組織后的效果是:事件統(tǒng)一綁定(bindEvent)瘸洛,畫面統(tǒng)一更新(fun1揍移、fun2、fun3)反肋,數(shù)據(jù)統(tǒng)一設(shè)定(updateData)那伐。

區(qū)分的很清楚品嚣,哪兒出錯找哪兒助被,幾乎不會交叉。而且比較容易拓展株扛,像事件可以繼續(xù)bindEvent綁定养距,畫面更新的函數(shù)可以相應(yīng)與fun1诉探、fun2、fun3并列添加铃在,數(shù)據(jù)的額外處理可以添加到updateData里。

這僅僅是代碼組織上的優(yōu)化,其實代碼本身也有很多可以改進的地方定铜,像全選的判定阳液、選擇區(qū)聯(lián)動刪除等都有更好的思路和代碼實現(xiàn)。

發(fā)現(xiàn)揣炕,其實這里面已經(jīng)有mvc的影子了帘皿,各司其職,分工明確畸陡,事件綁定那部分就算是一個弱controller鹰溜,綁定事件,分發(fā)事件響應(yīng)函數(shù);更新畫面狀態(tài)部分相當(dāng)于view了丁恭,更新畫面曹动;updateData更新數(shù)據(jù)部分更新的就是modle;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末牲览,一起剝皮案震驚了整個濱河市墓陈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌第献,老刑警劉巖贡必,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異庸毫,居然都是意外死亡仔拟,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門飒赃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來利花,“玉大人,你說我怎么就攤上這事盒揉〗唬” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵刚盈,是天一觀的道長羡洛。 經(jīng)常有香客問我,道長藕漱,這世上最難降的妖魔是什么欲侮? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮肋联,結(jié)果婚禮上威蕉,老公的妹妹穿的比我還像新娘。我一直安慰自己橄仍,他們只是感情好韧涨,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布牍戚。 她就那樣靜靜地躺著,像睡著了一般虑粥。 火紅的嫁衣襯著肌膚如雪如孝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天娩贷,我揣著相機與錄音第晰,去河邊找鬼。 笑死彬祖,一個胖子當(dāng)著我的面吹牛茁瘦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播储笑,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼甜熔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了南蓬?” 一聲冷哼從身側(cè)響起纺非,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赘方,沒想到半個月后烧颖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡窄陡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年炕淮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跳夭。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡涂圆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出币叹,到底是詐尸還是另有隱情润歉,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布颈抚,位于F島的核電站踩衩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏贩汉。R本人自食惡果不足惜驱富,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匹舞。 院中可真熱鬧褐鸥,春花似錦、人聲如沸赐稽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晰绎,卻和暖如春锭吨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背寒匙。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留躏将,地道東北人锄弱。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像祸憋,于是被迫代替她去往敵國和親会宪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,162評論 25 707
  • 在線閱讀 http://interview.poetries.top[http://interview.poetr...
    程序員poetry閱讀 114,395評論 24 450
  • 姓名:岳沁 學(xué)號:17101223458 轉(zhuǎn)載自:http://www.cnblogs.com/fsyz/p/80...
    丘之心閱讀 489評論 0 0
  • 用rails的都用過where方法蚯窥,總結(jié)了一些基本的掸鹅,歡迎提供更多的內(nèi)容。 where方法用來指定限制獲取記錄的條...
    GALAXY_ZMY閱讀 4,981評論 0 3
  • 原創(chuàng)160篇 文 / 烽火 走進“南京大屠殺”陳列館 七月的暑天驟然下起了雪…… 歷史在揭過殘暴的一幕時 匆匆地畫...
    慧心育子閱讀 229評論 0 1