1. 程式人生 > >從壹開始前後端分離 [ Vue2.0+.NET Core2.1] 十六 ║Vue基礎:ES6初體驗 & 模組化程式設計

從壹開始前後端分離 [ Vue2.0+.NET Core2.1] 十六 ║Vue基礎:ES6初體驗 & 模組化程式設計

緣起

昨天說到了《從壹開始前後端分離 [ Vue2.0+.NET Core2.1] 十五 ║ Vue前篇:JS物件&字面量&this》,通過總體來看,好像大家對這一塊不是很感興趣,嗯~~這一塊確實挺枯燥的,不能直接拿來程式碼跑一下那種,不過還是得說下去,繼續加油吧!如果大家對昨天的小demo練習的話,相信現在已經對JS的面向物件寫法很熟悉了,如果巢狀字面量定義函式,如何使用this關鍵字指向。今天呢,主要說一下ES6中的一些特性技巧,然後簡單說一下模組化的問題,好啦,開始今天的講解~

還是老規矩,一言不合就是上程式碼

str1 = 'Hello JS!';
function fun1() {
 
var str1 = 'Hello C#!'; } fun1(); alert(str1);

大家猜猜,最後會彈出來哪一句話?

零、今天要完成淺紫色的部分

一、什麼是傳說中的ES6

這些定義網上一大堆,不過還是粘出來,大家可以統一看一下,簡單瞭解瞭解:

1、定義

ECMAScript 6是JavaScript語言的下一代標準,在2015年6月正式釋出。它的目標,是使得JavaScript語言可以用來編寫複雜的大型應用程式,成為企業級開發語言。

標準的制定者有計劃,以後每年釋出一次標準,使用年份作為標準的版本。因為當前版本的ES6是在2015年釋出的,所以又稱ECMAScript 2015。也就是說,ES6就是ES2015,下一年應該會發布小幅修訂的ES2016。

2、有哪些新的變化

程式語言JavaScript是ECMAScript的實現和擴充套件,由ECMA(一個類似W3C的標準組織)參與進行標準化。ECMAScript定義了:

ECMAScript標準不定義HTML或CSS的相關功能,也不定義類似DOM(文件物件模型)的Web API,這些都在獨立的標準中進行定義。ECMAScript涵蓋了各種環境中JS的使用場景,無論是瀏覽器環境還是類似

node.js的非瀏覽器環境。

3、ECMAScript和JavaScript的關係

1996年11月,JavaScript的創造者Netscape公司,決定將JavaScript提交給國際標準化組織ECMA,希望這種語言能夠成為國際標準。次年,ECMA釋出262號標準檔案(ECMA-262)的第一版,規定了瀏覽器指令碼語言的標準,並將這種語言稱為ECMAScript,這個版本就是1.0版。

該標準從一開始就是針對JavaScript語言制定的,但是之所以不叫JavaScript,有兩個原因。一是商標,Java是Sun公司的商標,根據授權協議,只有Netscape公司可以合法地使用JavaScript這個名字,且JavaScript本身也已經被Netscape公司註冊為商標。二是想體現這門語言的制定者是ECMA,不是Netscape,這樣有利於保證這門語言的開放性和中立性。

因此,ECMAScript和JavaScript的關係是,前者是後者的規格,後者是前者的一種實現

二、var、let 與 const 塊作用域

這裡先說下,作用域的問題

1、ES6之前,JavaScript 並沒有塊級作用域,所謂的塊,就是大括號裡面的語句所組成的程式碼塊,比如

function blog(bl) {
    if (bl) {
        var foo = "Blog";
    }
    console.log(foo);
}

blog(true); //=> Blog

2、雖然變數變數foo 位於 if 語句的程式碼塊中,但是 JavaScript 並沒有塊級作用域的概念,因此被新增到了當前的執行環境 - 即函式中,在函式內都可以訪問到。

因此:var 定義的變數是函式級作用域,作用範圍是在函式開始階段和函式執行完成之前內都是存在的;

   並且如果該函式內部還存在匿名函式等特殊函式,這個 var 出的變數在匿名函式中任然可以用; 

3、在ES出現後,定義了一個新的命名方式 let 

function Blog(bool) {
    if (bool) {
        let foo = "Blog";
    } else {
        console.log(foo);
    }
}
Blog(false); //這裡會報錯 Uncaught ReferenceError: foo is not defined

因此,使用 let,上述問題完全解決,let出的變數作用域是 塊作用域,在離開某一程式碼塊,該變數就會被銷燬不存在

應當儘可能的避免用 var,用 let 來代替,除非你需要用到變數提升。

 4、隨著面向物件思維的出現,JS也出現了常量的定義 const

const 與 let 的基本用法相同,定義的變數都具有塊級作用域,也不會發生變數提升。不同的地方在於,const 定義的變數,只能賦值一次。

const foo='Blog';
function Blog(bool) {
    if (bool) {
         foo = "Vue";
    } else {
        console.log(foo);
    }
}
Blog(true); //這裡會報錯 Identifier 'foo' has already been declared

