模塊化、閉包與立即執行函數的使用、MVC裏的V和C

模塊化、MVC裏的V和C、閉包與立即執行函數的使用

這篇文章記錄我寫在線個人簡歷過程中學習的知識
完整代碼(暫未完成)
預覽地址

輪播Swiper組件的使用

英文官網

中文網--Swiper4.x使用方法

模塊化

學習寫代碼的方法:
CRM
抄,運行,修改
P6R2AU.png

模塊化:把對應功能放到塊裏面,這個塊可以是文件,或者div或者別的等等

P6IEXd.png

立即執行函數的使用

將js分成不同的幾個模塊後,然後使用文件引入,但是會出現問題:如果使用var 聲明變量,那麼就會成爲全局變量,這樣容易覆蓋.

ES6之前,只有函數裏面纔有局部變量.
如果只用花括號包起來,那麼在C++或者JAVA裏面就是局部變量,但是JS裏面會變量提升,提升到當前函數的最高地方,所以仍然是全局變量.

所以如果想用局部變量,解決方法是把它放到一個函數中,然後立即執行,這樣這個函數內部的變量就是局部變量.也不會被相同名字的全局變量覆蓋.

P6oiEq.png
不加感嘆號就會語法錯誤,不會執行.所以得加一個感嘆號,取反,就會運行後面的代碼,執行後面的函數.雖然改變了返回值,但是我們不需要返回值.所以改變了也無所謂

所以接下來我們將所有自己分離出來的單個js文件,都使用立即執行函數!function(){}.call()包起來

這樣纔算真正的模塊化,代碼相互之間沒有影響.
P6oZ2F.png

ps:
ES6模塊

閉包的使用

下面的例子都使用立即執行函數隔離作用域
如果兩個模塊之間需要交流,例如在第一個模塊上初始化,在第二個模塊上使用

方法一:使用window

比如兩個模塊

module1.js和module2.js都被引入一個html文件裏
PcP0PS.png

//module1.js
!function(){
    var person = window.person = {
        name:"frank",
    }
    //局部變量person和全局變量person用的是同一個地址
}.call()

雖然不同變量,但是是同樣的地址

//module2.js
!function(){
    var person = person;//即var person = window.person;
    console.log(person);
}.call();

這樣不同模塊間就可以通信,但這種方法不好.

方法二:使用閉包

始終不知道person的全部信息
,只能知道age的信息,且只能做一些它允許你操作的事情,這樣module1就會對局部變量person有一個掌控.不會出現有人把person變成-1的情況,因爲他訪問不到age,他只能去GrowUp,除此之外沒有能訪問到的方法.

//module1.js
!function(){
    var person = {
        name:"mataotao",
        age:18,
    };
    window.mataotaoGrowUp = function(){
        person.age+=1;
        return person.age;
    };
}.call();
//module2.js
!function(){
    var newAge = window.mataotaoGrowUp();
    console.log(newAge);//19
}.call();

閉包在哪裏?

如果一個函數訪問了函數外的變量(mataotaoGrowUp()使用了person.age),那麼 函數+函數外的變量,就是 閉包.

閉包作用:

  1. 用來 隱藏數據細節 (不告訴你多少歲但是你可以讓他漲一歲,隱藏了age 的細節和name)
  2. 可以用來 做訪問控制 (只能訪問到age,無法訪問到name)

如果沒有立即執行函數來模塊化,那麼這個閉包毫無意義,因爲person直接使全局變量,所有的函數都可以訪問到,並且修改也無法隱藏數據細節

PcPSH0.png

立即執行函數+閉包 實現對象細節的封裝的方法

面試官會將上面的module1做如下修改(實際本質不變)

//module1.js
var accessor = function(){//這是一個返回了匿名函數的函數,accessor-訪問器
    var person = {
        name:"mataotao",
        age:18,
    };
    return function(){
        person.age+=1;
        return person.age;
    };
}
var growUp = accessor();//執行accessor得到一個GrowUp函數
//growUp現在是一個全局變量了
growUp();

實際growUp()就相當於立即執行了,因爲我聲明瞭一個函數,而且立即執行了

這就是閉包

MVC的V和C

MVC的前提就是 模塊化
P6IKtf.png

View就是能看到的東西

例如在
<script src="./js/init_Swiper.js"></script><!-- 初始化Swiper>標籤 -->這個模塊中我們初始化了一個Swiper

PciCqI.png
這個並且對.swiper-container這個div進行操作,.swiper-container這個div就是 VIEW(用戶可以看到的東西).

對於輪播組件來說,這一部分就是他的view部分
PciiZt.png

這個div就是init-swiper這個模塊的view.

明白這個之後我們將view單獨分離出來

分離view

我們修改代碼,單獨將view分離,例如輪播圖的view:
PcFM1e.png

PcFDns.png

也將剩下的幾個js模塊進行修改

例如<script src="./js/sticky-navbar.js"></script>

PcF6A0.png

view就是要告訴js,html中的哪一塊是我要操作的東西

PcFhjJ.png

Controller就是控制View的方法

MVC中的C用來控制/操作view

以topNavBar爲例
PcFjjH.png
將要做的操作寫成controller函數,並把要操作的view當做參數傳進去,實現對view的控制/操作

進一步的改進:

PcEAmj.png

需要注意:

  1. 對象的函數裏的this,就是對象本身`controller.init(view);
    //相當於controller.init.call(controller,view);//this就是當前對象`

`this.bindEvents();

        //相當於this.bindEventS.call(this)`,這裏的this就是init函數裏call的controller,所以這個this是轉過來了,也是對象本身

繼續優化,分離代碼

如果我們要做其他的事情,比如把激活和不激活這個導航分離,不要寫在bindEvents裏了,繼續在對象裏添加操作的函數
PcV0P0.png
bind(this)後,就是把controller綁定到這個函數的this上,把這個函數的this由window變成controller,之後this.active();this.deactive();這兩個this 就變成了controller了

bind方法用於將函數體內的this綁定到某個對象,然後返回一個新函數。
bind()使用方法

這裏的bind()就是將函數體內的this綁定到了controller,函數體內的this就是controller了

如果不用bind()也可以用箭頭函數()=>{},箭頭函數本身是沒有this的.所以如果在箭頭函數用this,那麼就是箭頭函數外面的離它最近的this!
PceR9x.png

最終stick-navBar的代碼:
PcmvJ1.png

對輪播的js模塊使用controller進行優化

本來:
PcnCLD.png
修改後:
PcnNlV.png
修改之後的前後對比
結構非常清晰有條理,將整個要做的事井井有條得分爲幾個部分

對當頁跳轉的緩動動畫也進行controller的優化

下面是當頁跳轉的緩動動畫修改後的代碼:
Pc8uZV.png

總結

這樣代碼就不會顯得混亂了,controller對view的操作被有條理地分開,有初始化view,綁定view事件,激活這個view,不激活這個view等等對view的操作
controller所有的屬性就是對view的所有操作!!!
這就是mvc裏的c的意義

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章