小程序模板網(wǎng)

在你開發(fā)微信小程序時能用上的那些ES6特性

發(fā)布時間:2017-12-08 17:08 所屬欄目:小程序開發(fā)教程

微信小程序的官方開發(fā)工具中,已經(jīng)集成了 babel 插件對 ES6 語法進(jìn)行轉(zhuǎn)換,各種第三方工具自然更少不了了。

所以可以放心的嘗試使用 ES6,體驗新標(biāo)準(zhǔn)帶來的各種便利之處,省下時間后學(xué)習(xí)充電,或者早點下班、鍛煉身體、下廚做個菜,調(diào)節(jié)生活又放松身心,豈不美哉?

那么,在小程序開發(fā)的過程中,有哪些 ES6 特性是可以給我們帶來便利,提高開發(fā)效率的呢?這邊就結(jié)合實例,一一來說一說吧。

1. 箭頭表達(dá)式

做前端開發(fā)的,開始階段基本會遇到 this 與 閉包 帶來的坑————一些異步操作中,回調(diào)函數(shù)中丟失了當(dāng)前函數(shù)的上下文對象,導(dǎo)致異步操作完成后,更新原有上下文失敗。

為了避免這個問題,以前大家都是自己用變量保存一個閉包外部上下文的引用,取的名字可能千奇百怪:
that/_this/$this/self…在異步操作完成后的回調(diào)中,通過調(diào)取這個閉包外層的變量,達(dá)到更新回調(diào)前函數(shù)上下文對象的目的。

ES6 中增加了 箭頭表達(dá)式,效果和匿名函數(shù)相似,但箭頭表達(dá)式更為簡練,且內(nèi)部執(zhí)行時的 this 與外側(cè)一致,不再需要每次都額外增加變量引用了。

微信小程序里,對每個頁面編寫的代碼邏輯,都作為生命周期鉤子函數(shù)(如:onLoad, onShow, onUnload)和自定義函數(shù)(如:各類組件回調(diào)函數(shù))寫在 AppService 內(nèi)。

這兩種函數(shù)內(nèi),this 都指向當(dāng)前 Page 對象,在這些函數(shù)里做的各種異步操作,回調(diào)內(nèi)的 this 基本都應(yīng)該仍然保持為當(dāng)前 Page 對象。在這個情況下,使用箭頭表達(dá)式可以減少重復(fù)的工作、也減少遺漏 this 時出錯的幾率。

// ES5
var net = require('../public/net');
Page({
    data: {
        list: []
    },
    onShow: function () {
        var self = this;
        net.get('/Index/getList', function (res) {
            res = res || {};
            var status = res.status,
                data = res.data,
                list = data.list;
            if(status == 2) {
                self.setData({list: list});
            }
        });
    }
});
// ES6
import * as net from '../public/net';
Page({
    data: {
        list: []
    },
    onShow: function () {
        net.get('/Index/getList', (res = {}) => {
            let {status, data: {list}} = res;
            if (status == 2) {
                // 此處 this 的指向與 onShow 內(nèi)一致,無需增加 self 變量
                this.setData({list});
            }
        });
    }
});

2. 數(shù)組方法

雖然都說微信小程序 wxml 的 Mustache 語法與 Vue.js 很相似。但據(jù)說是為了分離 UI 線程和 AppService 線程,微信小程序暫時并不支持 {{value | filter}} 的寫法。

這時候可以借助于 ES5 中為數(shù)組對象增加的方法,之前因為瀏覽器兼容性問題,不一定全部能用。如今在移動端了,就盡情用起來吧:

輸出數(shù)據(jù)前,對后臺傳來的列表數(shù)據(jù)做一些預(yù)處理后再顯示時,通常使用 Array.prototype.forEach 和 Array.prototype.map 進(jìn)行相應(yīng)處理;
篩選掉無效數(shù)據(jù),可以使用 Array.prototype.filter。

// js
var helpers = {
    // 判斷是否有時間參數(shù)
    hasTime: (i) => {
        return !isNaN(parseInt(i.stamp));
    },
    // 時間轉(zhuǎn)換處理
    parseTime: (i) => {
        i.time = new Date(i.stamp + '000');
        return i;
    }
};
net.get('/Index/getList', (res = {}) => {
    let {status, data: {list}} = res;
    this.set({
        list: list.filter(helpers.hasTime)  // 篩選掉沒有時間戳字段的數(shù)據(jù)
                  .map(helpers.parseTime)   // 將時間戳字段轉(zhuǎn)化為 JS 的 Date 對象
    });
});

3. Rest 解構(gòu)賦值

直到寫這篇文章的時候,小程序官方的組件標(biāo)準(zhǔn)也仍然沒有出來。

目前的通常處理方案,一般是通過 template 配合解構(gòu)賦值不同對象的數(shù)據(jù),實現(xiàn)組件各自狀態(tài)、事件處理函數(shù)互相獨立的效果。

如,有兩個 template 都從 data 中綁定數(shù)據(jù)。


        < template name="banner">
    < view class="banner-wrap">
        < view wx:for="{{data}}" class="banner-item">
        < !--...-->
        < /view>
    < /view>
< /template>
< template name="comic-list">
    < view class="comic-list">
        < view wx:for="{{data}}" class="comic-item">
        < !--...-->
        < /view>
    < /view>
< /template>

