<!DOCTYPE html>
<html>
<head>
<title>Page title</title>
</head>
<body> <img src="images/company_logo.png" alt="Company">
<h1 class="hello-world">Hello, world!</h1>
</body>
</html>
HTML5 doctype在頁(yè)面開頭使用這個(gè)簡(jiǎn)單地doctype來(lái)啟用標(biāo)準(zhǔn)模式,使其在每個(gè)瀏覽器中盡可能一致的展現(xiàn);雖然doctype不區(qū)分大小寫,但是按照慣例,doctype大寫 (關(guān)于html屬性,大寫還是小寫)。<!DOCTYPE html> <html> ... </html> lang屬性根據(jù)HTML5規(guī)范:應(yīng)在html標(biāo)簽上加上lang屬性。這會(huì)給語(yǔ)音工具和翻譯工具幫助,告訴它們應(yīng)當(dāng)怎么去發(fā)音和翻譯。
更多關(guān)于 lang 屬性的說(shuō)明在這里;在sitepoint上可以查到語(yǔ)言列表;
但sitepoint只是給出了語(yǔ)言的大類,例如中文只給出了zh,但是沒有區(qū)分香港,臺(tái)灣,大陸。而微軟給出了一份更加詳細(xì)的語(yǔ)言列表.aspx),其中細(xì)分了zh-cn, zh-hk, zh-tw。<!DOCTYPE html> <html lang="en-us"> ... </html> 字符編碼通過(guò)聲明一個(gè)明確的字符編碼,讓瀏覽器輕松、快速的確定適合網(wǎng)頁(yè)內(nèi)容的渲染方式,通常指定為’UTF-8’。<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> ... </html> IE兼容模式用 <meta> 標(biāo)簽可以指定頁(yè)面應(yīng)該用什么版本的IE來(lái)渲染;<!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> </head> ... </html> 引入CSS, JS根據(jù)HTML5規(guī)范, 通常在引入CSS和JS時(shí)不需要指明 type,因?yàn)?text/css 和 text/javascript 分別是他們的默認(rèn)值。HTML5 規(guī)范鏈接使用link
使用style
使用script<!-- External CSS --> <link rel="stylesheet" href="code_guide.css"> <!-- In-document CSS --> <style> ... </style> <!-- External JS --> <script src="code_guide.js"></script> <!-- In-document JS --> <script> ... </script> 屬性順序屬性應(yīng)該按照特定的順序出現(xiàn)以保證易讀性;
class是為高可復(fù)用組件設(shè)計(jì)的,所以應(yīng)處在第一位;
id更加具體且應(yīng)該盡量少使用,所以將它放在第二位。
<a class="..." id="..." data-modal="toggle" href="#">Example link</a>
<input class="form-control" type="text">
<img src="..." alt="...">
boolean屬性指不需要聲明取值的屬性,XHTML需要每個(gè)屬性聲明取值,但是HTML5并不需要;
更多內(nèi)容可以參考 WhatWG section on boolean attributes:
boolean屬性的存在表示取值為true,不存在則表示取值為false。
<input type="text" disabled>
<input type="checkbox" value="1" checked>
<select>
<option value="1" selected>1</option>
</select>
在JS文件中生成標(biāo)簽讓內(nèi)容變得更難查找,更難編輯,性能更差。應(yīng)該盡量避免這種情況的出現(xiàn)。
在編寫HTML代碼時(shí),需要盡量避免多余的父節(jié)點(diǎn);很多時(shí)候,需要通過(guò)迭代和重構(gòu)來(lái)使HTML變得更少。
<!-- Not well -->
<span class="avatar">
<img src="...">
</span>
<!-- Better -->
<img class="avatar" src="...">
盡量遵循HTML標(biāo)準(zhǔn)和語(yǔ)義,但是不應(yīng)該以浪費(fèi)實(shí)用性作為代價(jià);任何時(shí)候都要用盡量小的復(fù)雜度和盡量少的標(biāo)簽來(lái)解決問題。
么是工廠模式?
工廠模式是用來(lái)創(chuàng)建對(duì)象的一種最常用的設(shè)計(jì)模式。我們不暴露創(chuàng)建對(duì)象的具體邏輯,而是將將邏輯封裝在一個(gè)函數(shù)中,那么這個(gè)函數(shù)就可以被視為一個(gè)工廠。工廠模式根據(jù)抽象程度的不同可以分為:簡(jiǎn)單工廠,工廠方法和抽象工廠。
如果只接觸過(guò)JavaScript這門語(yǔ)言的的人可能會(huì)對(duì)抽象這個(gè)詞的概念有點(diǎn)模糊,因?yàn)镴avaScript 一直將abstract作為保留字而沒有去實(shí)現(xiàn)它。如果不能很好的理解抽象的概念,那么就很難理解工廠模式中的三種方法的異同。
下面我們來(lái)看一下之前提到的工廠模式的三種實(shí)現(xiàn)方法: 簡(jiǎn)單工廠模式、工廠方法模式、抽象工廠模式。
簡(jiǎn)單工廠模式
簡(jiǎn)單工廠模式又叫靜態(tài)工廠模式,由一個(gè)工廠對(duì)象決定創(chuàng)建某一種產(chǎn)品對(duì)象類的實(shí)例。主要用來(lái)創(chuàng)建同一類對(duì)象。
在實(shí)際的項(xiàng)目中,我們常常需要根據(jù)用戶的權(quán)限來(lái)渲染不同的頁(yè)面,高級(jí)權(quán)限的用戶所擁有的頁(yè)面有些是無(wú)法被低級(jí)權(quán)限的用戶所查看。所以我們可以在不同權(quán)限等級(jí)用戶的構(gòu)造函數(shù)中,保存該用戶能夠看到的頁(yè)面。在根據(jù)權(quán)限實(shí)例化用戶。代碼如下:
UserFactory就是一個(gè)簡(jiǎn)單工廠,在該函數(shù)中有3個(gè)構(gòu)造函數(shù)分別對(duì)應(yīng)不同的權(quán)限的用戶。當(dāng)我們調(diào)用工廠函數(shù)時(shí),只需要傳遞superAdmin, admin, user這三個(gè)可選參數(shù)中的一個(gè)獲取對(duì)應(yīng)的實(shí)例對(duì)象。你也許發(fā)現(xiàn),我們的這三類用戶的構(gòu)造函數(shù)內(nèi)部很相識(shí),我們還可以對(duì)其進(jìn)行優(yōu)化。
簡(jiǎn)單工廠的優(yōu)點(diǎn)在于,你只需要一個(gè)正確的參數(shù),就可以獲取到你所需要的對(duì)象,而無(wú)需知道其創(chuàng)建的具體細(xì)節(jié)。但是在函數(shù)內(nèi)包含了所有對(duì)象的創(chuàng)建邏輯(構(gòu)造函數(shù))和判斷邏輯的代碼,每增加新的構(gòu)造函數(shù)還需要修改判斷邏輯代碼。當(dāng)我們的對(duì)象不是上面的3個(gè)而是30個(gè)或更多時(shí),這個(gè)函數(shù)會(huì)成為一個(gè)龐大的超級(jí)函數(shù),便得難以維護(hù)。所以,簡(jiǎn)單工廠只能作用于創(chuàng)建的對(duì)象數(shù)量較少,對(duì)象的創(chuàng)建邏輯不復(fù)雜時(shí)使用。
工廠方法模式
工廠方法模式的本意是將實(shí)際創(chuàng)建對(duì)象的工作推遲到子類中,這樣核心類就變成了抽象類。但是在JavaScript中很難像傳統(tǒng)面向?qū)ο竽菢尤?shí)現(xiàn)創(chuàng)建抽象類。所以在JavaScript中我們只需要參考它的核心思想即可。我們可以將工廠方法看作是一個(gè)實(shí)例化對(duì)象的工廠類。
在簡(jiǎn)單工廠模式中,我們每添加一個(gè)構(gòu)造函數(shù)需要修改兩處代碼。現(xiàn)在我們使用工廠方法模式改造上面的代碼,剛才提到,工廠方法我們只把它看作是一個(gè)實(shí)例化對(duì)象的工廠,它只做實(shí)例化對(duì)象這一件事情! 我們采用安全模式創(chuàng)建對(duì)象。
上面的這段代碼就很好的解決了每添加一個(gè)構(gòu)造函數(shù)就需要修改兩處代碼的問題,如果我們需要添加新的角色,只需要在UserFactory.prototype中添加。例如,我們需要添加一個(gè)VipUser:
上面的這段代碼中,使用到的安全模式可能很難一次就能理解。
因?yàn)槲覀儗uperAdmin、Admin、NormalUser等構(gòu)造函數(shù)保存到了UserFactory.prototype中,也就意味著我們必須實(shí)例化UserFactory函數(shù)才能夠進(jìn)行以上對(duì)象的實(shí)例化。如下面代碼所示
在上面的調(diào)用函數(shù)的過(guò)程中, 一旦我們?cè)谌魏坞A段忘記使用new, 那么就無(wú)法正確獲取到superAdmin這個(gè)對(duì)象。但是一旦使用安全模式去進(jìn)行實(shí)例化,就能很好解決上面的問題。
抽象工廠模式
上面介紹了簡(jiǎn)單工廠模式和工廠方法模式都是直接生成實(shí)例,但是抽象工廠模式不同,抽象工廠模式并不直接生成實(shí)例, 而是用于對(duì)產(chǎn)品類簇的創(chuàng)建。
上面例子中的superAdmin,admin,user三種用戶角色,其中user可能是使用不同的社交媒體賬戶進(jìn)行注冊(cè)的,例如:wechat,qq,weibo。那么這三類社交媒體賬戶就是對(duì)應(yīng)的類簇。在抽象工廠中,類簇一般用父類定義,并在父類中定義一些抽象方法,再通過(guò)抽象工廠讓子類繼承父類。所以,抽象工廠其實(shí)是實(shí)現(xiàn)子類繼承父類的方法。
上面提到的抽象方法是指聲明但不能使用的方法。在其他傳統(tǒng)面向?qū)ο蟮恼Z(yǔ)言中常用abstract進(jìn)行聲明,但是在JavaScript中,abstract是屬于保留字,但是我們可以通過(guò)在類的方法中拋出錯(cuò)誤來(lái)模擬抽象類。
上述代碼中的getPrice就是抽象方法,我們定義它但是卻沒有去實(shí)現(xiàn)。如果子類繼承WechatUser但是并沒有去重寫getName,那么子類的實(shí)例化對(duì)象就會(huì)調(diào)用父類的getName方法并拋出錯(cuò)誤提示。
下面我們分別來(lái)實(shí)現(xiàn)賬號(hào)管理的抽象工廠方法:
AccountAbstractFactory就是一個(gè)抽象工廠方法,該方法在參數(shù)中傳遞子類和父類,在方法體內(nèi)部實(shí)現(xiàn)了子類對(duì)父類的繼承。對(duì)抽象工廠方法添加抽象類的方法我們是通過(guò)點(diǎn)語(yǔ)法進(jìn)行添加的。
下面我們來(lái)定義普通用戶的子類:
上述代碼我們分別定義了UserOfWechat,UserOfQq,UserOfWeibo三種類。這三個(gè)類作為子類通過(guò)抽象工廠方法實(shí)現(xiàn)繼承。特別需要注意的是,調(diào)用抽象工廠方法后不要忘記重寫抽象方法,否則在子類的實(shí)例中調(diào)用抽象方法會(huì)報(bào)錯(cuò)。
我們來(lái)分別對(duì)這三種類進(jìn)行實(shí)例化,檢測(cè)抽象工廠方法是實(shí)現(xiàn)了類簇的管理。
從打印結(jié)果上看,AccountAbstractFactory這個(gè)抽象工廠很好的實(shí)現(xiàn)了它的作用,將不同用戶賬戶按照社交媒體這一個(gè)類簇進(jìn)行了分類。這就是抽象工廠的作用,它不直接創(chuàng)建實(shí)例,而是通過(guò)類的繼承進(jìn)行類簇的管理。抽象工廠模式一般用在多人協(xié)作的超大型項(xiàng)目中,并且嚴(yán)格的要求項(xiàng)目以面向?qū)ο蟮乃枷脒M(jìn)行完成。
ES6中的工廠模式
ES6中給我們提供了class新語(yǔ)法,雖然class本質(zhì)上是一顆語(yǔ)法糖,并也沒有改變JavaScript是使用原型繼承的語(yǔ)言,但是確實(shí)讓對(duì)象的創(chuàng)建和繼承的過(guò)程變得更加的清晰和易讀。下面我們使用ES6的新語(yǔ)法來(lái)重寫上面的例子。
ES6重寫簡(jiǎn)單工廠模式
使用ES6重寫簡(jiǎn)單工廠模式時(shí),我們不再使用構(gòu)造函數(shù)創(chuàng)建對(duì)象,而是使用class的新語(yǔ)法,并使用static關(guān)鍵字將簡(jiǎn)單工廠封裝到User類的靜態(tài)方法中:
ES6重寫工廠方法模式
在上文中我們提到,工廠方法模式的本意是將實(shí)際創(chuàng)建對(duì)象的工作推遲到子類中,這樣核心類就變成了抽象類。但是JavaScript的abstract是一個(gè)保留字,并沒有提供抽象類,所以之前我們只是借鑒了工廠方法模式的核心思想。
雖然ES6也沒有實(shí)現(xiàn)abstract,但是我們可以使用new.target來(lái)模擬出抽象類。new.target指向直接被new執(zhí)行的構(gòu)造函數(shù),我們對(duì)new.target進(jìn)行判斷,如果指向了該類則拋出錯(cuò)誤來(lái)使得該類成為抽象類。下面我們來(lái)改造代碼。
ES6重寫抽象工廠模式
抽象工廠模式并不直接生成實(shí)例, 而是用于對(duì)產(chǎn)品類簇的創(chuàng)建。我們同樣使用new.target語(yǔ)法來(lái)模擬抽象類,并通過(guò)繼承的方式創(chuàng)建出UserOfWechat, UserOfQq, UserOfWeibo這一系列子類類簇。使用getAbstractUserFactor來(lái)返回指定的類簇。
工廠模式的項(xiàng)目實(shí)戰(zhàn)應(yīng)用
在實(shí)際的前端業(yè)務(wù)中,最常用的簡(jiǎn)單工廠模式。如果不是超大型的項(xiàng)目,是很難有機(jī)會(huì)使用到工廠方法模式和抽象工廠方法模式的。下面我介紹在Vue項(xiàng)目中實(shí)際使用到的簡(jiǎn)單工廠模式的應(yīng)用。
在普通的vue + vue-router的項(xiàng)目中,我們通常將所有的路由寫入到router/index.js這個(gè)文件中。下面的代碼我相信vue的開發(fā)者會(huì)非常熟悉,總共有5個(gè)頁(yè)面的路由:
當(dāng)涉及權(quán)限管理頁(yè)面的時(shí)候,通常需要在用戶登陸根據(jù)權(quán)限開放固定的訪問頁(yè)面并進(jìn)行相應(yīng)權(quán)限的頁(yè)面跳轉(zhuǎn)。但是如果我們還是按照老辦法將所有的路由寫入到router/index.js這個(gè)文件中,那么低權(quán)限的用戶如果知道高權(quán)限路由時(shí),可以通過(guò)在瀏覽器上輸入url跳轉(zhuǎn)到高權(quán)限的頁(yè)面。所以我們必須在登陸的時(shí)候根據(jù)權(quán)限使用vue-router提供的addRoutes方法給予用戶相對(duì)應(yīng)的路由權(quán)限。這個(gè)時(shí)候就可以使用簡(jiǎn)單工廠方法來(lái)改造上面的代碼。
在router/index.js文件中,我們只提供/login這一個(gè)路由頁(yè)面。
我們?cè)趓outer/文件夾下新建一個(gè)routerFactory.js文件,導(dǎo)出routerFactory簡(jiǎn)單工廠函數(shù),用于根據(jù)用戶權(quán)限提供路由權(quán)限,代碼如下
在登陸頁(yè)導(dǎo)入該方法,請(qǐng)求登陸接口后根據(jù)權(quán)限添加路由:
在實(shí)際項(xiàng)目中,因?yàn)槭褂胻his.$router.addRoutes方法添加的路由刷新后不能保存,所以會(huì)導(dǎo)致路由無(wú)法訪問。通常的做法是本地加密保存用戶信息,在刷新后獲取本地權(quán)限并解密,根據(jù)權(quán)限重新添加路由。這里因?yàn)楹凸S模式?jīng)]有太大的關(guān)系就不再贅述。
總結(jié)
上面說(shuō)到的三種工廠模式和上文的單例模式一樣,都是屬于創(chuàng)建型的設(shè)計(jì)模式。簡(jiǎn)單工廠模式又叫靜態(tài)工廠方法,用來(lái)創(chuàng)建某一種產(chǎn)品對(duì)象的實(shí)例,用來(lái)創(chuàng)建單一對(duì)象;工廠方法模式是將創(chuàng)建實(shí)例推遲到子類中進(jìn)行;抽象工廠模式是對(duì)類的工廠抽象用來(lái)創(chuàng)建產(chǎn)品類簇,不負(fù)責(zé)創(chuàng)建某一類產(chǎn)品的實(shí)例。在實(shí)際的業(yè)務(wù)中,需要根據(jù)實(shí)際的業(yè)務(wù)復(fù)雜度來(lái)選擇合適的模式。對(duì)于非大型的前端應(yīng)用來(lái)說(shuō),靈活使用簡(jiǎn)單工廠其實(shí)就能解決大部分問題。
日資料推薦
《模式識(shí)別與機(jī)器學(xué)習(xí)+源碼》
《模式識(shí)別與機(jī)器學(xué)習(xí)》,原英文名為《Pattern Recognition and Machine Learning》,也就是鼎鼎大名的 PRML。這本教材提供了對(duì)模式識(shí)別和機(jī)器學(xué)習(xí)領(lǐng)域的全面介紹,面向的讀者是本科生和低年級(jí)博士生,以及研究人員和從業(yè)人員。
該書是機(jī)器學(xué)習(xí)領(lǐng)域中的第一本機(jī)器學(xué)習(xí)教科書,全面涵蓋了該領(lǐng)域重要的知識(shí)點(diǎn),如概率圖模型和確定性推理方法,并強(qiáng)調(diào)現(xiàn)代貝葉斯觀點(diǎn)。本書適用于機(jī)器學(xué)習(xí)、統(tǒng)計(jì)學(xué)、計(jì)算機(jī)科學(xué)、信號(hào)處理、計(jì)算機(jī)視覺、數(shù)據(jù)挖掘、生物信息學(xué)等課程。
? 掃 碼 即 可 查 看 收 藏?
下載鏈接:https://www.yanxishe.com/resourceDetail/1052?from=leiphonecolumn_res0323
雷鋒網(wǎng)雷鋒網(wǎng)雷鋒網(wǎng)
更多相關(guān)資料下載:https://www.yanxishe.com/resources?from=leiphonecolumn
資料 |《機(jī)器學(xué)習(xí)實(shí)戰(zhàn):基于 Scikit-Learn、Keras 和 TensorFlow(第二版)》
資料 |《常用數(shù)據(jù)挖掘算法總結(jié)及 Python 實(shí)現(xiàn)》
資料 | 《 Pytorch 深度學(xué)習(xí)實(shí)戰(zhàn) 》 資料 | 《 面向機(jī)器學(xué)習(xí)的特征工程 》
資料 | 程序員面試寶典 第 5 版
資料 | 《 機(jī)器學(xué)習(xí)數(shù)學(xué)基礎(chǔ) 》
資料 | 《 怎樣解題:數(shù)學(xué)競(jìng)賽攻關(guān)寶典(第 2 版) 》
資料 | 《 Linux 命令行與 shell 腳本編程大全 》
資料下載 | 數(shù)學(xué)分析八講(修訂版) :概述了數(shù)學(xué)分析的基本思想、基本概念和基本方法 資料 | 《 大話數(shù)據(jù)結(jié)構(gòu) 》
資料 | 《 你不知道的 JavaScript(上卷) 》
資料 | 算法設(shè)計(jì)與分析基礎(chǔ)(第 3 版)
資料 | 《 JavaScript 高級(jí)程序設(shè)計(jì)(第3版)中文-高清 》
資料 | 《 圖解密碼技術(shù)(第 3 版) 》
資料 | 《 Java 8 實(shí)戰(zhàn) 》 資料 | 《 推薦系統(tǒng)實(shí)踐 》
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。