摘要:模塊化以項目中普遍會有的文件為例,實現導出再在其他文件中通過實現導入導入模塊使用統一的模塊化規范,可以提高代碼的可讀性,更易于維護。類操作先實戰創建一個類在中創建實例中的類能讓我們可以用更簡明的語法實現繼承,也使代碼的可讀性變得更高。
上一篇通過TodoList的練習,目的是為了讓大家理解ES6中各種新特性的實際用途。
最好的學習方法就是實踐,所以這節課結合實際項目,來更好的理解和掌握ES6的用途和使用場景,達到靈活運用的目的。
1、模塊化
以項目中普遍會有的config.js文件為例,實現export導出:
const githubURL = "OUR GITHUB URL HERE"; const staticServer = "http://xxx.com"; const testsPath = `zaz-${type}-${name}/tests/index.htm?zaz[env]=tests`; const name = "stalker"; const type = "mod"; const version = "0.0.1"; const state = "ok"; const description = "JavaScript API to deal with user data"; let globalpkg = null; const config = { _static: { name, version, state, description, docs: `${githubURL}/pages/terra/zaz-${type}-${name}`, source: `${githubURL}/Terra/zaz-${type}-${name}`, tests: `${staticServer}/fe/${testsPath}`, dependencies: ["mod.wilson"] } }; export default config;
再在其他文件中通過import實現導入:
import config from "./config";//導入ES6模塊 import { globalpkg } from "./config"; import factory from "./factory"; zaz.use((pkg) => { "use strict"; config.dynamic.globalpkg = pkg; pkg.require(["modFactory"], (modFactory) => { modFactory.create(pkg.utils.deepMerge(config._static, factory)); }); });
使用ES6統一的模塊化規范,可以提高代碼的可讀性,更易于維護。
2、數組操作
import React,{Component} from "react"; class RepeatArray extends Component{ constructor() { super(); } render(){ const names = ["Alice", "Emily", "Kate"]; return ({ let p=document.querySelectorAll("p"); let pArr=Array.from(p); pArr.forEach(function(item){ console.log(item.textContent); }); Array.from(pArr,function(item){return item + "ES6"}); }); } }
使用Array.from 同時對每個元素進行操作。
3、模板字符串
常見的使用場景便是寫組件模板時使用:
$("#result").append(` There are ${basket.count} items in your basket, ${basket.onSale} are on sale! `);
可以在模板字符串中任意的嵌入變量, 調用函數等。
4、解構與擴展操作符
擴展操作符在父組件給子組件傳遞一批屬性的情境中更為方便。
下面的例子把className以外的所有屬性傳遞給div標簽
class AutoloadingPostsGrid extends React.Component { render() { var { className, ...others, // contains all properties of this.props except for className } = this.props; return (); } }
使用react開發最常見的問題就是父組件要傳給子組件的屬性較多時比較麻煩
class MyComponent extends React.Component{ //假設MyComponent已經有了name和age屬性 render(){ return () } }
使用擴展操作符可以變得很簡單
class MyComponent extends React.Component{ //假設MyComponent已經有了name和age屬性 render(){ return () } }
上述方式是將父組件的所有屬性都傳遞下去,如果這其中有些屬性不需要傳遞呢?也很簡單
class MyComponent extends React.Component{ //假設MyComponent有很多屬性,而name屬性不需要傳遞給子組件 var {name,...MyProps}=this.props; render(){ return () } }
上述方法最常用的場景就是父組件的class屬性需要被多帶帶提取出來作為某個元素的class,而其他屬性需要傳遞給子組件。
在構建通用容器時,擴展屬性會非常有用。
function App1() { return; } function App2() { const props = {firstName: "Ben", lastName: "Hector"}; return ; }
5、Promise
場景一 : 所有圖片加載完再顯示在頁面上,避免頁面閃動。
function loadImg(src) { return new Promise((resolve, reject) => { let img = document.createElement("img"); img.src = src; img.onload = function () { resolve(img) } img.onerror = function (err) { reject(err) } }) } function showImgs(imgs) { imgs.forEach(function(img){ document.body.appendChild(img); }) } Promise.all([ loadImg("https://example.com/pic1") loadImg("https://example.com/pic2") loadImg("https://example.com/pic3") ]).then(showImgs)
場景二: 多個資源中只要加載了其中一種就可。
{ function loadImg(src) { return new Promise((resolve, reject) => { let img = document.createElement("img"); img.src = src; img.onload = function () { resolve(img) } img.onerror = function (err) { reject(err) } }) } function showImgs(img) { document.body.appendChild(img); } Promise.race([ loadImg("https://example.com/pic1") loadImg("https://example.com/pic2") loadImg("https://example.com/pic3") ]).then(showImgs) }
6、Generator
在異步編程的解決方案中,Generator比Promise更高級些。
使用場景:抽獎次數邏輯控制、長輪詢(服務器請求報錯再次請求, 定時發送請求)
// 以前控制次數是在全局中申明,既不安全又影響性能 let draw = function (count) { // 具體抽獎邏輯 console.info(`剩余${count}次`) } let residue = function* (count) { while (count > 0) { count-- yield draw(count) } } let start = residue(5) let btn = document.createElement("button") btn.id="start" btn.textContent = "抽獎" document.body.appendChild(btn); document.getElementById("start").addEventListener("click", function() { start.next() }, false) } { // 長輪詢 let ajax = function* () { yield new Promise(function(resolve, reject) { setTimeout(() => { resolve({code: 0}) }, 200); }) } let pull = function () { let generator = ajax() let step = generator.next() step.value.then(function(d){ if (d.code !=0 ) { setTimeout(() => { console.info("wait") pull() }, 100); } else { console.info(d) } }) } pull()
通過下面這張流程圖,再加深下對Generator的理解。
7、await
在項目中,有時會出現需要同時依賴多個接口,而且必須在這幾個請求都處理完后,才能開始處理數據的情況。我們可以在一個 async函數 中寫多個await 語法的請求,然后逐個處理,但是這樣效率太低了。
多個請求是可以并行執行的。這時就可以結合 Promise.all 高級方法來處理,可以同時發起多個請求,然后統一處理接口返回數據。
為了方便,這里演示同時請求2個url,多個的也是一樣的, 如下:
export default { name: "hello1", data () { return { msg: "Hello Vue.js", info: {}, user1: {}, user2: {} } }, methods: { async getUserInfo () { try { const res = await this.$http.get("http://aaa.com/userinfo"); this.info = res.data } catch (e) { console.log(e); } }, async get2UserInfo () { try { const res = await Promise.all([ this.$http.get("http://aaa.com/userinfo1"), this.$http.get("http://aaa.com/userinfo2"), ]) this.user1 = res[0].data; this.user2 = res[1].data; } catch (e) { console.log(e); } } }, created () { this.getUserInfo(); this.get2UserInfo(); } }
再次運行項目,可以發現頁面在初始化的時候同時發起了3個請求,并正常渲染出了接口數據。
注意:這里的 Promise.all() 的參數是一個函數執行隊列,它們會同時發起,然后都請求成功后,會將隊列的每個任務的結果組裝成一個結果數據,然后返回。
8、類操作
先實戰創建一個List類
import Utils from "./Utils.js"; class List { constructor(title = "", items = [], isEditable = true, id = "") { this.id = (id) ? id : Utils.guid(); this.title = title; this.items = items; this.isEditable = isEditable; } render() { var html = ``; return html; } getItemById(id) { let item = this.items.filter(i => i.id === id); return ((item.length) ? item[0] : null); } add(item) { this.items.push(item); } remove(item) { this.items = this.items.filter(i => (i.id !== item.id)); } } export default List;${this.title}
${(this.isEditable) ? "X" : ""}`; this.items.forEach(function(item) { html += item.render(); }); html += `
${(this.isEditable) ? "Add Item" : ""}
在app.js中創建List實例:
import List from "./List.js"; import Utils from "./Utils.js"; import Status from "./Status.js"; class App { constructor(lists = []) { this.lists = lists; } getDueItems() { let dueItems = []; this.lists.forEach(function(list) { list.items.forEach(function(item) { if (item.date && item.status === Status.PENDING && Utils.dateDiffInDays(new Date(item.date), new Date()) > 0) { dueItems.push(item); } }); }); return dueItems; } getItemById(id) { const filterById = (function filterById(id1) { return function(listItem) { return listItem.id === id1; }; }(id)); for (let i = 0; i < this.lists.length; i++) { let item = this.lists[i].items.filter(filterById); if (item.length) { return item[0]; } } return null; } getListById(id) { let list = this.lists.filter(l => l.id === id); return ((list.length) ? list[0] : null); } render() { let pastDueList = new List("Past Due Date", this.getDueItems(), false); let html = `"; return html; } add(list) { this.lists.push(list); } remove(list) { this.lists = this.lists.filter(l => (l.id !== list.id)); } } export default App;[+] Add List`; this.lists.forEach(function(list) { html += list.render(); }); html += pastDueList.render(); html += "
ES6中的類能讓我們可以用更簡明的語法實現繼承,也使代碼的可讀性變得更高。
9、Proxy
Proxy可以讓我們根據不同的業務邏輯進行相應的處理, 對原對象進行映射,生成新的對象,操作新對象的同時通過一定的規則修改原對象。
// 先定義一個函數 function validator(target,validator) { return new Proxy(target, { _validator: validator, set(targer,key,value,proxy){ if (targer.hasOwnProperty(key)) { let va = this._validator[key]; if (!!va(value)) { return Reflect.set(target,key,value,proxy) }else { throw Error(`不能設置${key}到${value}`) } }else { throw Error(`${key} 不存在`) } } }) } const personValidator={ name(val){ return typeof val === "string" }, age(val){ return typeof val === "number" && val >18 } } class Person{ constructor(name,age) { this.name = name this.age = age return validator(this, personValidator) } } const person = new Person("lilei", 30) console.info(person) // Proxy {name: "lilei", age: 30} // person.name = 48 // Uncaught Error: 不能設置name到48 // console.info(person) person.name = "han mei mei" console.info(person) // Proxy {name: "han mei mei", age: 30}
點評:使用Proxy進行數據校驗,將對象和驗證分離開,便于后期代碼的維護。
總結本篇主要通過實際項目中的例子回顧ES6的知識點,幫大家梳理重點和難點。學會ES6語法不難,活學活用到項目才是關鍵。
希望各位小伙伴能充分認識到ES6的強大,通過在實際工作中不斷地使用ES6,提升代碼質量和工作效率,這樣就能多一點喝茶看電影的時間。
最后祝大家都能成為別人眼中的程序猿大牛,O(∩_∩)O哈哈~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104546.html
摘要:云集一線大廠有真正實力的程序員團隊云集一線大廠經驗豐厚的碼農,開源奉獻各教程。融合多種常見的需求場景網絡請求解析模板引擎靜態資源日志記錄錯誤請求處理。結合語句中轉中間件控制權,解決回調地獄問題。注意分支中的目錄為當節課程后的完整代碼。 ?? ?與眾不同的學習方式,為你打開新的編程視角 獨特的『同步學習』方式 文案講解+視頻演示,文字可激發深層的思考、視頻可還原實戰操作過程。 云...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。異步編程入門的全稱是前端經典面試題從輸入到頁面加載發生了什么這是一篇開發的科普類文章,涉及到優化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結思考,循序漸進的理解 TypeScript。 網絡基礎知識之 HTTP 協議 詳細介紹 HTT...
閱讀 3346·2021-11-25 09:43
閱讀 3134·2021-10-11 10:58
閱讀 2735·2021-09-27 13:59
閱讀 3074·2021-09-24 09:55
閱讀 2166·2019-08-30 15:52
閱讀 1826·2019-08-30 14:03
閱讀 2256·2019-08-30 11:11
閱讀 2020·2019-08-28 18:12