“消失”的這倆個月里,我的前端項目如何從零開始

“消失”的這倆個月里,雖然我的技術(shù)博客沒有更新,卻也發(fā)生了很多事情值得自己凝聚。

先是拜讀了趙皓陽的新書《生而貧窮》,書中用大量的客觀數(shù)據(jù)描繪了一個驅(qū)離的世界——貧者越貧與階級固化。其中讓我感悟到,當(dāng)我們大學(xué)生覺得自己被高成就人才“碾壓”而感嘆自己的命運之時,還有很多根本走不到高考這一步的孩子們填充著金字塔的底層;國內(nèi)互聯(lián)網(wǎng)巨頭公司即使形成了壟斷資本鏈,不斷貪婪地吞噬著新興的中小型軟件公司,人民日報一批判,騰訊市值也得蒸發(fā)個千百億。

再是經(jīng)歷了自己喜歡的自媒體公號被整肅的痛心過程,其中包括對“毒舌電影”的封殺和對趙皓陽的公號的一個月禁言。難怪以特立獨行為特點的自由主義者李敖先生,在 05 年來大陸進(jìn)行神州文化之旅時曾表示愿意拋棄自己的自由主義,來換我國憲法中白紙黑字的“言論自由”,現(xiàn)在看來,這條路還挺久。

話說回重點,當(dāng)然要凝聚一下這倆個月我對前端項目的實踐心得,也是本文的主旨——曾經(jīng)大談方法論的我,在實踐過程中如何快速填坑,又如何感悟到以后要避免像這次一樣在編程上的大量“搬磚”?

“消失”的這倆個月里,我的前端項目如何從零開始。

項目背景及功能拆解

一切之前,先看一下提交作品階段由我原聲解說的真實系統(tǒng)演示與功能詳解的視頻,如下。

[圖片上傳失敗...(image-39199-1509644428516)]](http://upload-images.jianshu.io/upload_images/2558748-b5c8c5142d99e406.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

可見這場中國軟件杯競賽我們選的競賽題目是基于微信公眾號開發(fā)的借閱伴侶,其中的核心需求如下:

  • 用戶可以進(jìn)入借閱書城搜書、借書,包括掃碼搜書
  • 用戶可以收藏、預(yù)訂書籍并及時得到公眾號的主推提醒
  • 用戶可以修改信息或查看自己的搜書、藏書、預(yù)訂書籍的記錄
  • 管理員需要授權(quán)用戶借閱此書和驗收用戶歸還書籍并確認(rèn)無損
  • 管理員需要錄入相關(guān)書籍信息,管理管理員用戶

原型制作

有了上示所列的功能,根據(jù)微信公眾號服務(wù)的是手機用戶的特點,不難設(shè)計出一個通用的手機端風(fēng)格的原型。原型底下的導(dǎo)航欄中的四個功能,便是整個應(yīng)用的核心:圖書導(dǎo)航、書庫搜書、借閱書車和個人中心。這里使用“墨刀”原型設(shè)計工具,原型設(shè)計工具能仿真交互上的一些操作,最終還能將結(jié)果導(dǎo)出成 HTML 放置到服務(wù)器上,方便給他人發(fā)送鏈接進(jìn)行功能交流。

架構(gòu)項目

能在一個競賽中展現(xiàn)自己的特點想必一定是好事,剛開始構(gòu)想項目所需要用到的技術(shù)棧的時候,一股腦把我知道的(都沒實戰(zhàn)過的)所有技術(shù)點都諾列了出來,每個技術(shù)點各有分工,一時美哉,如下。

  • Bower 做 JavaScript 的包依賴管理
  • JQuery 封裝 DOM 操作并進(jìn)行跨域請求
  • NPM 做 Node.js 的包依賴管理(沒用上)
  • ESLint 做代碼風(fēng)格規(guī)范檢測(未實現(xiàn))
  • Grunt 啟動 Karma 統(tǒng)一項目管理(未實現(xiàn))
  • Istanbul 檢查單元測試代碼覆蓋率(有問題)
  • Jasmine 做單元測試(有問題)
  • JSDoc 規(guī)范代碼注釋風(fēng)格(未實現(xiàn))
  • Karma 自動化完成單元測試(有問題)
  • Webpack 最終打包整個項目文件(未實現(xiàn))
  • Yeoman 最后封裝成一個項目原型模板(未實現(xiàn))

除了前倆個技術(shù)點使用起來真的很簡單外,別的技術(shù)點在嘗試的過程中都遇到阻礙,用 Karma 自動化完成 Jasmine 單元測試并依靠 Istanbul 將測試覆蓋率輸出成 HTML 這個本來是實現(xiàn)成功了的,但引入 JQuery 后,Jasmine 默認(rèn)不識別 JQuery 的 $ 符號及其各種函數(shù),這幾個技術(shù)點便在最后暫時被拋棄。

其實,Karma、Jasmine、Istanbul 被拋棄的主要原因是自己還不習(xí)慣,或者說不會,先寫測試再寫程序,也就是測試驅(qū)動開發(fā)。雖然測試驅(qū)動開發(fā)在去年暑假的特訓(xùn)營里學(xué)過,但久久的未深入和這次項目功能的復(fù)雜性自己一時無法預(yù)測完畢,才導(dǎo)致自己剛開始就先寫了注冊時的輸入框驗證的測試代碼,后期的所有功能代碼都是想到就直接跳過測試來寫實際代碼,后期引入 JQuery 時遇到 Jasmine 默認(rèn)不支持 JQuery 才發(fā)覺測試代碼的坑已經(jīng)很難及時彌補回來了,期末和競賽就快要截止這兩件事更重要。

最后的項目目錄是這樣的,鑒于本次項目開發(fā)過程構(gòu)建在 Git 上,開源許可證書、說明文檔、Git 忽略文件都必不可少;Bower 管理器需要 bower.json 配置文件并會據(jù)此生成 bower_components 依賴庫、Node 包管理器需要 package.json 配置文件并回?fù)?jù)此生成 node_modules 模塊。prototype 放原型設(shè)計工具導(dǎo)出的有交互功能的 HTML 頁面,項目最后合并后端代碼時導(dǎo)入 java_api 和 php_wechat 庫,就是最終的整個目錄結(jié)構(gòu)了。

