實戰 | 用原生js寫一個"多動症"的簡歷

作者|謙龍

原文|用原生js寫一個"多動症"的簡歷 - 騰訊Web前端 IMWeb 團隊社區

會動的簡歷實現思路

這張會動的簡歷,就好像一個打字員在不斷地錄入文字,頁面呈現動態效果。又好像一個早已經錄製好影片,而我們只是坐在放映機前觀看。

原理分兩個部分

1、頁面能看見的不斷跳動著的增加的文字,控制

2、頁面的布局效果由藏在"背後的"style標籤完成

想像一下你要往一張網頁每間隔0.1秒增加一個啊字,是不是開個定時器,間斷地往body裡面塞啊,就可以啊!沒錯,做到這一步就完成了原理的第一部分。

再想像一下,在往頁面裡面塞啊的時候,我還想改變啊字的字體顏色以及網頁背景顏色,那應該怎麼做呢,是不是執行下面的代碼就可以呢,沒錯,只不過更改字體和背景色不是突然改變的,而是也是開個定時器,間斷地往style標籤中塞入以下代碼,這樣就完成了原理的第二步,是不是好簡單, 接下來讓我們一步步完成它:

項目搭建

在這個項目中我們

1、使用webpack2來完成項目的構建

2、使用yarn來處理依賴包的管理

3、使用es6的寫法

4、使用部分原生dom操作api

5、standard.js(代碼風格約束利器)

目錄結構如下:

最重要的幾個模塊分別是resumeEditor(簡歷編輯模塊) stylesEditor(簡歷樣式編輯模塊) 以及vQuery(封裝的dom操作模塊) 最後app.js(入口模塊)再將幾個模塊的功能結合起來完成整個項目。

vQuery(封裝的dom操作模塊)

因為後面的幾個模塊都要依賴這個小模塊,所以我們先簡單的看下。

可以看出它做的事就是封裝一個構造函數Vquery,它的實例會有一些簡單的dom操作方法,最後為了能夠像jQuery那樣使用$().funcName的形式去使用,我們導出了一個匿名函數,在匿名函數中去new Vquery

stylesEditor(簡歷樣式編輯模塊)

簡歷所展現的布局效果都是由這個模塊完成的,核心方法是showStyles。

stylesEditor(簡歷樣式編輯模塊)

簡歷編輯模塊用來展示簡歷內容,主要會經歷由markdown格式往html頁面形式的轉換。

app(入口模塊)

最後由app入口模塊將以上幾個模塊整合完成項目的功能,我們找出其中的核心代碼來, ??,你沒看錯,傳說中的回調地獄,亮瞎了我的狗眼啊。想必大家和我一樣都是不願意看到這坨噁心的代碼的,但對於處理非同步問題,回調又的確是一直以來的解決方案之一。

因為定時器的操作是非同步行為,而我們的簡歷生成過程會涉及到多個非同步操作,所以為了看到如首頁預覽鏈接的效果,必須等前一個步驟完成之後,才能執行下一步步驟,這裡首先使用的回調函數的解決方案,大家可以從github上拉取代碼,分別切換以下幾個分支來查看不同的解決方案

1、master(使用回調函數處理)

2、promise(使用promise處理)

3、generator-thunk(使用generator + thunk函數處理)

4、generator-promise(使用generator + promise處理)

5、async(使用async處理)

解決回調地獄之promise

回調方式能夠解決非同步操作問題,但是代碼寫起來非常的不美觀,可讀性差,代碼呈橫向發展趨勢...偉大的程序員們開疆擴土發明了promise的解決方案。我們來看一下promise分支中app模塊最終的寫法

可以看到,代碼清爽了很多,縱向發展,應用第一步第二步第三步...一眼就能夠看出來,當然實現的邏輯是將原來的相關的模塊用Promise包裝起來,並且在原來回調函數執行的地方resolve即可,詳細實現,歡迎查看項目源碼

解決回調地獄之generator-thunk,generator-promise

兩種方式比較類似,都要用到es6中的generator。關於什麼是generator,thunk函數,可以查看軟大神關於ECMAScript 6 入門,這裡簡要地講述一下,其如何處理非同步操作問題使得可以將非同步行為寫起來如同步般爽。

上面的代碼在過了200毫秒會log出2222,過了1秒鐘之後log出1111。

這,要??了,你不是說generator寫起來同步可以解決非同步問題嗎,為毛這裡timeOut2沒有在timeOut1之後執行呢,畢竟gen函數中看起來是希望這樣的嘛。

其實不然,timeOut2啥時候執行取決於:

試想兩個函數幾乎同時執行,那在定時器中當然是200毫秒後的timeOut2先列印出2222來,但是有沒有辦法,讓timeOut2在timeOut1後執行呢?答案是有的

可以看到我們在timeOut1執行完成之後,再將指針指向下一個位置,即timeOut2再去執行,這樣的結果就和gen函數中兩個yield的寫起來同步感覺一樣了。但是含有一個問題,如果涉及到很多個非同步操作,我們是很難通過上面的方式將非同步流程管理起來的。於是我們需要做下面一件事:

內部的next函數就是 thunk 的回調函數。next函數先將指針移到 generator 函數的下一步(gen.next方法),然後判斷 generator 函數是否結束(result.done屬性),如果沒結束,就將next函數再傳入 thunk 函數(result.value屬性),否則就直接退出。

最後我們在看一下通過co函數的寫法完成上面的例子

解決回調地獄之async

async其實就是generator函數的語法糖。大家如果把generator弄明白了,使用它一定不再話下,關於這個項目的用法,歡迎查看async分支源代碼,這裡不再贅述。

尾述

本文中可能存在闡述不當的地方,歡迎大家指正。最後點個贊,點個star好不好呀。

源碼地址:qianlongo/resume-native

推薦閱讀:

前端周刊第42期
2017 年 9 月:15 個有趣的 JS 和 CSS 庫
基於Express的Node項目實踐

TAG:前端开发 | 前端工程师 | 前端框架 |