非漁之魚蜘澜,君其饗之:使用 React+Mustache 搭建一個(gè)類似螞蟻金服的 AntDesign 設(shè)計(jì)語(yǔ)言站點(diǎn)

題外話

最近一月實(shí)習(xí)入職施流,體驗(yàn)了一把 994 的生活 (因?yàn)橹苋覍W(xué)校還有課,一周實(shí)習(xí)四天)鄙信,也算是馬老師口中的 “身在福中” 了瞪醋,雖然很是疲憊,但是確實(shí)收獲頗多装诡,公司里面很多很多大佬银受,于我眼界践盼、技術(shù)、想法都提升增益了很多宾巍,特別是技術(shù)咕幻,我一個(gè)一直在學(xué)習(xí) Vue 的菜虛鯤突然進(jìn)了 React 項(xiàng)目組,羊入狼群顶霞,不知所措肄程,不過(guò)還好的是有點(diǎn) Vue 的底子,所以學(xué)起來(lái)也不算太難...

項(xiàng)目概述

這個(gè)月也一直在負(fù)責(zé)搭建一個(gè)類似螞蟻金服的設(shè)計(jì)語(yǔ)言網(wǎng)站选浑,受益匪淺蓝厌,項(xiàng)目也差不多完成了,馬上上線了古徒,所以也花些時(shí)間理一理這個(gè)項(xiàng)目的技術(shù)實(shí)現(xiàn)褂始,因?yàn)槭枪卷?xiàng)目,為了保密(不失業(yè))描函,所以我這里不會(huì)貼任何源代碼,因?yàn)槲疫@個(gè)項(xiàng)目與螞蟻金服的 AntDesign 很是相似狐粱,所以我之后的介紹都以 AntDesign 為例
伏愿:不現(xiàn)魚之相舀寓,仍識(shí)漁之意,一道非漁之魚肌蜻,君其饗之互墓!

技術(shù)分析

先放一張 AntDesign 的官網(wǎng)截圖



開(kāi)始剖析:




其實(shí)整個(gè)站點(diǎn)結(jié)構(gòu)極其簡(jiǎn)單,我已經(jīng)都畫出來(lái)了:

  • 頭部蒋搜,底部篡撵,側(cè)邊欄:這三部分結(jié)構(gòu)是內(nèi)容都是不變的,最多就是不同的選項(xiàng)卡被選中的時(shí)候顏色變一下
  • 正文內(nèi)容豆挽,錨點(diǎn)定位欄育谬,前后頁(yè)跳轉(zhuǎn):這三部分隨著頁(yè)面的不同內(nèi)容也會(huì)不同,所以這部分需要做定制化處理

技術(shù)棧

如果是初入門的切圖仔帮哈,制作這個(gè)網(wǎng)站其實(shí)也是一點(diǎn)壓力都沒(méi)有的膛檀,估計(jì)壓力比較大就是樣式和自適應(yīng)的問(wèn)題,利用 HTML+CSS+一點(diǎn)點(diǎn)的 JS 只要寫好一份頁(yè)面娘侍,然后每一個(gè)頁(yè)面對(duì)應(yīng)一份 HTML 和 CSS咖刃,又因?yàn)檎麄€(gè)站點(diǎn)的頁(yè)面很相似,所以利用 CV 大法憾筏,可以很快地完成整個(gè)站點(diǎn)
所以目錄結(jié)構(gòu)可能就是:
三個(gè)文件夾:JS嚎杨、CSS、HTML氧腰,然后每個(gè)頁(yè)面一一對(duì)應(yīng)
如果是這種方式寫出來(lái)的代碼枫浙,代碼結(jié)構(gòu)臃腫刨肃,可維護(hù)性差,(而且顯得大公司就很沒(méi)有水準(zhǔn)……)
So自脯,就有利用這樣的方式:

  • React:前端三大框架之一
  1. 數(shù)據(jù)驅(qū)動(dòng) DOM之景,將一些靜態(tài)的數(shù)據(jù)抽離出來(lái),避免臃腫重復(fù)的 DOM 結(jié)構(gòu)
  2. 組件化膏潮,使各個(gè)頁(yè)面相似的結(jié)構(gòu)抽離出來(lái)锻狗,形成一個(gè)組件
  • Mustache:前端模板引擎