├── LICENSE # 開源許可證書
├── README.md # 項目說明文檔
├── app # 移動端前端項目正式源碼
│   ├── admin # 移動端管理 APP 源代碼
│   └── user # 移動端用戶借閱官網(wǎng)源代碼
├── bower.json # Bower 前端庫依賴關(guān)系
├── bower_components # Bower 前端依賴庫(.gi)
│   └── 相關(guān)配置詳見 [bower.json](./bower.json)
├── images # 公用圖片庫
├── java_api # 服務(wù)端搜索引擎接口源碼
├── karma.conf.js # Karma 自動化完成單元測試配置
├── node_modules # Node 安裝模塊(.gi)
│   └── 相關(guān)配置詳見 [package.json](./package.json)
├── package.json # Node 配置
├── pc # 電腦端前端項目正式源代碼
│   └── admin # 桌面端管理系統(tǒng)源代碼
├── prototype # 原型圖 HTML 版
├── unit-test # 前端單元測試
├── php_wechat # 微信端源代碼
└── .gitignore # Git 版本管理忽略信息說明文件

根據(jù)項目要求,我們需要開發(fā)管理員手機端、管理員電腦端和用戶手機端——統(tǒng)一起來就是手機端和電腦端,手機端包括用戶模塊和管理員模塊,不難架構(gòu)出 app 、app/admin、app/user 和 pc/admin 的文件目錄,其中這三個目錄里的子目錄都是這樣的:

├── *.html # 低耦合的 HTML 頁面
├── css # CSS 源代碼
├── images # 背景圖、LOGO 等
└── js # JS 源代碼

因為沒用上測試和 Webpack 等技術(shù),也就沒有了其相應(yīng)目錄。

UI 開發(fā)

剛剛提到了制作出的原型能導(dǎo)出 HTML,那我們豈不美哉?把原型設(shè)計工具當(dāng)成像 DreamWeaver 一樣的可視化前端開發(fā)工具真的可以嗎?我們來看看導(dǎo)出的源碼。

源碼里能看到項目被 webpack 打包,況且很多 CSS 也可能是用 SASS 等預(yù)處理器編譯后的結(jié)果,并不是真正易懂的源碼,前端開發(fā)人員依然需要運用 UI 技術(shù)從原生程序搭建自己的項目。