AppService 中對于這兩個模板創(chuàng)建兩個不同對象,即可管理自身狀態(tài),不用擔(dān)心字段名重復(fù)的問題。

Page({
    onLoad: function () {
        // 加載 Banner 數(shù)據(jù)并顯示
        this.loadData('/bannerState/get', (data) => {
            this.setData({
                bannerState: data
            });
        });
        // 加載 ComicList 數(shù)據(jù)并顯示
        this.loadData('/comicListState/get', (data) => {
            this.setData({
                comicListState: data
            });
        });
    },
    loadData: function (url, callback) {
        var data = [];
        /* 從 url 加載數(shù)據(jù)的邏輯 */
        setTimeout(() => {
            callback({
                data: data
            });
        }, 100);
    }
});

頁面內(nèi)渲染模板時,對 bannerState 和 comicListState 字段進(jìn)行解構(gòu)即可。

< template is="banner" data="{{...bannerState}}"/>
< template is="comicList" data="{{...comicListState}}"/>

這是個非常重要且實用的特性,基于這個基礎(chǔ)可以封裝出有具有通用邏輯的基類,實現(xiàn)模塊內(nèi)部的邏輯閉環(huán),達(dá)到組件化開發(fā)的效果。

4. 增強的對象字面量

setData()

setData() 中的數(shù)據(jù)字段名與變量名一致時,不需要重復(fù)寫兩遍,上面加載數(shù)據(jù)的代碼就可以這樣簡寫:

this.loadData('/bannerState/get', (bannerState) => {
    this.setData({
        bannerState
    });
});

數(shù)據(jù)字段較多時,效率會快很多。減少了整理和重構(gòu)代碼需要調(diào)整的地方,降低維護(hù)成本。

// 傳統(tǒng)對象字面量
this.setData({
    data1: data1,
    data2: data2,
    data3: data3,
    data4: data4,
    data5: data5
});
// 增強的對象字面量
this.setData({data1, data2, data3, data4, data5});

成員方法

增強的對象字面量寫法,還包括函數(shù)的簡寫:

// 傳統(tǒng)的對象字面量
var comicState = {
    onTap: function (e) {
        // ...
    },
    onScroll: function (e) {
        // ...
    }
};
// 增強的對象字面量
var comicState = {
    onTap(e) {
        // ...
    },
    onScroll(e) {
        // ...
    }
};

這種簡潔的成員函數(shù)寫法,是不是很像 class 中的函數(shù)聲明?

class ComicState {
    onTap (e) {
        // ...
    }
    onScroll (e) {
        // ...
    }
}

5. Class 與繼承

使用 ES5 的 prototype 寫法,實現(xiàn)簡單的類繼承也沒太大問題,但涉及到父類函數(shù)調(diào)用等情況,代碼耦合度會變得更高,需要一定經(jīng)驗才能寫出方便維護(hù)的代碼。

通過 ES6 語法來實現(xiàn)類繼承的話,有了統(tǒng)一的標(biāo)準(zhǔn),寫出的類繼承更加直觀,更方便調(diào)整。

class Base {
    constructor (options, otherArg) {
        // Do something.
    }
}
class ChildType extends Base {
    constructor (options) {
        super(options, ChildType);
        // Do something.
    }
}

6. 塊作用域變量

使用 for 對數(shù)據(jù)做迭代遍歷時,語句中聲明的 var 型變量名作用域其實提升到了函數(shù)頂部,不同迭代間忘記處理的話,可能會導(dǎo)致數(shù)據(jù)污染。

改為使用 ES6 的 let/const 可避免這一情況,放心使用塊級作用域。

for (let k in data1) {
    // ...
}
// ...
let k = 0;
// ...
for (let k in data2) {
    // ...
}

補充:

微信小程序使用的 babel 啟用的轉(zhuǎn)碼規(guī)則可能不是最新的,截止目前版本,測試使用以下 ES6 會有問題,需要注意。

  • class 內(nèi)部聲明的靜態(tài)字段;
// 以下代碼在 babel 的 repl 中能正常處理,在小程序開發(fā)工具內(nèi)會報錯
class TestClass {
    static MODE = {
        NORMAL: 1,
        DISABLED: -1
    }
}
// 輸出:1
console.log(TestClass.MODE.NORMAL);
  • for...of 語法遍歷對象(直接使用了 Symbol.iterator,移動端可能尚未實現(xiàn));

20170329 更新:新版本開發(fā)工具似乎已經(jīng)完善了這個問題,可以使用下面的 ES6 寫法了:

function Test() {
    this.a = 1;
    this.b = 2;
}
Test.prototype = {
    c: 3
};
var o = new Test();
// ES5
for (var k in o) {
    if (k.hasOwnProperty(k)) {
        console.log(o[k]);
    }
}   // 輸出:1 2
// ES6
for (let k of Object.keys(o)) {
    console.log(o[k]);
}   // 輸出:1 2

for...of 用于數(shù)組遍歷時,效果與 Array.prototype.forEach 類似,區(qū)別是可以在途中 break 中斷循環(huán),無需每次遍歷整個數(shù)組。

// Array.prototype.forEach
comicList.forEach((c) => {
    // ...
});
// for...of
for (let c of comicList) {
    // ...
}


易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://22321a.com/wxmini/doc/course/18081.html 復(fù)制鏈接 如需定制請聯(lián)系易優(yōu)客服咨詢:800182392 點擊咨詢
QQ在線咨詢