類似 FreeMarker 模版引擎,不過(guò)不同于 FreeMaker 依托于 Java 相得益彰焕参, Mustache 是根正苗紅的前端模板引擎轻纪,十分友好好上手,語(yǔ)法和應(yīng)用搭配 React 簡(jiǎn)直不要太爽

  • Gulp+Sass:CSS 預(yù)處理器和自動(dòng)構(gòu)建工具

利用 Sass 再也不用寫面條一樣的臃腫丑陋的 CSS 了叠纷,其中的對(duì)于 CSS 變量刻帚,函數(shù),CSS 結(jié)構(gòu)的拓展優(yōu)化非常得好涩嚣,又因?yàn)闉g覽器只會(huì)識(shí)別 CSS 文件崇众,這時(shí)候需要 Gulp 自動(dòng)化構(gòu)建工具了,Gulp 不僅僅可以將 Sass 文件打包成 CSS 文件航厚,而且可以做到自動(dòng)化構(gòu)建顷歌,巴拉巴拉……具體可自行了解

  • Eslint+Stylelint:代碼規(guī)范

當(dāng)進(jìn)行大型項(xiàng)目開(kāi)發(fā)的時(shí)候,項(xiàng)目組不止一個(gè)人在開(kāi)發(fā)幔睬,而且項(xiàng)目在版本迭代的時(shí)候需要維護(hù)眯漩,這時(shí)候代碼規(guī)范就極其重要了

技術(shù)實(shí)現(xiàn)

以上介紹了大概介紹了技術(shù)棧,那么接下來(lái)就是怎么實(shí)現(xiàn)螞蟻金服的 AntDesign 的技術(shù)實(shí)現(xiàn)了麻顶!So赦抖,讓我們一層層揭下AntDesign 的 衣服 面紗吧!

組件化

在前文中我就提到:
React 的好處之一:將各個(gè)頁(yè)面相似的結(jié)構(gòu)抽離出來(lái)辅肾,形成一個(gè)組件
AntDesign 站點(diǎn)網(wǎng)頁(yè)的頭部队萤,底部,側(cè)邊欄矫钓,錨點(diǎn)定位欄浮禾,前后頁(yè)跳轉(zhuǎn)都是結(jié)構(gòu)相同的部分,所以這些都可以抽離出來(lái)份汗,放置在一個(gè) Components文件夾中盈电,單獨(dú)成一個(gè)組件,文件目錄類似這樣:

Components
 |—— Header.js
 |—— NavBar.js
 |—— PageNav.js
 |—— PageTurn.js
 └── Footer.js
  • 頭部和尾部

頭部和尾部結(jié)構(gòu)并不復(fù)雜杯活,而且多是靜態(tài)的固定的數(shù)據(jù)匆帚,所以可以直接寫,然后引入各個(gè)頁(yè)面中

  • 側(cè)邊欄

側(cè)邊欄可以直接寫樣式旁钧,通過(guò)重復(fù)的 DOM 結(jié)構(gòu)堆砌而成
但是可以利用 React 的好處之二:數(shù)據(jù)驅(qū)動(dòng) DOM吸重,將一些靜態(tài)的數(shù)據(jù)抽離出來(lái)互拾,避免臃腫重復(fù)的 DOM 結(jié)構(gòu)
1.將側(cè)邊導(dǎo)航欄的內(nèi)容數(shù)據(jù)抽成一個(gè)數(shù)組,獨(dú)立在在一個(gè)獨(dú)立的NavData.js文件中然后export出去
2.在NavBar.js中引入NavData.js嚎幸,通過(guò)Array.map()方法將數(shù)組依次遍歷然后生成重復(fù)的相同DOM

Example:


export const allMenus = [
    {
      text: 'Ant Design',
      type: 'design',
      menus: [
        { text: '介紹', type: 'design1', url: '/design/introduce.html' },
        { text: '設(shè)計(jì)價(jià)值觀', type: 'design2', url: '/design/design-values.html' },
        { text: '實(shí)踐案例', type: 'design3', url: '/design/practice-case.html' },
      ],
    },
    {
      text: '原則',
      type: 'principle',
      menus: [
        ...//省略原則的子選項(xiàng)
      ],
    },
    ...//省略后續(xù)的菜單選項(xiàng)
  ];