HTML 實現(xiàn)

在 app/user、app/admin、pc/admin 中的結(jié)構(gòu)剛剛已經(jīng)介紹,HTML 就分別地放在這些目錄下。目錄結(jié)構(gòu)中提到的低耦合,要求我們將 CSS 寫到 CSS 文件,將 JS 寫到 JS 文件中,最后再分別合并 CSS 文件和 JS 文件到自己的文件夾中即可。方便起見,剛剛說到的三個項目目錄結(jié)構(gòu)再次放到這里。

├── *.html # 低耦合的 HTML 頁面
├── css # CSS 源代碼
├── images # 背景圖、LOGO 等
└── js # JS 源代碼

在我這次的 HTML 實現(xiàn)過程中,主要就在寫 DIV 標(biāo)簽及其用到的 Class 屬性名、偶爾修改一下外鏈。在剛用戶進(jìn)入的圖書導(dǎo)航的首頁上,我們可以在不寫 CSS 的情況下構(gòu)建出下列 DIV 層次結(jié)構(gòu)。其中我寫的這個可能并不是最優(yōu)方案,甚至稱不上好,但它達(dá)到了能用的效果,并讓我及時的提交競賽作品,后期改進(jìn)即可。

  • 圖書導(dǎo)航頁原型圖:
  • 圖書導(dǎo)航頁 DIV 層次結(jié)構(gòu)

其中注釋里說的“這里將被 ajax”加載、“這是書名等”可以在后期才開發(fā) JS 代碼需要填充頁面時再加上,前期寫一個死的文字模板反而方便在開發(fā) CSS
代碼時及時布局效果。

CSS 實現(xiàn)

實現(xiàn) CSS 代碼時,這里使用了一個看起來不那么方便的選擇器方式 —— 從和當(dāng)前 DIV (也可以看做“組件”)直接相關(guān)的根 DIV 開始向下寫,CSS 的優(yōu)先級并不需要這樣寫,但這樣寫好處之一是能快速看出層級關(guān)系,修改相應(yīng)代碼。這是我從“海投網(wǎng)”中借鑒的,以后學(xué) SASS 或重構(gòu) UI 時可以考慮嘗試另一種風(fēng)格,漸漸找到較為合適自己的那一個。

/* 輪播圖 */

.mSlideShowWrap {
    margin: 0;
    padding: .2rem 0 0 0;
    height: 8.6rem;
    width: 100%;
    display: block;
}

.mSlideShowWrap .mNewBooksSideBar {
    height: 8.6rem;
    width: 1.4rem;
    border: #bbb solid medium;
    display: block;
    float: left;
    background-color: #fff;
}

.mSlideShowWrap .mNewBooksSideBar .mSideBarTitle {
    margin: 0;
    padding: 0 0 .2rem .1rem;
    height: 2.15rem;
    width: auto;
    display: block;
    color: #000;
}

由于之前淺嘗輒止 CSS,在其實現(xiàn)過程反而不會使用 position、float 等功能,布局方面多用 CSS3 的 flex 實現(xiàn),快速學(xué)習(xí) flex 之后的大部分寫 CSS 的時間,都在搬 flex 的磚,這就是我搬磚的由來,卻因之后的 JavaScript 編程實戰(zhàn)而“高潮”。

邏輯與接口實現(xiàn)(JavaScript 編程)

大前端時代到來,簡單的前端界面設(shè)計人員早已飽和,前端技術(shù)也迎來了新的高度,很多時候我們是將前端開發(fā)者和 JavaScript 程序員掛鉤起來的,然而事實上并不是這樣。前端工程師起初多叫重構(gòu)工程師,從《Web 全棧工程的自我修養(yǎng)》作者余果的求職經(jīng)歷可以看到,最開始前端就是偏向設(shè)計和交互的,就是用來一絲不差的實現(xiàn)高保真原型圖,現(xiàn)在用戶體驗的要求上來了,異步請求的需求量上來了,JavaScript 才漸漸成了前端工程師的必備技能,甚至漸漸的,“掌握至少一門后端語言”也加入到了前端工程師的招聘需求中。

看來又多說了幾句,這次競賽前端項目的最后就是用 JavaScript 進(jìn)行邏輯與接口的實現(xiàn)。我們來分別談一談。

JavaScript 邏輯實現(xiàn)