因此const多用作不發生變化的變數定義,比如定義月份,或者,星期等:const months = [];

三、箭頭函式

還記得昨天的那個小demo麼,今天再說一個地方

var obj = {
    data: {
        books: "",
        price: 0,
        bookObj: null
    },
   bind() {//注意!ES6 中,可以使用這種方法簡寫函式,等價於 bind: function () {
        var that = this;
     //普通函式
        //$(".ok").click(function () {
     // console.log(this);//這個時候,this,就是 .ok 這個Html標籤
// var bookItem = that.data.bookObj; // var _parice = $(bookItem).data("price"); // var _book = $(bookItem).data("book"); // that.data.books += _book + ","; // that.data.price += parseInt(_parice); // that.show(); //});      //箭頭函式 $(".ok").click(() => { var bookItem = this.data.bookObj;//在箭頭函式中,this指向的是定義函式時所在的物件 var _parice = $(bookItem).data("price"); var _book = $(bookItem).data("book"); this.data.books += _book + ","; this.data.price += parseInt(_parice); this.show(); $(".bg,.popupbox").hide(); }); }, }

在普通的click函式中 this 指向物件  $(".ok") ,因此,我們如果想要獲取定義的物件中的資料(obj.data),那我們只能在 click 方法前,就去用一個 that 自定義變數來儲存這個 this ,

但是在箭頭函式中就不一樣了,this 始終指向定義函式時所在的物件(就是 obj 物件);

是不是更方便些!

在Vue中,也經常使用 vue例項,或者this來獲取相應的值

var vm = new Vue({
    el:'#root',
    data:{
        tasks:[]
    },
    mounted(){
        axios.get('/tasks')
        .then(function (response) {
            vm.tasks = response.data;//使用Vue例項
        })
    },
    mounted2(){
           axios.get('/tasks')
            .then(response => this.tasks = response.data);//箭頭函式 this 
    }
});

四、引數預設值 && rest引數

1、 在ES6中,可以像C#那樣定義預設引數

function buyBook(price, count = 0.9){
    return price * count;
}
buyBook(100);

//甚至可以將方法的值賦給引數
function buyBook(price, count =GetCount()){
    return price * count;
}
function GetCount(){
    return 100;
}

buyBook(200);

2、不僅如此,還可以快速獲取引數值

//ES6之前是這樣的
function add(a,b,c){
    let total = a + b + c;
    return total;
}
add(1, 2, 3);

//ES6你可以這麼操作,提供了 rest 引數來訪問多餘變數
function sum(...num) {
    let total = 0;
    for (let i = 0; i < num.length; i++) {
        total = total + num[i];
    }
    return total;
}
sum(1, 2, 3, 4, 6);

五、ES6中的表示式

1、字串表示式

在之前我們都是這樣使用字串表示式

var name = 'id is ' + bid+ ' ' + aid + '.'
var url = 'http://localhost:5000/api/values/' + id

在ES6中我們有了新語法,在反引號包裹的字串中,使用${NAME}語法來表示模板字元:

var name = `id is ${aid} ${bid}`
var url = `http://localhost:5000/api/values/${id}`//注意是反引號,英文輸入下下的,Tab鍵上邊的那個

2、還有就是多行表示式的寫法

//之前我們都是這麼寫的
var roadPoem = '這個是一個段落'
    + '換了一行'
    + '增加了些內容'
    + 'dddddddddd'
 
//但是在ES6中,可以使用反引號
var roadPoem = `這個是一個段落
   換了一行
    增加了些內容,
    dddddddddd
    結尾,`
 

六、模組化定義

 1、什麼是模組化開發

 模組化開發是基於一定的語法規範,通過程式碼書寫設計,使程式碼耦合度降低,模組化的意義在於最大化的設計重用,以最少的模組、零部件,更快速的滿足更多的個性化需求。因為有了模組,我們就可以更方便地使用別人的程式碼,想要什麼功能,就載入什麼模組。

用阮一峰大神的說法就是:

今天的Web網頁越來越像桌面程式,網頁上載入的javascript也越來越複雜,前端工程師不得不開始用軟體工程的思維去管理自己的程式碼。Javascript模組化程式設計,已經成為一個非常迫切的需求。理想情況下,開發者只需要實現核心的業務邏輯,其他都可以載入別人已經寫好的模組。但是,Javascript不是一種模組化程式語言,它不支援"類"(class),更別提"模組"(module)了。(正在制定中的ECMAScript標準第六版將正式支援"類"和"模組",但還需要很長時間才能投入實用

 就這樣,Node.js 就出現了,一個用來開發伺服器端的js框架,基於commonJs的模組化。當然中間還有CMD,AMD(這個東西我還需要慢慢研究下);

2、模組化在程式碼中是如何體現的呢

1、首先我們先看看普通的定義一個類是如何寫的

新建一個index.js 檔案

class Student {
    constructor(homework= []) {
        this.homework= homework;
    }

    study() {
        console.log(this.homework);
    }
}

const st = new Student ([
    'blog',
    'api',
    'vue'
]);

st.study();

然後新建一個index.html頁面,引用該js檔案

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

    <script src="index.js"></script>
</body>
</html>

然後就可以得到結果:

 

這是一個很簡單的,定義一個Student 類,然後定義一個方法,通過傳遞一個數組引數,來例項化。

這樣雖然很簡單,但是卻無法複用,無法作為一個零件來使用。而且如果有一個地方要修改,多處都需要修改,這個面向物件的思想,沒有發揮出來;

這個時候你可能會說,把這個拆成兩個問題,就可以複用了,嗯~試試

2、我們把這兩個檔案分開

新建一個Student.js ,定義處理Student類;然後新建一個main.js方法,來呼叫例項化該類,就可以使用

然後在 index.html 頁面裡去引用這兩個檔案

<body>

    <script src="Student.js"></script>
    <script src="main.js"></script>
</body>

當然結果是一樣的,這樣雖然實現了分隔開,也可以去不同的地方呼叫;

但是,從上文中你也看的出,如果不是自己寫的程式碼,一般不太容易看的明白,到底是什麼意思,直觀性不是很好,我們將無法看到彼此間的關聯(main.js 載入 Student.js),

3、我們用模組的寫法設計這個呼叫

ES6 模組不是物件,而是通過export命令顯式指定輸出的程式碼,再通過import命令輸入。

我們直接修改之前的程式碼

然後在 index.html 頁面中,只需要引用 <script src="main.js"></script> 就行

4、因為瀏覽器現在還不能直接執行模組化程式碼,所以我們需要打包,打包工具有很多,比如 webpack

注意:這裡用到打包概念,之後會講到,這裡就先略過,以後會講到,步驟是

首先安裝npm,或者阿里映象 cnpm(npm其實是Node.js的包管理工具,這個在我們之後的Node.js環境配置中,自動隨帶安裝)
全域性安裝 rollup.js   $ cnpm install --global rollup

cd 當前資料夾 $ rollup main.js --format iife --output bundle.js 


然後只需要引用生成的  <script src="bundle.js"></script>

5、這裡我因為測試,已經生成好了,打包出來的bundle.js 是這樣的,是不是兜兜轉轉又回到了之前的寫法,其實ES6的模組開發,就是匯入的程式碼塊兒

(function () {
    'use strict';

    class TaskCollection {
        constructor(tasks = []) {
            this.tasks = tasks;
        }

        dump() {
            console.log(this.tasks);
        }
    }


    const tc = new TaskCollection([
        'blog',
        'api',
        'vue'
    ]);

    tc.dump();

}());

 總結來說:模組化的好處和問題

可維護性

靈活架構,焦點分離

方便模組間組合、分解

方便單個模組功能除錯、升級

多人協作互不干擾

可測試性,可分單元測試;

效能損耗

系統分層,呼叫鏈會很長

模組間通訊,模組間傳送訊息會很耗效能

 其實說白了,就是JS在作為一個開發語言來說,越來越靠近了後端伺服器語言。

七、每天一個小Demo

這裡是一個特別特別簡單的關於ES6的留言板,大家可以看一看

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h2>簡易留言板</h2>
    <input type="text" placeholder="請輸入內容" size="30" id="msg">
    <input type="button" value="留言" id="btn">
    <div id="msg-div"></div>
    <script>
        //let 定義塊級變數
        let oBtn = document.getElementById('btn');
        let msg = document.getElementById('msg');
        let content = document.getElementById('msg-div');
        oBtn.onclick = () => {
            let ovalue = msg.value;
            let ali = document.createElement('p');
            //ES6模板字串
            //多行表示式
            ali.innerHTML = `${ovalue}<span style="color:red;">  
                                刪除</span>`;

            var aspan = content.getElementsByTagName('p');
            if (aspan.length > 0) {
                content.insertBefore(ali, aspan[0]);
            } else {
                content.appendChild(ali);
            }
            msg.value = '';
            var oSpan = content.getElementsByTagName('span');
            for (let i = 0; i < oSpan.length; i++) {
                //ES6箭頭函式
                oSpan[i].onclick = function () {
                    content.removeChild(this.parentNode);//注意this的指向
                };
            }
        };
    </script>
</body>
</html>

八、結語

通過這兩天的學習,大家瞭解到了,JS的一些特性和變化:巢狀字面量的定義,面向物件的封裝,類和模組化的使用,ES6的日益成熟,通過打包進行釋出等等,都能表現出JS在向一個伺服器端語言快速邁進的衝動,也是極大的推動了,MVVM的到來,從而實現像Node.js 這種,可以脫離瀏覽器環境也能執行的不一樣視角。好啦,關於JS高階,這兩講已經差不多了,當然還有其他的,大家可以自行學習瞭解,其實這兩篇都懂的化,已經差不多了,明天咱們就開始正式進入Vue入門篇,通過引用Vue.js 實現栗子。