可以將菜單欄的菜單如此抽出構(gòu)成一個(gè)數(shù)組颜矿,然后將數(shù)組 allMenus 遍歷生成 DOM

  • 前后頁(yè)跳轉(zhuǎn)
    前后頁(yè)跳轉(zhuǎn)中的內(nèi)容就是左側(cè)菜單欄中的子選項(xiàng),只要獲取當(dāng)前的頁(yè)面的前一項(xiàng)和后一項(xiàng)的菜單欄子選項(xiàng)就可以了嫉晶,所以也可以同樣利用剛剛抽離出來(lái)的數(shù)組 allMenus
正文內(nèi)容渲染

正文內(nèi)容每頁(yè)都不一樣骑疆,所以是無(wú)法抽離成組件的,所以這個(gè)需要單獨(dú)寫替废,但是每一個(gè) HTML 文件除<body></body>標(biāo)簽其中的內(nèi)容不一樣箍铭,其他都可以復(fù)用,所以這時(shí)候 Mustache 就派上用場(chǎng)了:

  1. 每個(gè)頁(yè)面單獨(dú)寫一個(gè) JS 文件椎镣,寫成一個(gè) React 類诈火,然后就等于寫 HTML一樣在類render()中寫頁(yè)面內(nèi)容 DOM
  2. 將頁(yè)面的頭部菜單類別、主菜單類別状答、子菜單類別冷守、錨點(diǎn)內(nèi)容作為類的屬性一起export出去,這樣就能在寫錨點(diǎn)定位欄組件和頁(yè)面跳轉(zhuǎn)組件的時(shí)候使用props接收數(shù)據(jù)
  3. 創(chuàng)建一個(gè)單獨(dú)的 js 文件惊科,來(lái)管理這么多頁(yè)面export出來(lái)的數(shù)據(jù)內(nèi)容教沾,即類似上文的將導(dǎo)航欄抽成一個(gè)數(shù)組一樣,同理译断,將所有的頁(yè)面也抽成一個(gè)數(shù)組,之后就可以再使用Array.map()方法或悲,配合 Mustache 一一將 React 渲染成 html 文件
    Example:
    我用 AntDesign 菜單欄的第一項(xiàng) 'Ant Design' 的 '介紹' 頁(yè)面為例:

每個(gè)頁(yè)面有自己的頭部菜單類別(headType)孙咪、主菜單類別(firstType)、子菜單類別(subType)巡语、錨點(diǎn)內(nèi)容(affixList)翎蹈,那么我們就可以直接在頁(yè)面中定制化然后暴露出去:

import React, { Component } from 'react';

export default class Introduce extends Component {
  render() {
    return (
      <div className="content">
        {/* '介紹' 頁(yè)面的 DOM 結(jié)構(gòu)*/}
       </div>
    );
  }
}

Introduce.headType = 'design';
Introduce.firstType = 'design';
Introduce.subType = 'design1';
Introduce.affixList = [
  '設(shè)計(jì)資源',
  '前端實(shí)現(xiàn)',
  '誰(shuí)在使用',
  '社區(qū)評(píng)價(jià)',
  '如何貢獻(xiàn)',
];

以此類推,創(chuàng)建這么一個(gè)數(shù)組男公,來(lái)管理這么多的頁(yè)面數(shù)據(jù):

import Introduce from '../src/pages/design/Introduce';
import DesignValues from '../src/pages/design/DesignValues';
import PracticeCase from '../src/pages/design/PracticeCase';
...//將每個(gè)頁(yè)面 export 的都引進(jìn)來(lái)

export const allPages = [
  {
    mainCpn: Introduce,
    title: '介紹',
    name: 'design/introduce.html',
  },
  {
    mainCpn: DesignValues,
    title: '設(shè)計(jì)價(jià)值觀',
    name: 'design/design-values.html',
  },
  {
    mainCpn: BarrierFree,
    title: '實(shí)踐案例',
    name: 'design/practice-case.html',
  },
...//省略其他頁(yè)面
];
  1. 寫一份base.html作為渲染的基礎(chǔ)模版荤堪,在<body></body>中定義一個(gè)變量,作為 Mustache 內(nèi)容填充的插槽:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{title}}</title>
    <link rel="stylesheet" href="/css/base.css?v={{version}}" />
</head>

<body>
    <div id="app">{{{ssrHtml}}}</div>
</body>
<script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
<script type="text/javascript" src="/js/base.js?v={{version}}"></script>