邏輯實現(xiàn)包括輸入框信息的驗證、頁面的跳轉(zhuǎn)和用戶登錄狀態(tài)的保存等。在引入 JQuery 后,這一切開發(fā)變得簡單起來。

下面是一個用 JQuery 快速實現(xiàn)的輸入框驗證代碼示例。

var password = $("input:eq(0)").val();
var newPassword = $("input:eq(1)").val();
var rePassword = $("input:eq(2)").val();
var identity = $("input:eq(3)").val();
var flag = 1; // 1 代表判斷通過

if (!checkIDCard(identity)) flag = 0, tips = "不符合正確的身份證號格式";
if (!compareTwoPassWord(newPassword, rePassword)) flag = 0, tips = "密碼與重復(fù)密碼不一致";
if (!checkPassword(rePassword)) flag = 0, tips = "不符合正確的重復(fù)密碼格式(6~13位)";
if (!checkPassword(newPassword)) flag = 0, tips = "不符合正確的新密碼格式(6~13位)";
if (!checkPassword(password)) flag = 0, tips = "不符合正確的舊密碼格式(6~13位)";

下面是一個根據(jù)邏輯需求進(jìn)行頁面跳轉(zhuǎn)的代碼示例。

if (data["IsSuccess"]) {
    $(".pContentMessage").text("錄入成功!正在重新加載");
    setTimeout(function () {
        window.location.href = "admin_center.html?tab=0";
    }, 1000);
}

JavaScript 接口實現(xiàn)

前后端分離的項目中,后端只用注重接口的實現(xiàn)即可,一個一個很短的接口鏈接及其參數(shù)說明、返回結(jié)果說明拋給前端,前端就要進(jìn)行各種相應(yīng)的邏輯編程、UI 編程,正想不通,為什么在我周圍,學(xué)前端的還是女生多。當(dāng)然啦,前端業(yè)界的領(lǐng)頭人物性別比例就不多說了。我曾在一個前端微信群中聊過這類有關(guān)性別平等的話題,偏見還是很多的,就在我們身邊,這里就不多多說來。啊,前端和后端也平等。

一言不合,后端拋給你個接口,長得還很奇怪的樣子:

補全圖書信息
  • 請求地址

https://corefuture.cn/lib_api/book/finishBook.action

  • 請求類型

HTTP:POST

  • 參數(shù)
參數(shù)名稱 參數(shù)說明 必填
isbn 書的isbn號 Y
  • 結(jié)果示例
{
  "next": "",
  "count": 1,  
  "books": [
    {
      "bId": null,
      "bName": "大型網(wǎng)站系統(tǒng)與Java中間件開發(fā)實踐",
      "sId": null,
      "cId": null,
      "spell": null,
      "initial": null,
      "imgurl": "https://img1.doubanio.com/mpic/s27269837.jpg",
      "isbn": "9787121227615",
      "author": "曾憲杰",
      "count": null
    }
  ]
}
  • 返回參數(shù)說明
next:下一頁得next值,""表示沒有下一頁
count:books中含有幾本書
books:book的集合
book{
    bId:書籍唯一標(biāo)識
    bName:書籍名稱
    sId:書庫的標(biāo)識ID
    cId:書籍類型的標(biāo)識ID
    spell:全拼
    initial:首字母
    imgurl:書籍圖片路徑
    isbn:書籍的isbn號
    author:作者
    count:書庫中該書的總量
}

當(dāng)然,前端進(jìn)行數(shù)據(jù)訪問的跨域權(quán)限需要后端支持,具體怎么支持這就不是前端的事了。當(dāng)后端有上述接口示例交給前端時,如果不是需要帶有 Cookie 等參數(shù)的接口,前端可以直接用代碼實戰(zhàn)訪問,根據(jù)瀏覽器開發(fā)者工具里的具體報錯信息來修改代碼;更推薦在寫跨域代碼前先用 postman 這類的可視化 HTTP 請求工具/ API 測試工具來測試。

postman - 可視化 HTTP 請求工具

編寫跨域請求代碼時,需要一些異步回調(diào)相關(guān)的知識,當(dāng)請求結(jié)果返回時觸發(fā)回調(diào)函數(shù),進(jìn)行相應(yīng)的操作。這里用道德回調(diào)函數(shù),主要就是頁面跳轉(zhuǎn)和數(shù)據(jù)渲染兩個功能,例如一個完整的跨域請求函數(shù),并將返回結(jié)果渲染到頁面的代碼可以是下面這個樣子。

