【技巧篇】JavaScript設計模式之策略模式應用

阿9發表於2018-07-23

看標題好像非常高大威猛的樣子?,且不要被題目嚇到,或許這個技巧很多朋友在工作中都運用過,只是可能不夠完善或者不care這種寫法屬於什麼設計模式。

是的,我們的目的很明確,就是DRY——Don't repeat yourself!

文章開頭,我們想來點一下題,什麼是策略模式?

策略模式的定義:每個策略中定義一系列的演算法,把它們一個個封裝起來,並且使它們可以相互替換。

好吧,我已開始也是被這個定義嚇尿了。簡單地舉個栗子說,就是你下班回家,可以走路、騎車、坐車、開車、開飛機等,每種方式都是一個策略,在程式碼裡就可以將每個策略寫成一個個的方法,方便管理。這樣就不用使用一大堆判斷語句了,難看而且不好維護。

我們今天講的是技巧,在這裡就不得不說到事件委託——又是一個高大威猛的概念(概念雖好,其實在程式碼裡就很好理解,不信接著看)

沒有場景的程式碼都是耍流氓!

【技巧篇】JavaScript設計模式之策略模式應用
【技巧篇】JavaScript設計模式之策略模式應用

場景很簡單,就是點選“已有賬號,立即登入”切換到登入,點選“還沒有賬號”切換到註冊

有些小夥伴一下就明白了怎麼回事,不就是個點選切換嘛!誒,是滴,就是這麼簡單,但我們就是喜歡吃豬蹄吃出熊掌的感覺?

寫兩個簡單的div代替一下(其中class中的hide代表隱藏的css):

<div id="login-box">
這是個登入框
   <span id="goToRegister">還沒有賬號?馬上註冊</span
</div>

<div id="register-box" class="hide">
這是個註冊框
   <span id="goToLogin">已有賬號,立即登入</span
</div>
複製程式碼

善用jQuery的小夥伴們一下子就想到了該怎麼寫:

$('#goToRegister').click(function () {
            $('#login-box').addClass('hide')
                .siblings('#register-box').removeClass('hide');
        });
        $('#goToLogin').click(function () {
            $('#register-box').addClass('hide')
                .siblings('#login-box').removeClass('hide');
        });
複製程式碼

不得不佩服jQuery,簡單明瞭。但是這樣寫有一個很大的問題,就是頁面如果有很多的點選事件的時候,難道也要去一個一個複製貼上類似的程式碼嗎?還是那句話——don't repeat youself!

還記得我們剛才提到過的事件委託嗎?還不清楚什麼是事件委託還是要去搜一下,簡單的理解就是所有子元素的相同事件都委託到父元素。

$('body').on("click",function (e) {
            if (e.target.id === 'goToLogin') {
                $('#register-box').addClass('hide')
                    .siblings('#login-box').removeClass('hide');
            } else if (e.target.id === 'goToRegister') {
                $('#login-box').addClass('hide')
                    .siblings('#register-box').removeClass('hide');
            }
        })
複製程式碼

是的,這就是事件委託,把兩個點選事件都委託給body。為什麼要用事件委託呢,一方面是好看(可讀性高),不用像上面的程式碼一樣複製那麼多的事件程式碼;另一方面是效能,因為掛載事件的時候是很消耗效能的,一兩個事件可能不覺得,一旦有個幾十上百個事件(比如說列表)的時候,你就會臉上笑嘻嘻,心裡媽賣批。

程式碼好像稍稍完善了一丟丟,但是!就像上面說的,一旦有很多的而且是不一樣子元素的事件的時候,你就要寫很多很多判斷語句,這是我們萬萬不想看到的,這個時候我們就要想想有沒有什麼設計模式來解決此類問題。對,策略模式。

很明顯這裡有兩種策略:跳到登入或者跳到註冊

var cutOver = {
            goToLogin: function () { //跳到登入
                $('#register-box').addClass('hide')
                    .siblings('#login-box').removeClass('hide');
            },
            goToRegister: function () { //跳到註冊
                $('#login-box').addClass('hide')
                    .siblings('#register-box').removeClass('hide');
            }
        };
複製程式碼

說到策略這個詞,我們不得不聯想到執行者,那麼在這裡的執行者是誰呢?我們要寫一個去執行策略的方法:

var eventProxy = function (command) {
            cutOver[command] && cutOver[command]();
            //command存在的時候才執行策略
        };
複製程式碼

最後就是策略模式的事件委託:

$('body').on("click",function (e) {
            eventProxy(e.target.id);
        });
複製程式碼

寫到這裡其實就算結束了。慢著!說好的技巧呢?聰明的你會注意到我在策略物件裡的方法名其實是兩個div的id。所以,最大的技巧既不是策略模式,也不是事件委託,而是這個相當於粘合劑一樣的小技巧,是它把策略模式和事件委託很好的聯絡到一起。


相關文章