</html>
  1. 利用fs這個(gè) node 模塊讀取base.html的內(nèi)容枢赔,然后作為 Mustache.render()方法的渲染對(duì)象參數(shù)澄阳,再將之前構(gòu)建好的頁(yè)面數(shù)組賦值給 base.html定義好的變量 ssrHtml ,再一一遍歷作為被渲染對(duì)象踏拜,然后再使用fs寫出各個(gè) HTML 文件

如此這般碎赢,最后便生成了整個(gè)項(xiàng)目的目錄文件
哦,對(duì)了速梗,為什么會(huì)引入了 Jquery肮塞?
因?yàn)檫@個(gè)項(xiàng)目有自適應(yīng)襟齿,所以會(huì)有動(dòng)畫和操作 DOM ,而且 React 只是單純地直接渲染 DOM 枕赵,沒(méi)有操作數(shù)據(jù)來(lái)驅(qū)動(dòng) DOM 猜欺,所以沒(méi)有和 Jq 沖突,所以可以放心地使用 Jq (其實(shí)用到 Jq 的地方也不多拷窜,就一些滾動(dòng)監(jiān)聽(tīng)之類的幾個(gè)方法)

The End

其實(shí)有很多細(xì)節(jié)的开皿,但是很多細(xì)節(jié)一聊就暴露我這個(gè)公司項(xiàng)目的源碼啊什么的了,而且由于時(shí)間實(shí)力原因装黑,可能很多問(wèn)題講不清晰副瀑,歡迎留言私信!定當(dāng)改進(jìn)加勉恋谭!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末糠睡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子疚颊,更是在濱河造成了極大的恐慌狈孔,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件材义,死亡現(xiàn)場(chǎng)離奇詭異均抽,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)其掂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門油挥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人款熬,你說(shuō)我怎么就攤上這事深寥。” “怎么了贤牛?”我有些...
    開(kāi)封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵惋鹅,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我殉簸,道長(zhǎng)闰集,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任般卑,我火速辦了婚禮武鲁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蝠检。我一直安慰自己洞坑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布厚脉。 她就那樣靜靜地躺著浊闪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪峭跳。 梳的紋絲不亂的頭發(fā)上排拷,一...
    開(kāi)封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天侧漓,我揣著相機(jī)與錄音,去河邊找鬼监氢。 笑死布蔗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的浪腐。 我是一名探鬼主播纵揍,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼议街!你這毒婦竟也來(lái)了泽谨?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤特漩,失蹤者是張志新(化名)和其女友劉穎吧雹,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體涂身,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雄卷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蛤售。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丁鹉。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖悴能,靈堂內(nèi)的尸體忽然破棺而出揣钦,到底是詐尸還是另有隱情,我是刑警寧澤搜骡,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站佑女,受9級(jí)特大地震影響记靡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜团驱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一摸吠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嚎花,春花似錦寸痢、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)道逗。三九已至,卻和暖如春献烦,著一層夾襖步出監(jiān)牢的瞬間滓窍,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工巩那, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吏夯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓即横,卻偏偏與公主長(zhǎng)得像噪生,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子东囚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5跺嗽? 答:HTML5是最新的HTML標(biāo)準(zhǔn)。 注意:講述HT...
    kismetajun閱讀 27,485評(píng)論 1 45
  • 問(wèn)答題47 /72 常見(jiàn)瀏覽器兼容性問(wèn)題與解決方案舔庶? 參考答案 (1)瀏覽器兼容問(wèn)題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,751評(píng)論 1 92
  • 前端開(kāi)發(fā)面試題 面試題目: 根據(jù)你的等級(jí)和職位的變化抛蚁,入門級(jí)到專家級(jí),廣度和深度都會(huì)有所增加惕橙。 題目類型: 理論知...
    怡寶丶閱讀 2,582評(píng)論 0 7
  • 可是瞧甩,我卻有這么一個(gè)男...
    巧克力熊閱讀 351評(píng)論 0 0
  • 這兩天里肚逸,我相信大家對(duì)何潔的離婚案開(kāi)庭的報(bào)道都有關(guān)注。 大家也許會(huì)在想彬坏,是什么讓一個(gè)女人會(huì)如此無(wú)情與絕望朦促? 昔日的...
    上善若水芳閱讀 327評(píng)論 1 4