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

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

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

輪播Swiper組件的使用

英文官網html

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

模塊化

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

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

P6IEXd.png

當即執行函數的使用

將js分紅不一樣的幾個模塊後,而後使用文件引入,可是會出現問題:若是使用var 聲明變量,那麼就會成爲全局變量,這樣容易覆蓋.面試

ES6以前,只有函數裏面纔有局部變量.
若是隻用花括號包起來,那麼在C++或者JAVA裏面就是局部變量,可是JS裏面會變量提高,提高到當前函數的最高地方,因此仍然是全局變量.segmentfault

因此若是想用局部變量,解決方法是把它放到一個函數中,而後當即執行,這樣這個函數內部的變量就是局部變量.也不會被相同名字的全局變量覆蓋.閉包

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

因此接下來咱們將全部本身分離出來的單個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就是當前對象
  2. 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的意義

相關文章
相關標籤/搜索