by yugasun from yugasun.com/post/you-ma… 本文可全文轉載,但須要保留原做者和出處。javascript
上一篇中咱們已經學會使用 babel
將 ES6 轉化爲 ES5 了,而且展現了一些 ES6 代碼,這一篇將重點聊聊 ES6 在 Vuejs 項目中一些部分應用。css
摘自 ECMAScript 6 簡介:html
你們習慣將
ECMAScript 6.0
簡稱爲ES6
,它是 Javascript 語言的下一代標準,它的目標,是使得 Javascript 語言能夠用來編寫複雜的大型應用程序,成爲企業級開發語言。前端
說是下一代,其實早在 2015 年 6月就正式發佈了(因此又稱 ES2015
),截止今日已經快3年了,很快 ES7/ES8 都要出來了,因此做爲前端開發者,學習 ES6 已是個必然命題了。不要再問有沒有必要學習之類的問題了。vue
關於 ES6 的基礎知識,推薦 阮一峯
老師的 ECMAScript 6 入門,看完你就會以爲,並不難。至於有些後端的朋友跟我聊到說 ES6 徹底不明白,那是由於大家思想還停留在過去 jQuery
的時代,那個時候只須要隨便複製幾段代碼,而後寫幾個 js 函數,就能夠搞定不少後端模板頁面了,可是今非昔比了,因此若是大家想深刻了解前端,作一個全棧工程師,仍是靜下心來,好好閱讀這篇 ES6 教程。代碼這東西,不僅是須要會用,更重要的是須要知其因此然。就像你一個 python 同事看到一段代碼時問我,爲啥 JS 引用一個模塊時是 import Vue form 'vue'
,而不是 from 'vue' import Vue
同樣,這個我是無法解釋的,由於ES6語言的規範就是這樣的啊~java
複製一份上一篇中的項目,在 src
目錄下建立一個 utils.js
文件,內容以下:python
/** * 簡單的深拷貝實現,我的常常這麼使用 * 這裏obj中不能包含特殊類型值:undefined,NaN,function類型值 * @param {object} obj */
export function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
/** * log 函數的二次封裝,這裏只是爲了演示 * @param {any} content */
export function log(content) {
console.log(`[Yuga log]: ${JSON.stringify(content)}`);
}
複製代碼
它就是經過 export
暴露出了兩個工具函數。webpack
修改 app.js
代碼進行引入使用:ios
import './styles/app.scss';
import Vue from 'vue';
import userinfo from './info';
import { deepClone } from './utils';
import * as utils from './utils';
import hello1 from './hello1.vue';
import hello2 from './hello2.vue';
new Vue({
el: "#app",
template: '<div><hello1 v-bind:info="userinfo"/><hello2/></div>',
data () {
return {
userinfo: deepClone(userinfo)
}
},
components: {
hello1,
hello2
},
created () {
// 你會發現這裏也同時改變了源原數據 info ,
// 因此須要用到深拷貝源數據賦值給 data 中的 info
this.userinfo.name = 'yugasun111'
utils.log(userinfo)
}
});
複製代碼
上面分別演示了 5 種模塊引入方法,不管是哪種,其實這個要看該模塊是如何 export
的,對於任何一個 npm 模塊,若是它支持 ES6 方式引入,它通常都會使用 export
或 export default
關鍵字暴露出一個對象(任何一個js數據類型),只不過 export default
指定了默認輸出,這樣用戶就不用閱讀接口文檔,就能夠按照本身須要加載該模塊,並修改成本身喜歡的名稱來使用。而對於有些模塊(如上面的 utils.js
)能夠經過 export
關鍵字來實現多個子模塊的輸出,這樣用戶就能夠根據我的須要來引入對應的子模塊,前提是得知道其內部子模塊名稱才行。 而 import 'normalize.css'
至關於全局引入了,將該模塊的全部內容一併引入。git
更多細節講解,建議閱讀這篇文章: ES6 Module 的語法
這點對於 require
的引入方式,是無法作到的,而著名的 tree-shaking 功能就是依賴 ES6 的這種模塊系統。
Promise
是異步編程的一種解決方案,比傳統的解決方案(回調函數)更合理和更強大。它由社區最先提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了Promise
對象。詳細Promise
介紹能夠閱讀這篇博文:異步編程之 Promise; ES2017 標準又引入了 async 函數,是的異步操做變得更加方便。更詳細的介紹在這裏:async 函數。
有的人說有了 async 函數
就再也不須要 Promise
了,我以爲是不對的,由於不少異步模塊都是先基於 Promise
封裝,而後才能通過 async/await
函數來操做的。固然把二者結合起來用,能夠完成更增強大的異步編程操做,Vuejs 代碼也變得更加靈活、簡介和強大。
這裏既然是 Vuejs 實戰,我就不講它們的基礎用法了,來看看如何用在實際項目中吧~
要想在項目中使用 async/await
函數,就必須有相關 babel
插件來支持,由於 async/await
語法屬於 ES2017 規範的內容,因此須要引入 babel-preset-stage-2
插件來轉化,固然還有 stage-0, stage-1, stage-3
等,這裏參考 vue-cli
經常使用 stage-2
,直接安裝:
npm install babel-preset-stage-2 babel-plugin-transform-runtime --save-dev
複製代碼
而後在 .babelrc
文件中添加配置:
{
"presets": [ "env", "stage-2" ],
"plugins": [
"transform-runtime"
]
}
複製代碼
如今咱們的語言支持,配置好了,如今開始使用。
上面的代碼中,咱們的 userinfo
是咱們經過 info.js
硬編碼,而後在 app.js
中引入,經過 props
傳遞給了 hello1.vue
組件,下面咱們經過請求接口方式來獲取。
先安裝 vue-axios-plugin
插件,來提供網絡請求服務:
npm install vue-axios-plugin --save
複製代碼
而後在 app.js
中導入並使用:
// 引入插件
import VueAxiosPlugin from 'vue-axios-plugin';
// 使用插件
Vue.use(VueAxiosPlugin)
複製代碼
這樣在應用中的組件中都會在 this
上綁定一個 $http
屬性,它由 get
和 post
方法,具體使用文檔:vue-axios-plugin文檔。
而後在 hello1.vue
中建立請求方法 getUserInfo
,並在 created
鉤子函數中調用:
// ...
methods: {
async getUserInfo () {
try {
const res = await this.$http.get('http://yapi.demo.qunar.com/mock/4377/userinfo');
this.info = res.data
} catch (e) {
console.log(e);
}
}
},
// ...
複製代碼
從新運行項目,審覈元素,發現成功發起了 GET
請求,並顯示了接口數據。
注意:其實 Vuejs 的
methods
屬性中全部的方法均可以定義爲async函數
來使用,包括 Vuejs 的生命週期函數,好比created
。
能夠發現使用 async/await
語法比使用 Promise
的鏈式語法簡潔多了,並且閱讀性更強了。
由於本人工做主要是在大數據可視化,常常在繪製某張定製化圖形時,須要同時依賴多個接口(不要問我爲何會有這麼多接口?爲啥後端不一次性傳給我?由於我不想跟他們撕逼,╮(╯▽╰)╭哎
),並且必須在這幾個請求都處理完後,才能開始處理數據,多的時候一張圖行依賴6個接口,固然我能夠在一個 async函數
中寫6行 await
語法的請求,而後逐個處理,可是這樣效率過低了,可是這6個請求是能夠並行執行的。這時就能夠結合 Promise.all 高級方法來處理。這樣我能夠同時發起六個請求,而後統一處理接口返回數據。爲了方便,這裏演示同時請求2個url,多個的是同樣的。咱們再在 hello1.vue
中添加一個 get2UserInfo
方法,而後在 created
中調用下,更新後的 hello1.vue
以下:
<template>
<div>
<h1>{{ msg }}</h1>
<a v-bind:href="info.site">{{ info.name }}</a><br>
<a v-bind:href="user1.site">{{ user1.name }}</a><br>
<a v-bind:href="user2.site">{{ user2.name }}</a><br>
</div>
</template>
<script> export default { name: 'hello1', data () { return { msg: 'Hello Vue.js', info: {}, user1: {}, user2: {} } }, methods: { async getUserInfo () { try { const res = await this.$http.get('http://yapi.demo.qunar.com/mock/4377/userinfo'); this.info = res.data } catch (e) { console.log(e); } }, async get2UserInfo () { try { const res = await Promise.all([ this.$http.get('http://yapi.demo.qunar.com/mock/4377/userinfo1'), this.$http.get('http://yapi.demo.qunar.com/mock/4377/userinfo2'), ]) this.user1 = res[0].data; this.user2 = res[1].data; } catch (e) { console.log(e); } } }, created () { this.getUserInfo(); this.get2UserInfo(); } } </script>
<style lang="scss" scoped> h1 { color: $green; } </style>
複製代碼
再次運行項目,能夠發現頁面在初始化的時候同時發起了3個請求,並正常渲染出了接口數據。經過控制檯能夠看到這三個請求是並行發起的。
注意:這裏的
Promise.all()
的參數是一個函數執行隊列,它們會同時發起,而後都請求成功後,會將隊列的每一個任務的結果組裝成一個結果數據,而後返回。
其實要把講ES6講完,實在是太難了,寫本書都很難講好,我這裏只能說是班門弄斧一下,結合我在 Vue 中的相關實踐,對相關功能作個簡短介紹,但願能起到引導的做用。不太瞭解的朋友,能夠認真閱讀下文首提到的阮一峯老師的文章。接下來後面的文章將所有使用 ES6 的語法編寫代碼。