function finishBook () {
    // 隱藏詳情頁
    $(".pContentDetailWrap:eq(0)").hide();
    $(".pContentSubmitWrap:eq(0)").hide();
    var isbn = $("input:eq(0)").val();
    var post_data = {
        "isbn": isbn
    };
    if (!isbn) {
        $(".pContentMessage").text("ISBN 號不能為空");
        return;
    }
    var post_url = "https://wwwxinle.cn/Book/public/index.php/index/Manager/infoBook";
    $.post(post_url, post_data, function (data, status) {
        data = JSON.parse(data);
        if (data["count"] == 0) {
            $(".pContentMessage").text("沒有找到相關(guān)信息");
            return;
        }
        var book = data["books"][0];
        $(".pContentDetailLeftWrap img").attr("src", book["imgurl"])
        $(".pContentDetailItemWrap:eq(0) input").val(book["bName"]);
        $(".pContentDetailItemWrap:eq(3) input").val(book["author"]);
        $(".pContentDetailItemWrap:eq(4) input").val(1);
        $(".pContentDetailHiddenWrap").text(JSON.stringify(book));
        $(".pContentDetailWrap:eq(0)").show();
        $(".pContentSubmitWrap:eq(0)").show();
    });
}

回調(diào)成功,一個完整的跨域流程和前端對接口的實現(xiàn)流程就到了收尾之處?;卣{(diào)函數(shù)還有很多其它的注意點,比如回調(diào)函數(shù)里的變量值不能被回調(diào)函數(shù)外訪問的時候需要注意什么等,遇到這些坑時可以選擇盡可能將外部變量及其功能放入內(nèi)部實現(xiàn),或用其他更前沿的技術(shù)來實現(xiàn)。

整體架構(gòu)回顧

之前一直在說前端項目的構(gòu)建過程,在我們團隊三人的整體分工中,也是有其整體框架:Web 前端和沒有數(shù)據(jù)庫的 PHP 后端進(jìn)行請求,PHP 后端和有數(shù)據(jù)庫的 JAVA 數(shù)據(jù)接口進(jìn)行請求,JAVA 數(shù)據(jù)接口直接訪問數(shù)據(jù)庫——沃,其實隊友用的是基于 Apache Lucene(TM) 的開源搜索引擎,只不過我當(dāng)時看到他們進(jìn)行 SQL 操作了,不知者無罪~

獨特吧?Node.js 除了做后端,也可以做“前臺”,就是這時 Node 不操作數(shù)據(jù)庫,操作數(shù)據(jù)庫的還是典型的后端語言如 PHP、JAVA、Python 等;那么在這個項目中,PHP 微信端有點“前臺”的感覺,主要承載著每個人專屬微信號信息的獲取和公眾號的主推功能,并向 JAVA 后端進(jìn)行數(shù)據(jù)訪問。Web 前端只和 PHP 微信端進(jìn)行聯(lián)絡(luò)。

如果可以和 MVC 架構(gòu)聯(lián)系起來的話,Web 前端是大 V,PHP 微信端是大 C,JAVA 服務(wù)端是大 M;其中每個大 V、大 C、大 M 都有自己小 V、小 C、小 M。神奇的邏輯。

舍不得收尾、說拜拜

轉(zhuǎn)眼間,自己還在大學(xué)期間學(xué) JavaScript 基礎(chǔ)、學(xué)習(xí) CSS 布局的時候,ES 7、ES8 都開始被各大社群討論;React、Vue 等主流框架也開始加深誘惑著我們初學(xué)者;各大培訓(xùn)班瘋狂輸出的前端學(xué)員就光數(shù)量上也讓大學(xué)生軟件開發(fā)學(xué)習(xí)者有所擔(dān)憂。

一切還好。正如文章開始的那些感悟中隱藏在背后的那句羅曼羅蘭式英雄的風(fēng)度一樣——“世界上只有一種真正的英雄主義,就是認(rèn)清了生活的真相后還依然熱愛它”。

哈哈,希望我的引用不算錯位。也希望我的這個項目總結(jié)能散發(fā)出本身應(yīng)有的光芒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容