你也许不知道的Vuejs - 使用ES6快乐的玩耍
by yugasun from yugasun.com/post/you-ma… 本文可全文轉(zhuǎn)載,但需要保留原作者和出處。
上一篇中我們已經(jīng)學(xué)會(huì)使用 babel 將 ES6 轉(zhuǎn)化為 ES5 了,并且展示了一些 ES6 代碼,這一篇將重點(diǎn)聊聊 ES6 在 Vuejs 項(xiàng)目中一些部分應(yīng)用。
什么是ES6
摘自 ECMAScript 6 簡(jiǎn)介:
大家習(xí)慣將 ECMAScript 6.0 簡(jiǎn)稱為 ES6,它是 Javascript 語(yǔ)言的下一代標(biāo)準(zhǔn),它的目標(biāo),是使得 Javascript 語(yǔ)言可以用來(lái)編寫復(fù)雜的大型應(yīng)用程序,成為企業(yè)級(jí)開發(fā)語(yǔ)言。
說(shuō)是下一代,其實(shí)早在 2015 年 6月就正式發(fā)布了(所以又稱 ES2015),截止今日已經(jīng)快3年了,很快 ES7/ES8 都要出來(lái)了,所以作為前端開發(fā)者,學(xué)習(xí) ES6 已經(jīng)是個(gè)必然命題了。不要再問(wèn)有沒(méi)有必要學(xué)習(xí)之類的問(wèn)題了。
關(guān)于 ES6 的基礎(chǔ)知識(shí),推薦 阮一峰 老師的 ECMAScript 6 入門,看完你就會(huì)覺得,并不難。至于有些后端的朋友跟我聊到說(shuō) ES6 完全不明白,那是因?yàn)槟銈兯枷脒€停留在過(guò)去 jQuery 的時(shí)代,那個(gè)時(shí)候只需要隨便復(fù)制幾段代碼,然后寫幾個(gè) js 函數(shù),就可以搞定很多后端模板頁(yè)面了,但是今非昔比了,所以如果你們想深入了解前端,做一個(gè)全棧工程師,還是靜下心來(lái),好好閱讀這篇 ES6 教程。代碼這東西,不只是需要會(huì)用,更重要的是需要知其所以然。就像你一個(gè) python 同事看到一段代碼時(shí)問(wèn)我,為啥 JS 引用一個(gè)模塊時(shí)是 import Vue form 'vue',而不是 from 'vue' import Vue 一樣,這個(gè)我是沒(méi)法解釋的,因?yàn)镋S6語(yǔ)言的規(guī)范就是這樣的啊~
模塊的定義和引入
復(fù)制一份上一篇中的項(xiàng)目,在 src 目錄下創(chuàng)建一個(gè) utils.js 文件,內(nèi)容如下:
/*** 簡(jiǎn)單的深拷貝實(shí)現(xiàn),個(gè)人經(jīng)常這么使用* 這里obj中不能包含特殊類型值:undefined,NaN,function類型值* @param {object} obj*/ export function deepClone(obj) {return JSON.parse(JSON.stringify(obj)); }/*** log 函數(shù)的二次封裝,這里只是為了演示* @param {any} content*/ export function log(content) {console.log(`[Yuga log]: ${JSON.stringify(content)}`); } 復(fù)制代碼它就是通過(guò) export 暴露出了兩個(gè)工具函數(shù)。
修改 app.js 代碼進(jìn)行引入使用:
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 () {// 你會(huì)發(fā)現(xiàn)這里也同時(shí)改變了源原數(shù)據(jù) info ,// 所以需要用到深拷貝源數(shù)據(jù)賦值給 data 中的 infothis.userinfo.name = 'yugasun111'utils.log(userinfo)} }); 復(fù)制代碼上面分別演示了 5 種模塊引入方法,無(wú)論是哪一種,其實(shí)這個(gè)要看該模塊是如何 export 的,對(duì)于任何一個(gè) npm 模塊,如果它支持 ES6 方式引入,它一般都會(huì)使用 export 或 export default 關(guān)鍵字暴露出一個(gè)對(duì)象(任何一個(gè)js數(shù)據(jù)類型),只不過(guò) export default 指定了默認(rèn)輸出,這樣用戶就不用閱讀接口文檔,就可以按照自己需要加載該模塊,并修改為自己喜歡的名稱來(lái)使用。而對(duì)于有些模塊(如上面的 utils.js)可以通過(guò) export 關(guān)鍵字來(lái)實(shí)現(xiàn)多個(gè)子模塊的輸出,這樣用戶就可以根據(jù)個(gè)人需要來(lái)引入對(duì)應(yīng)的子模塊,前提是得知道其內(nèi)部子模塊名稱才行。 而 import 'normalize.css' 相當(dāng)于全局引入了,將該模塊的所有內(nèi)容一并引入。
更多細(xì)節(jié)講解,建議閱讀這篇文章: ES6 Module 的語(yǔ)法
這點(diǎn)對(duì)于 require 的引入方式,是沒(méi)法做到的,而著名的 tree-shaking 功能就是依賴 ES6 的這種模塊系統(tǒng)。
異步編程
Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案(回調(diào)函數(shù))更合理和更強(qiáng)大。它由社區(qū)最早提出和實(shí)現(xiàn),ES6 將其寫進(jìn)了語(yǔ)言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了 Promise 對(duì)象。詳細(xì) Promise 介紹可以閱讀這篇博文:異步編程之 Promise; ES2017 標(biāo)準(zhǔn)又引入了 async 函數(shù),是的異步操作變得更加方便。更詳細(xì)的介紹在這里:async 函數(shù)。
有的人說(shuō)有了 async 函數(shù) 就不再需要 Promise 了,我覺得是不對(duì)的,因?yàn)楹芏喈惒侥K都是先基于 Promise 封裝,然后才能經(jīng)過(guò) async/await 函數(shù)來(lái)操作的。當(dāng)然把兩者結(jié)合起來(lái)用,可以完成更加強(qiáng)大的異步編程操作,Vuejs 代碼也變得更加靈活、簡(jiǎn)介和強(qiáng)大。
這里既然是 Vuejs 實(shí)戰(zhàn),我就不講它們的基礎(chǔ)用法了,來(lái)看看如何用在實(shí)際項(xiàng)目中吧~
要想在項(xiàng)目中使用 async/await 函數(shù),就必須有相關(guān) babel 插件來(lái)支持,因?yàn)?async/await 語(yǔ)法屬于 ES2017 規(guī)范的內(nèi)容,所以需要引入 babel-preset-stage-2 插件來(lái)轉(zhuǎn)化,當(dāng)然還有 stage-0, stage-1, stage-3 等,這里參考 vue-cli 常用 stage-2,直接安裝:
npm install babel-preset-stage-2 babel-plugin-transform-runtime --save-dev 復(fù)制代碼然后在 .babelrc 文件中添加配置:
{"presets": [ "env", "stage-2" ],"plugins": ["transform-runtime"] } 復(fù)制代碼現(xiàn)在我們的語(yǔ)言支持,配置好了,現(xiàn)在開始使用。
上面的代碼中,我們的 userinfo 是我們通過(guò) info.js 硬編碼,然后在 app.js 中引入,通過(guò) props 傳遞給了 hello1.vue 組件,下面我們通過(guò)請(qǐng)求接口方式來(lái)獲取。
先安裝 vue-axios-plugin 插件,來(lái)提供網(wǎng)絡(luò)請(qǐng)求服務(wù):
npm install vue-axios-plugin --save 復(fù)制代碼然后在 app.js 中導(dǎo)入并使用:
// 引入插件 import VueAxiosPlugin from 'vue-axios-plugin'; // 使用插件 Vue.use(VueAxiosPlugin) 復(fù)制代碼這樣在應(yīng)用中的組件中都會(huì)在 this 上綁定一個(gè) $http 屬性,它由 get 和 post 方法,具體使用文檔:vue-axios-plugin文檔。
然后在 hello1.vue 中創(chuàng)建請(qǐng)求方法 getUserInfo,并在 created 鉤子函數(shù)中調(diào)用:
// ... 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);}} }, // ... 復(fù)制代碼重新運(yùn)行項(xiàng)目,審核元素,發(fā)現(xiàn)成功發(fā)起了 GET 請(qǐng)求,并顯示了接口數(shù)據(jù)。
注意:其實(shí) Vuejs 的 methods 屬性中所有的方法都可以定義為 async函數(shù) 來(lái)使用,包括 Vuejs 的生命周期函數(shù),比如 created。
可以發(fā)現(xiàn)使用 async/await 語(yǔ)法比使用 Promise 的鏈?zhǔn)秸Z(yǔ)法簡(jiǎn)潔多了,而且閱讀性更強(qiáng)了。
高級(jí)異步編程
因?yàn)楸救斯ぷ髦饕窃诖髷?shù)據(jù)可視化,經(jīng)常在繪制某張定制化圖形時(shí),需要同時(shí)依賴多個(gè)接口(不要問(wèn)我為什么會(huì)有這么多接口?為啥后端不一次性傳給我?因?yàn)槲也幌敫麄兯罕?#xff0c;╮(╯▽╰)╭哎),而且必須在這幾個(gè)請(qǐng)求都處理完后,才能開始處理數(shù)據(jù),多的時(shí)候一張圖行依賴6個(gè)接口,當(dāng)然我可以在一個(gè) async函數(shù) 中寫6行 await 語(yǔ)法的請(qǐng)求,然后逐個(gè)處理,但是這樣效率太低了,但是這6個(gè)請(qǐng)求是可以并行執(zhí)行的。這時(shí)就可以結(jié)合 Promise.all 高級(jí)方法來(lái)處理。這樣我可以同時(shí)發(fā)起六個(gè)請(qǐng)求,然后統(tǒng)一處理接口返回?cái)?shù)據(jù)。為了方便,這里演示同時(shí)請(qǐng)求2個(gè)url,多個(gè)的是一樣的。我們?cè)僭?hello1.vue 中添加一個(gè) get2UserInfo 方法,然后在 created 中調(diào)用下,更新后的 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> 復(fù)制代碼再次運(yùn)行項(xiàng)目,可以發(fā)現(xiàn)頁(yè)面在初始化的時(shí)候同時(shí)發(fā)起了3個(gè)請(qǐng)求,并正常渲染出了接口數(shù)據(jù)。通過(guò)控制臺(tái)可以看到這三個(gè)請(qǐng)求是并行發(fā)起的。
注意:這里的 Promise.all() 的參數(shù)是一個(gè)函數(shù)執(zhí)行隊(duì)列,它們會(huì)同時(shí)發(fā)起,然后都請(qǐng)求成功后,會(huì)將隊(duì)列的每個(gè)任務(wù)的結(jié)果組裝成一個(gè)結(jié)果數(shù)據(jù),然后返回。
總結(jié)
其實(shí)要把講ES6講完,實(shí)在是太難了,寫本書都很難講好,我這里只能說(shuō)是班門弄斧一下,結(jié)合我在 Vue 中的相關(guān)實(shí)踐,對(duì)相關(guān)功能做個(gè)簡(jiǎn)短介紹,希望能起到引導(dǎo)的作用。不太了解的朋友,可以認(rèn)真閱讀下文首提到的阮一峰老師的文章。接下來(lái)后面的文章將全部使用 ES6 的語(yǔ)法編寫代碼。
源碼在此
專題目錄
You-May-Not-Know-Vuejs
總結(jié)
以上是生活随笔為你收集整理的你也许不知道的Vuejs - 使用ES6快乐的玩耍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: PowerPC中断系统简介(一)
- 下一篇: 【vue】使用vue+element搭建