前端開(kāi)發(fā)規(guī)范

一撼短、概述

本規(guī)范旨在為前端程序的開(kāi)發(fā)者提供規(guī)范化最新的指導(dǎo),可用于程序員個(gè)人編譯環(huán)境以及研發(fā)團(tuán)隊(duì)集成環(huán)境等場(chǎng)合的代碼規(guī)范化檢查挺勿。

不管有多少人共同參與同一項(xiàng)目曲横,一定要確保每一行代碼都像是同一個(gè)人編寫的

二、方針

約束等級(jí) 約束效力 強(qiáng)制性
【強(qiáng)制】 違反該項(xiàng)將被認(rèn)為代碼存在嚴(yán)重缺陷 前端程序團(tuán)隊(duì)必須遵守
【推薦】 違反該項(xiàng)將被認(rèn)為代碼存在輕微缺陷 根據(jù)具體產(chǎn)品特性的不同不瓶,選擇性地遵守
【參考】 違反該項(xiàng)可被認(rèn)為代碼存在優(yōu)化空間 從產(chǎn)品持續(xù)優(yōu)化及人員技能提升的角度禾嫉,參考使用

三、環(huán)境要求

  1. 【強(qiáng)制】Node.js 8.9 或更高版本湃番,你可以使用 nvmnvm-windows 在一臺(tái)電腦中管理多個(gè) Node 版本

  2. 【強(qiáng)制】使用 Visual Studio Code (VS Code) 進(jìn)行代碼編寫

  3. 【強(qiáng)制】代碼提交前使用 VS Code 進(jìn)行格式化(不要格式引入的外部文件)

  4. 【強(qiáng)制】規(guī)定 Tab 大小為 2 個(gè)空格夭织,保證在所有環(huán)境下獲得一致展現(xiàn)

// settings.json
{
  "editor.tabSize": 2
  // ...
}
  1. 【強(qiáng)制】安裝插件 Vetur( Vue開(kāi)發(fā)擴(kuò)展及 Vue 文件代碼格式化)

  2. 【強(qiáng)制】安裝插件 Prettier - Code formatter( CSS / Less / JS 等其他文件代碼格式化;Vetur 的格式化基于此插件實(shí)現(xiàn)吠撮,固可以在所有文件實(shí)現(xiàn)統(tǒng)一的格式化)

  3. 【推薦】安裝插件 Chinese (Simplified) Language Pack for Visual Studio Code ( VS Code 簡(jiǎn)體中文語(yǔ)言包)

  4. 【推薦】使用 Chrome 瀏覽器并安裝 Vue.js devtools 進(jìn)行調(diào)試

四、編碼規(guī)范

4.1 HTML / Template 編碼規(guī)范

  1. 【強(qiáng)制】縮進(jìn)使用兩個(gè)空格代替 Tab
    • 前端代碼層級(jí)較深讲竿,使用短縮進(jìn)有利于利用屏幕空間泥兰,提升效率
    • 使用兩個(gè)空格代替 Tab 可以保證在所有環(huán)境下獲得一致展現(xiàn)
<!-- not good -->
<div>
    <div>bar</div>
</div>

<!-- good -->
<div>
  <div>bar</div>
</div>
  1. 【強(qiáng)制】嵌套元素應(yīng)當(dāng)縮進(jìn)一次(即兩個(gè)空格),同層級(jí)縮進(jìn)應(yīng)保持一致
<!-- not good -->
<div>
<div>bar</div>
  <div>bar</div>
</div>

<!-- good -->
<div>
  <div>bar</div>
  <div>bar</div>
</div>
  1. 【強(qiáng)制】對(duì)于屬性的定義题禀,使用雙引號(hào)鞋诗,不要使用單引號(hào)
<!-- not good -->
<input class='a' type=text>

<!-- good -->
<input class="a" type="text">
  1. 【強(qiáng)制】不要省略可選的結(jié)束標(biāo)簽(closing tag)(如</li> 或 </body>)
    省略可選的結(jié)束標(biāo)簽,雖不會(huì)違反 H5 規(guī)范迈嘹;但可能會(huì)造成層級(jí)上的困擾削彬,導(dǎo)致代碼出現(xiàn)無(wú)法預(yù)料的問(wèn)題
<!-- not good -->
<h1>h1 text
  <h2>h2 text

<!-- good -->
<h1>h1 text</h1>
<h2>h2 text</h2>
  1. 【強(qiáng)制】特殊符號(hào)使用 HTML 字符實(shí)體(實(shí)體名稱對(duì)大小寫敏感),常用如下:
符號(hào) 實(shí)體編碼
空格 &nbsp;
? &copy;
&yen;
? &reg;
> &reg;
< &lt;
& &amp;
  1. 【強(qiáng)制】td / th 要在 tr 里面秀仲,li 要在 ul / ol 里面
<!-- not good -->
<table>
  <td>test</td>
</table>

<!-- good -->
<table>
  <tr>
    <td>test</td>
  </tr>
</table>
  1. 【強(qiáng)制】ul / ol 的直接子元素只能是 li融痛,不能包含其他元素
<!-- not good -->
<ul>
  <span>123</span>
  <li>a</li>
  <li>b</li>
</ul>
  1. 【強(qiáng)制】行內(nèi)元素里面不可使用塊級(jí)元素
    a 標(biāo)簽是一個(gè)行內(nèi)元素,行內(nèi)元素里面套了一個(gè) div 的標(biāo)簽神僵,這樣可能會(huì)導(dǎo)致 a 標(biāo)簽無(wú)法正常點(diǎn)擊
<!-- not good -->
<a href="../test">
  <div></div>
</a>

可以使用如下代碼進(jìn)行修復(fù):

<a href="../test" style="display: block">
  <div></div>
</a>
  1. 【強(qiáng)制】不使用自定義標(biāo)簽雁刷,會(huì)與Vue組件系統(tǒng)的自定義組件沖突
  2. 【強(qiáng)制】不使用重復(fù)屬性,重復(fù)的屬性只會(huì)取第一個(gè)
<!-- error -->
<input class="a" type="text" class="b">
   
<!-- good -->
<input class="a b" type="text">
  1. 【強(qiáng)制】不要在https的鏈接里寫http的圖片
    只要https的網(wǎng)頁(yè)請(qǐng)求了一張http的圖片保礼,就會(huì)導(dǎo)致瀏覽器地址欄左邊的小鎖沒(méi)有了沛励,一般不要寫死,寫成根據(jù)當(dāng)前域名的協(xié)議去加載炮障,用//開(kāi)頭:
<img src="http://static.chimeroi.com/hello-world.jpg">
  1. 【推薦】不要在自閉合(self-closing)元素的尾部添加斜線( HTML5 規(guī)范中說(shuō)明這是可選的)
<!-- not good -->
<img src="logo.png" alt />
   
<!-- good -->
<img src="logo.png" alt>
  1. 【推薦】不使用屬性設(shè)置樣式(img, table等元素)
<!-- not good -->
<img src="test.jpg" alt width="400" height="300">

<!-- good -->
<img src="test.jpg" style="width:400px;height:300px;">
  1. 【參考】自定義屬性要以data-開(kāi)頭 自己添加的非標(biāo)準(zhǔn)的屬性要以data-開(kāi)頭目派,否則w3c validator會(huì)認(rèn)為是不規(guī)范的
<!-- not good -->
<div count="5"></div>

<!-- good -->
<div data-count="5"></div>

HTML5 doctype
【強(qiáng)制】為每個(gè) HTML 頁(yè)面添加標(biāo)準(zhǔn)模式(standard mode)的聲明,確保在每個(gè)瀏覽器中擁有一致的展現(xiàn)

<!DOCTYPE html>

<html>
  ...

語(yǔ)言屬性
【強(qiáng)制】為每個(gè) HTML 頁(yè)面根元素添加 lang 屬性

根據(jù) HTML5 規(guī)范:

強(qiáng)烈建議為 html 根元素指定 lang 屬性胁赢,從而為文檔設(shè)置正確的語(yǔ)言企蹭。這將有助于語(yǔ)音合成工具確定其所應(yīng)該采用的發(fā)音,有助于翻譯工具確定其翻譯時(shí)所應(yīng)遵守的規(guī)則等等。

<html lang="zh-CN">
  <!-- ... -->
</html>

字符編碼

【強(qiáng)制】通過(guò)聲明一個(gè)明確的字符編碼练对,讓瀏覽器輕松遍蟋、快速的確定網(wǎng)頁(yè)內(nèi)容渲染方式,通常指定為'UTF-8'

<html>
  <head>
    <meta charset="UTF-8">
  </head>
  ...

引入 CSS 和 JavaScript 文件

【強(qiáng)制】根據(jù) HTML5 規(guī)范螟凭,在引入 CSS 和 JavaScript 文件時(shí)不需要指定 type 屬性虚青,因?yàn)?text/css 和 text/javascript 分別是它們的默認(rèn)值

<!-- 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>

減少標(biāo)簽的數(shù)量

【推薦】編寫 HTML 代碼時(shí),盡量避免多余的層級(jí)

<!-- not good -->
<span class="avatar">
  <img src="...">
</span>

<!-- good -->
<img class="avatar" src="...">

屬性順序
【參考】屬性應(yīng)該按照特定的順序出現(xiàn)以保證易讀性

  1. class
  2. id
  3. name
  4. data-*
  5. src, for, type, href, value , max-length, max, min, pattern
  6. placeholder, title, alt
  7. aria-*, role
  8. required, readonly, disabled

語(yǔ)義化
【參考】盡量遵循 HTML 標(biāo)準(zhǔn)和語(yǔ)義螺男,但是不要以犧牲實(shí)用性為代價(jià)棒厘;任何時(shí)候都要盡量使用最少的標(biāo)簽并保持最小的復(fù)雜度。

4.2 CSS / Less 編碼規(guī)范

命名

  1. 【強(qiáng)制】類名使用小寫字母下隧,以中劃線分隔

  2. 【強(qiáng)制】id 采用駝峰式命名

  3. 【強(qiáng)制】less 中的變量奢人、函數(shù)、混合等采用駝峰式命名

@mainFontColor: #444;

#companyName,
.company-name {
  color: @mainFontColor;
}

語(yǔ)法

  1. 【強(qiáng)制】所有聲明語(yǔ)句都應(yīng)當(dāng)以分號(hào)結(jié)尾 最后一條聲明語(yǔ)句后面的分號(hào)是可選的淆院,但是何乎,如果省略這個(gè)分號(hào),你的代碼可能更易出錯(cuò)
/* error */
.selector {
    font-size: 15px
  color: red
}

/* not good */
.selector {
    font-size: 15px;
  color: red
}

/* good */
.selector {
    font-size: 15px;
  color: red;
}
  1. 【強(qiáng)制】避免為 0 值指定單位土辩,例如支救,用 margin: 0; 代替 margin: 0px;
  2. 【強(qiáng)制】為選擇器中的屬性添加雙引號(hào),例如拷淘,input[type="text"]各墨; 某些情況下是可選的,但是启涯,為了代碼的一致性贬堵,建議都加上雙引號(hào)
/* not good */
.selector[type=text] {
  /* ... */
}

/* good */
.selector[type="text"] {
  /* ... */
}
  1. 【強(qiáng)制】十六進(jìn)制值應(yīng)該全部小寫,例如结洼,#f3f6fa

  2. 【強(qiáng)制】不出現(xiàn)空的規(guī)則(聲明塊中沒(méi)有聲明語(yǔ)句)

  3. 【強(qiáng)制】不要設(shè)置太大的z-index(一個(gè)正常的系統(tǒng)的層級(jí)關(guān)系在 10 以內(nèi)就能完成)

  4. 【強(qiáng)制】多寫注釋黎做,且多使用句子進(jìn)行描述而不是詞語(yǔ)

/* 為了去除輸入框和表單點(diǎn)擊時(shí)的灰色背景 */
input, 
form {
    -webkit-tap-highlight-color:  rgba(255, 255, 255, 0);
}
  1. 【推薦】不要使用*選擇器

  2. 【推薦】適當(dāng)使用:before:after來(lái)畫(huà)頁(yè)面的一些視覺(jué)上的輔助性元素,如三角形补君、短的分隔線引几、短豎線等,可以減少頁(yè)面上沒(méi)有用的標(biāo)簽

  3. 【推薦】選擇器不要超過(guò)4層(在 Less 中避免嵌套超過(guò) 4 層)

  4. 【推薦】用 border: 0; 代替 border: none;

  5. 【推薦】使用簡(jiǎn)寫形式的十六進(jìn)制值挽铁,例如伟桅,用 #fff代替 #ffffff

  6. 【推薦】對(duì)于屬性值或顏色參數(shù),省略小于 1 的小數(shù)前面的 0 (例如叽掘,.5 代替 0.5楣铁;-.5px代替 -0.5px

代碼風(fēng)格
此處大部分工作將由代碼格式化工具完成(參見(jiàn)環(huán)境要求),一般無(wú)需考慮

  1. 【強(qiáng)制】縮進(jìn)使用兩個(gè)空格代替 Tab
  2. 【強(qiáng)制】為選擇器分組時(shí)更扁,將單獨(dú)的選擇器單獨(dú)放在一行
/* not good */
.selector, .selector-secondary, .selector[type=text] {
  /* ... */
}

/* good */
.selector,
.selector-secondary,
.selector[type="text"] {
  /* ... */ 
}
  1. 【強(qiáng)制】聲明塊的左花括號(hào)前添加一個(gè)空格

  2. 【強(qiáng)制】聲明塊的右花括號(hào)應(yīng)當(dāng)單獨(dú)成行

  3. 【強(qiáng)制】每條聲明語(yǔ)句的 : 后應(yīng)該插入一個(gè)空格

  4. 【強(qiáng)制】每條樣式聲明應(yīng)該獨(dú)占一行

/* not good */
.selector {
    font-size: 15px; color: red;
}

/* good */
.selector {
    font-size: 15px;
  color: red;
}
  1. 【強(qiáng)制】對(duì)于以逗號(hào)分隔的屬性值盖腕,每個(gè)逗號(hào)后面都應(yīng)該插入一個(gè)空格(例如赫冬,box-shadowtransition
/* not good */
.selector {
  transition: border .2s,color .3s,padding .4s;
}

/* good */
.selector {
  transition: border .2s, color .3s, padding .4s;
}
  1. 【強(qiáng)制】!important前插入一個(gè)空格

  2. 【強(qiáng)制】注釋://后插入一個(gè)空格溃列,/*后插入一個(gè)空格劲厌,*/前插入一個(gè)空格

  3. 【強(qiáng)制】Less 的操作符,在圓括號(hào)中的數(shù)學(xué)計(jì)算表達(dá)式的數(shù)值听隐、變量和操作符之間均添加一個(gè)空格

  4. 【推薦】注釋統(tǒng)一用/* */( Less 中也不要用//

樣式兼容性

  1. 【強(qiáng)制】當(dāng)使用一些較新的 CSS3 語(yǔ)法時(shí)补鼻,應(yīng)注意添加瀏覽器前綴( FAIS 2 打包工具包含 CSS 預(yù)處理,固無(wú)需考慮此條)

  2. 【推薦】不要使用 input 的 line-height來(lái)做垂直居中 設(shè)置 line-height為一個(gè)很高的值會(huì)導(dǎo)致 Safari 瀏覽器的輸入光標(biāo)變得巨大 (與 line-height 等高)

/* not good */
input {
  height: 40px;
  line-height: 40px;
}

/* good */
input {
  height: 20px;
  line-height: 20px;
  padding: 10px 0;
}

選擇器權(quán)重(樣式覆蓋)

權(quán)重的基本規(guī)則:

  1. 相同的權(quán)重:以后面出現(xiàn)的選擇器為最后規(guī)則
  2. 相同的權(quán)重:以后面出現(xiàn)的選擇器為最后規(guī)則
    詳細(xì)了解權(quán)重計(jì)算方法
  1. 【強(qiáng)制】非通用樣式使用嵌套方式進(jìn)行編寫雅任,避免影響其他自己不了解樣式风范,造成樣式覆蓋
  2. 【推薦】Vue 中樣式謹(jǐn)慎使用 scoped,會(huì)影響樣式選擇器性能沪么,請(qǐng)使用第一點(diǎn)進(jìn)行特有樣式編寫
  3. 【推薦】樣式需要修改時(shí)硼婿,盡量找到原樣式聲明進(jìn)行修改
  4. 【強(qiáng)制】無(wú)法修改原樣式聲明時(shí),應(yīng)通過(guò)權(quán)重關(guān)系禽车,編寫權(quán)重更高的樣式進(jìn)行覆蓋
  5. 【強(qiáng)制】不使用!important寇漫,除非原樣式使用內(nèi)聯(lián)樣式或!important且無(wú)法直接修改

聲明簡(jiǎn)寫

  1. 【推薦】當(dāng)你不確定自己寫的屬性會(huì)否影響到其他屬性時(shí),應(yīng)避免使用簡(jiǎn)寫
/* error */
.element {
  margin: 0 0 10px;
  background: red;
  background: url("image.jpg");
  border-radius: 3px 3px 0 0;
}

/* good */
.element {
  margin-bottom: 10px;
  background-color: red;
  background-image: url("image.jpg");
  border-top-left-radius: 3px;
  border-top-right-radius: 3px;
}
  1. 【推薦】當(dāng)你確定自己的聲明不會(huì)影響到其他屬性時(shí)哭当,請(qǐng)使用簡(jiǎn)寫提升代碼簡(jiǎn)潔性
/* not good */
.element {
  padding-top: 10px;
  padding-right: 20px;
  padding-bottom: 15px;
  padding-left: 20px;
}

/* good */
.element {
  padding: 10px 20px 15px;
}

CSS動(dòng)畫(huà)

  1. 【推薦】不要使用all屬性做動(dòng)畫(huà)

使用transition做動(dòng)畫(huà)的時(shí)候不要使用all所有屬性猪腕,在有一些瀏覽器上面可能會(huì)有一些問(wèn)題,如下:

transition: all 2s linear;

在Safari上面可能會(huì)有一些奇怪的抖動(dòng)钦勘,正確的做法是要用哪個(gè)屬性做動(dòng)畫(huà)就寫哪個(gè),如果有多個(gè)就用隔開(kāi)亚亲,如下代碼所示:

transition: transform 2s linear, opacity 2s linear;

  1. 【推薦】位移動(dòng)畫(huà)使用 transform 替代 position (提升動(dòng)畫(huà)性能)
  2. 【推薦】使用 CSS 動(dòng)畫(huà)替代 JS 動(dòng)畫(huà)

聲明順序

【參考】相關(guān)的屬性聲明按以下順序做分組處理彻采,組之間需要有一個(gè)空行

  1. Positioning(影響其他元素和自身位置相關(guān)聲明

  2. Box model(自身盒模型相關(guān)聲明)

  3. Typographic(文本相關(guān)聲明)

  4. Visual(自身樣式)

  5. Misc(其他聲明)

.declaration-order {
  /* Positioning */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 100;

  /* Box-model */
  display: block;
  float: right;
  width: 100px;
  height: 100px;

  /* Typography */
  font: normal 13px "Helvetica Neue", sans-serif;
  line-height: 1.5;
  color: #333;
  text-align: center;

  /* Visual */
  background-color: #f5f5f5;
  border: 1px solid #e5e5e5;
  border-radius: 3px;

  /* Misc */
  opacity: 1;
}

4.3 JavaScript 編碼規(guī)范

命名

  1. 【強(qiáng)制】標(biāo)準(zhǔn)變量采用駝峰式命名(考慮與后臺(tái)交換數(shù)據(jù)的情況,對(duì)象屬性可靈活命名)

  2. 【強(qiáng)制】常量全大寫捌归,用下劃線連接

  3. 【強(qiáng)制】變量名不應(yīng)過(guò)短肛响,要能準(zhǔn)確完整地描述該變量所表述的事物

不好的變量名 好的變量名
inp input, priceInput
day1, day2, param1 today, tomorrow
id userId, orderId
obj orderData, houseInfos
tId removeMsgTimerId
handler submitHandler, searchHandler
  1. 【強(qiáng)制】變量名不要使用計(jì)算機(jī)術(shù)語(yǔ),如 texareaData惜索,應(yīng)該取和業(yè)務(wù)相關(guān)的名字特笋,如 leaveMsg

  2. 【強(qiáng)制】變量名的對(duì)仗要明確,如 up/down巾兆、begin/end猎物、opened/closed、visible/invisible蔫磨、scource/target

  3. 【強(qiáng)制】變量名使用正確的語(yǔ)法

不要使用中文拼音,如 shijianchuo 應(yīng)改成 timestamp 圃伶; 如果是復(fù)數(shù)的話加 s堤如,或者加上 List蒲列,如 orderList、menuItems搀罢; 而過(guò)去式的加上 ed蝗岖,如 updated/found 等; 如果正在進(jìn)行的加上 ing榔至,如 calling抵赢;

  1. 【推薦】使用臨時(shí)變量時(shí)請(qǐng)結(jié)合實(shí)際需要進(jìn)行變量命名

些喜歡取temp和obj之類的變量,如果這種臨時(shí)變量在兩行代碼內(nèi)就用完了洛退,接下來(lái)的代碼就不會(huì)再用了瓣俯,還是可以接受的,如交換數(shù)組的兩個(gè)元素兵怯。但是有些人取了個(gè)temp彩匕,接下來(lái)十幾行代碼都用到了這個(gè)temp,這個(gè)就讓人很困惑了媒区。所以應(yīng)該盡量少用temp類的變量

// not good
let temp = 10;
let leftPosition = currentPosition + temp驼仪,
    topPosition = currentPosition - temp;

// good
let adjustSpace = 10;
let leftPosition = currentPosition + adjustSpace,
     topPosition = currentPosition - adjustSpace;
  1. 【推薦】波爾變量可以結(jié)合實(shí)際語(yǔ)境使用 done/found/successs/ok/available/complete 等修飾詞
// good
let ajaxDone = true,
    fileFound = false,
    resourceUpdated = true;
  1. 【推薦】波爾變量名應(yīng)使用肯定的布爾變量名袜漩,不要使用否定的名詞绪爸,如 notOk、notReady宙攻,因?yàn)榉穸ǖ脑~取反的時(shí)候就會(huì)比較奇怪奠货,如 if (!notOk)

語(yǔ)法

  1. 【強(qiáng)制】變量不要先使用后聲明

  2. 【強(qiáng)制】不要聲明了變量卻不使用

  3. 【強(qiáng)制】不要在同個(gè)作用域下聲明同名變量

  4. 【強(qiáng)制】一個(gè)函數(shù)作用域中所有的變量聲明盡量提到函數(shù)首部,可根據(jù)代碼進(jìn)行分組座掘,但不允許出現(xiàn)兩個(gè)連續(xù)的變量聲明

// not good
let registerForm = null;
let question = "";
let calculateResult = 0;

// good
let registerForm = null,
    question = "",
    calculateResult = 0;
  1. 【強(qiáng)制】為了快速知曉變量類型递惋,聲明變量時(shí)要賦值
// not good
let registerForm,
    question,
    calculateResult;

// good
let registerForm = null,
    question = "",
    calculateResult = 0;
  1. 【強(qiáng)制】單一函數(shù)的返回值類型要確定(如下無(wú)法確定該函數(shù)的最終返回類型)
// not good
function calculatePrice(seatCount){
  if (seatCount <= 0) {
     return "";
  } else {
     return seatCount * 79;
  }
}
  1. 【強(qiáng)制】debugger不要出現(xiàn)在提交的代碼里

  2. 【推薦】使用===代替==!==代替!===會(huì)自動(dòng)進(jìn)行類型轉(zhuǎn)換溢陪,可能會(huì)出現(xiàn)奇怪的結(jié)果)

null == undefined          //true
'' == '0'                  //false
0  == ''                   //true
0  == '0'                  //true
' \t\r\n ' == 0            //true
new String("abc") == "abc" //true
new Boolean(true) == true  //true
true == 1                  //true
  1. 【推薦】使用三目運(yùn)算代替簡(jiǎn)單的 if-else
// not good
let seatDiscount = 100;
if (seat < 5) {
  seatDiscount = 90;
} else if(seat < 10) {
  seatDiscount = 80;
} else {
  seatDiscount = 70;
}

// good
let seatDiscount = seat < 5 ? 90 : seat < 10 ? 80 : 70;
  1. 【推薦】使用let定義變量萍虽,const定義常量

  2. 【推薦】使用箭頭函數(shù)取代簡(jiǎn)單的函數(shù)

// not good
let _this = this;
setTimeout(function() {
  _this.foo = "bar";
}, 2000);

// good
setTimeout(() => this.foo = "bar", 2000);
  1. 【推薦】在必要的地方添加非空判斷以提高代碼的穩(wěn)健性

  2. 【推薦】將復(fù)雜的函數(shù)分解成多個(gè)子函數(shù),方便維護(hù)和復(fù)用

代碼風(fēng)格
此處大部分工作將由代碼格式化工具完成(參見(jiàn)環(huán)境要求)形真,一般無(wú)需考慮

  1. 【強(qiáng)制】縮進(jìn)使用兩個(gè)空格代替 Tab

  2. 【強(qiáng)制】統(tǒng)一使用雙引號(hào)""(與 Prettier 默認(rèn)格式化配置持一致)

  3. 【強(qiáng)制】以下幾種情況后需加分號(hào);

    • 變量聲明

    • 表達(dá)式

    • return

    • throw

    • break

    • continue

    • do-while

  4. 【強(qiáng)制】以下幾種情況不需要空格:

    • 二元運(yùn)算符前后
    • 三元運(yùn)算符'?:'前后
    • 代碼塊'{'前
    • 下列關(guān)鍵字前:else,while,catch,finally
    • 下列關(guān)鍵字后:
      if,else,for,while,do,switch,case,try,catch,finally,with,
      return,typeof
    • 單行注釋'//'后(若單行注釋和代碼同行杉编,則'//'前也需要),多行注釋'*'后
    • 對(duì)象的屬性值前
    • for循環(huán)咆霜,分號(hào)后留有一個(gè)空格邓馒,前置條件如果有多個(gè),逗號(hào)后留一個(gè)空格
    • 無(wú)論是函數(shù)聲明還是函數(shù)表達(dá)式裕便,'{'前一定要有空格
    • 函數(shù)的參數(shù)之間

數(shù)組绒净、對(duì)象

1.【強(qiáng)制】對(duì)象屬性名不需要加引號(hào)

2.【強(qiáng)制】對(duì)象以縮進(jìn)的形式書(shū)寫,不要寫在一行

3.【強(qiáng)制】數(shù)組中不要存在空元素

4.【強(qiáng)制】不要用for in循環(huán)數(shù)組

5.【推薦】數(shù)組偿衰、對(duì)象最后不要有逗號(hào)

// not good
let a = {
  'b': 1
};

let a = { b: 1 };

let a = {
  b: 1,
  c: 2,
};

// good
let a = {
  b: 1,
  c: 2
};

使用 null

【強(qiáng)制】正確使用 null

適用場(chǎng)景:

  • 初始化一個(gè)將來(lái)可能被賦值為對(duì)象的變量
  • 與已經(jīng)初始化的變量做比較
  • 作為一個(gè)參數(shù)為對(duì)象的函數(shù)的調(diào)用傳參
  • 作為一個(gè)返回對(duì)象的函數(shù)的返回值
  1. 不要用null來(lái)判斷函數(shù)調(diào)用時(shí)有無(wú)傳參

  2. 不要與未初始化的變量做比較

// not good
function test(a, b) {
  if (b === null) {
    // not mean b is not supply
    // ...
  }
}

let a;

if (a === null) {
  // ...
}

// good
let a = null;

if (a === null) {
  // ...
}

使用 undefined

【強(qiáng)制】正確使用 undefined

  1. 不要給變量賦值 undefined(undefined 本身就表示一個(gè)變量未定義)

  2. 不要直接使用 undefined 進(jìn)行變量判斷

  3. 使用typeof和字符串 'undefined' 對(duì)變量進(jìn)行判斷

// not good
if (person === undefined) {
  // ...
}

// good
if (typeof person === 'undefined') {
  // ...
}

文檔注釋
【參考】各類標(biāo)簽 @param, @method 等請(qǐng)參考 usejsdoc JSDoc Guide挂疆;

建議在以下情況下使用:

- 所有常量
- 所有函數(shù)
- 所有類
/**
 * @func
 * @desc 一個(gè)帶參數(shù)的函數(shù)
 * @param {string} a - 參數(shù)a
 * @param {number} b=1 - 參數(shù)b默認(rèn)值為1
 * @param {string} c=1 - 參數(shù)c有兩種支持的取值</br>1—表示x</br>2—表示xx
 * @param {object} d - 參數(shù)d為一個(gè)對(duì)象
 * @param {string} d.e - 參數(shù)d的e屬性
 * @param {string} d.f - 參數(shù)d的f屬性
 * @param {object[]} g - 參數(shù)g為一個(gè)對(duì)象數(shù)組
 * @param {string} g.h - 參數(shù)g數(shù)組中一項(xiàng)的h屬性
 * @param {string} g.i - 參數(shù)g數(shù)組中一項(xiàng)的i屬性
 * @param {string} [j] - 參數(shù)j是一個(gè)可選參數(shù)
 */
function foo(a, b, c, d, g, j) {
  // ...
}

4.4 Vue 組件編碼規(guī)范

命名

  1. 【強(qiáng)制】組件名應(yīng)該始終是多個(gè)單詞的改览,根組件App 除外
// not good
Vue.component('todo', {
  // ...
})
export default {
  name: 'Todo',
  // ...
}

// good
Vue.component('todo-item', {
  // ...
})
export default {
  name: 'TodoItem',
  // ...
}
  1. 【強(qiáng)制】單文件組件的文件名應(yīng)該要么始終是單詞大寫開(kāi)頭( PascalCase ),要么始終是橫線連接( kebab-case )
// not good
components/
|- mycomponent.vue

components/
|- myComponent.vue

// good
components/
|- MyComponent.vue

components/
|- my-component.vue
  1. 【推薦】應(yīng)用特定樣式和約定的基礎(chǔ)組件 (也就是展示類的缤言、無(wú)邏輯的或無(wú)狀態(tài)的組件) 應(yīng)該全部以一個(gè)特定的前綴開(kāi)頭宝当,比如 Base、App 或 V
// not good
components/
|- MyButton.vue
|- VueTable.vue
|- Icon.vue

// good
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue

components/
|- AppButton.vue
|- AppTable.vue
|- AppIcon.vue

components/
|- VButton.vue
|- VTable.vue
|- VIcon.vue
  1. 【推薦】只應(yīng)該擁有單個(gè)活躍實(shí)例的單例組件應(yīng)該以 The 前綴命名胆萧,以示其唯一性

單例組件不意味著組件只可用于一個(gè)單頁(yè)面庆揩,而是每個(gè)頁(yè)面只使用一次。這些組件永遠(yuǎn)不接受任何 prop跌穗,因?yàn)樗鼈兪菫槟愕膽?yīng)用定制的订晌,而不是它們?cè)谀愕膽?yīng)用中的上下文。如果你發(fā)現(xiàn)有必要添加 prop蚌吸,那就表明這實(shí)際上是一個(gè)可復(fù)用的組件锈拨,只是目前在每個(gè)頁(yè)面里只使用一次

// not good
components/
|- Heading.vue
|- MySidebar.vue

// good
components/
|- TheHeading.vue
|- TheSidebar.vue
  1. 【強(qiáng)制】和父組件緊密耦合的子組件應(yīng)該以父組件名作為前綴命名

如果一個(gè)組件只在某個(gè)父組件的場(chǎng)景下有意義,這層關(guān)系應(yīng)該體現(xiàn)在其名字上羹唠。因?yàn)榫庉嬈魍ǔ?huì)按字母順序組織文件奕枢,所以這樣做可以把相關(guān)聯(lián)的文件排在一起

// not good
components/
|- TodoList.vue
|- TodoItem.vue
|- TodoButton.vue
components/
|- SearchSidebar.vue
|- NavigationForSearchSidebar.vue

//good
components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue
components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue
  1. 【強(qiáng)制】組件名應(yīng)該以高級(jí)別的 (通常是一般化描述的) 單詞開(kāi)頭,以描述性的修飾詞結(jié)尾
// not good
components/
|- ClearSearchButton.vue
|- ExcludeFromSearchInput.vue
|- LaunchOnStartupCheckbox.vue
|- RunSearchButton.vue
|- SearchInput.vue
|- TermsCheckbox.vue

// good
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue
  1. 【推薦】組件名應(yīng)該傾向于完整單詞而不是縮寫
// not good
components/
|- SdSettings.vue
|- UProfOpts.vue

// good
components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue

語(yǔ)法

  1. 【強(qiáng)制】組件的data 必須是一個(gè)函數(shù)(除了 new Vue 外的任何地方)
// not good
export default {
  data: {
    foo: 'bar'
  }
}

// good
export default {
  data () {
    return {
      foo: 'bar'
    }
  }
}
  1. 【強(qiáng)制】prop 的定義應(yīng)該盡量詳細(xì)佩微,至少需要指定其類型
// not good
// 這樣做只有開(kāi)發(fā)原型系統(tǒng)時(shí)可以接受
props: ['status']

// good
props: {
  status: String
}

// better
props: {
  status: {
    type: String,
    required: true,
    validator: function (value) {
      return [
        'syncing',
        'synced',
        'version-conflict',
        'error'
      ].indexOf(value) !== -1
    }
  }
}
  1. 【強(qiáng)制】為 v-for 設(shè)置鍵值缝彬;在組件上總是必須用 key 配合 v-for,以便維護(hù)內(nèi)部組件及其子樹(shù)的狀態(tài)在組件上總是必須用key 配合 v-for哺眯,以便維護(hù)內(nèi)部組件及其子樹(shù)的狀態(tài)

4.【強(qiáng)制】不要把 v-ifv-for同時(shí)用在同一個(gè)元素上(大部分時(shí)候你可以使用計(jì)算屬性實(shí)現(xiàn))

<!-- not good -->
<ul>
  <li
    v-for="user in users"
    v-if="user.isActive"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

<!-- good -->
<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
  1. 【強(qiáng)制】自閉合組件在單文件組件谷浅、字符串模板和 JSX 中沒(méi)有內(nèi)容的組件應(yīng)該是自閉合的;但在 DOM 模板里不要這樣做
<!-- not good -->
<!-- 在單文件組件奶卓、字符串模板和 JSX 中 -->
<MyComponent></MyComponent>
<!-- 在 DOM 模板中 -->
<my-component/>

<!-- good -->
<!-- 在單文件組件壳贪、字符串模板和 JSX 中 -->
<MyComponent/>
<!-- 在 DOM 模板中 -->
<my-component></my-component>
  1. 【強(qiáng)制】模版中的組件名大小寫在單文件組件和字符串模板中組件名應(yīng)該總是 PascalCase 的;但是在 DOM 模板中總是 kebab-case 的
<!-- not good -->
<!-- 在單文件組件和字符串模板中 -->
<mycomponent/>
<!-- 在單文件組件和字符串模板中 -->
<myComponent/>
<!-- 在 DOM 模板中 -->
<MyComponent></MyComponent>

<!-- good -->
<!-- 在單文件組件和字符串模板中 -->
<MyComponent/>
<!-- 在 DOM 模板中 -->
<my-component></my-component>

亦或者

<!-- 在所有地方 -->
<my-component></my-component>
  1. 【強(qiáng)制】JS/JSX 中的組件名應(yīng)該始終是 PascalCase 的
// not good
Vue.component('myComponent', {
  // ...
})
import myComponent from './MyComponent.vue'
export default {
  name: 'myComponent',
  // ...
}
export default {
  name: 'my-component',
  // ...
}

// good
Vue.component('MyComponent', {
  // ...
})
import MyComponent from './MyComponent.vue'
export default {
  name: 'MyComponent',
  // ...
}
  1. 【推薦】Prop 名大小寫寝杖,在聲明 prop 的時(shí)候,其命名應(yīng)該始終使用 camelCase互纯,而在模板和 JSX 中應(yīng)該始終使用 kebab-case
// not good
props: {
  'greeting-text': String
}
<WelcomeMessage greetingText="hi"/>

// good
props: {
  greetingText: String
}
<WelcomeMessage greeting-text="hi"/>
  1. 【推薦】多個(gè)特性的元素應(yīng)該分多行撰寫瑟幕,每個(gè)特性一行(此項(xiàng) Vetur 插件會(huì)自動(dòng)根據(jù)行寬閾值進(jìn)行自動(dòng)折行處理,一般無(wú)需考慮)
<!-- not good -->
<img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
<MyComponent foo="a" bar="b" baz="c"/>

<!-- good -->
<img
  src="https://vuejs.org/images/logo.png"
  alt="Vue Logo"
>
<MyComponent
  foo="a"
  bar="b"
  baz="c"
/>
  1. 【強(qiáng)制】組件模板應(yīng)該只包含簡(jiǎn)單的表達(dá)式留潦,復(fù)雜的表達(dá)式則應(yīng)該重構(gòu)為計(jì)算屬性或方法
// not good
{{
  fullName.split(' ').map(function (word) {
    return word[0].toUpperCase() + word.slice(1)
  }).join(' ')
}}

// good
// 在模板中
{{ normalizedFullName }}
// 復(fù)雜表達(dá)式已經(jīng)移入一個(gè)計(jì)算屬性
computed: {
  normalizedFullName: function () {
    return this.fullName.split(' ').map(function (word) {
      return word[0].toUpperCase() + word.slice(1)
    }).join(' ')
  }
}
  1. 【推薦】應(yīng)該把復(fù)雜計(jì)算屬性分割為盡可能多的更簡(jiǎn)單的屬性
// not good
computed: {
  finalPrice: function () {
    var basePrice = this.manufactureCost / (1 - this.profitMargin)
    return (
      basePrice -
      basePrice * (this.discountPercent || 0)
    )
  }
}

// good
computed: {
  basePrice: function () {
    return this.manufactureCost / (1 - this.profitMargin)
  },
  discount: function () {
    return this.basePrice * (this.discountPercent || 0)
  },
  finalPrice: function () {
    return this.basePrice - this.discount
  }
}
  1. 【強(qiáng)制】非空 HTML 特性值應(yīng)該始終帶引號(hào)
<!-- not good -->
<input type=text>
<AppSidebar :style={width:sidebarWidth+'px'}>

<!-- good -->
<input type="text">
<AppSidebar :style="{ width: sidebarWidth + 'px' }">
  1. 【強(qiáng)制】可簡(jiǎn)寫指令需要縮寫 (用 : 表示 v-bind: 和用 @ 表示 v-on:)

代碼風(fēng)格

此處大部分工作將由代碼格式化工具完成(參見(jiàn)環(huán)境要求)狭姨,一般無(wú)需考慮
具體要求見(jiàn) 4.1 胁塞,4.2,4.3 中代碼風(fēng)格部分

組件/實(shí)例的選項(xiàng)的順序

【參考】組件/實(shí)例的選項(xiàng)應(yīng)該有統(tǒng)一的順序,這是我們推薦的組件選項(xiàng)默認(rèn)順序:

  1. 副作用 (觸發(fā)組件外的影響)
    • el
  2. 全局感知 (要求組件以外的知識(shí))
    • name
    • parent
  3. 組件類型 (更改組件的類型)
    • functional
  4. 模板修改器 (改變模板的編譯方式)
    • delimiters
    • comments
  5. 模板依賴 (模板內(nèi)使用的資源)
    • components
    • directives
    • filters
  6. 組合 (向選項(xiàng)里合并屬性)
    • extends
    • mixins
  7. 接口 (組件的接口)
    • inheritAttrs
    • model
    • props/propsData
  8. 本地狀態(tài) (本地的響應(yīng)式屬性)
    • data
    • computed
  9. 事件 (通過(guò)響應(yīng)式事件觸發(fā)的回調(diào))
    • watch
    • 生命周期鉤子 (按照它們被調(diào)用的順序)
      • beforeCreate
      • created
      • beforeMount
      • mounted
      • beforeUpdate
      • updated
      • activated
      • deactivated
      • beforeDestroy
      • destroyed
  10. 非響應(yīng)式的屬性 (不依賴響應(yīng)系統(tǒng)的實(shí)例屬性)
    • methods
  11. 渲染 (不依賴響應(yīng)系統(tǒng)的實(shí)例屬性)
    • template / render
    • renderError

元素特性的順序

【參考】元素 (包括組件) 的特性應(yīng)該有統(tǒng)一的順序色洞,這是我們?yōu)樵靥匦酝扑]的默認(rèn)順序

  1. 定義 (提供組件的選項(xiàng))
    • is
  2. 列表渲染 (創(chuàng)建多個(gè)變化的相同元素)
    • v-for
  3. **條件渲染 **(元素是否渲染/顯示)
    • v-if
    • v-else-if
    • v-else
    • v-show
    • v-cloak
  4. 渲染方式 (改變?cè)氐匿秩痉绞?
    • v-pre
    • v-once
  5. 全局感知 (需要超越組件的知識(shí))
    • id
  6. 唯一的特性 (需要唯一值的特性)
    • ref
    • key
    • slot
  7. 雙向綁定 (把綁定和事件結(jié)合起來(lái))
    • v-model
  8. 其它特性 (所有普通的綁定或未綁定的特性)
  9. 事件 (組件事件監(jiān)聽(tīng)器)
    • v-on
  10. 內(nèi)容 (覆寫元素的內(nèi)容)
    • v-html
    • v-text

單文件組件的頂級(jí)元素的順序

【強(qiáng)制】單文件組件應(yīng)該總是按照 <template><script><style> 的標(biāo)簽順序

<!-- good -->
<!-- ComponentA.vue -->
<template>...</template>
<style>/* ... */</style>

<!-- ComponentB.vue -->
<template>...</template>
<script>/* ... */</script>
<style>/* ... */</style>

隱性的父子組件通信

【強(qiáng)制】應(yīng)該優(yōu)先通過(guò) prop 和事件進(jìn)行父子組件之間的通信隶症,而不是 this.$parent 或改變 prop。

一個(gè)理想的 Vue 應(yīng)用是 prop 向下傳遞许起,事件向上傳遞的。遵循這一約定會(huì)讓你的組件更易于理解菩鲜。然而园细,在一些邊界情況下 prop 的變更或this.$parent 能夠簡(jiǎn)化兩個(gè)深度耦合的組件。
問(wèn)題在于接校,這種做法在很多簡(jiǎn)單的場(chǎng)景下可能會(huì)更方便猛频。但請(qǐng)當(dāng)心,不要為了一時(shí)方便 (少寫代碼) 而犧牲數(shù)據(jù)流向的簡(jiǎn)潔性 (易于理解)蛛勉。

非 Flux 的全局狀態(tài)管理
【強(qiáng)制】應(yīng)該優(yōu)先通過(guò) Vuex 管理全局狀態(tài)鹿寻,而不是通過(guò) this.$root 或一個(gè)全局事件總線。

通過(guò) this.$root 和/或全局事件總線管理狀態(tài)在很多簡(jiǎn)單的情況下都是很方便的诽凌,但是并不適用于絕大多數(shù)的應(yīng)用毡熏。Vuex 提供的不僅是一個(gè)管理狀態(tài)的中心區(qū)域,還是組織皿淋、追蹤和調(diào)試狀態(tài)變更的好工具招刹。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市窝趣,隨后出現(xiàn)的幾起案子疯暑,更是在濱河造成了極大的恐慌,老刑警劉巖哑舒,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妇拯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡洗鸵,警方通過(guò)查閱死者的電腦和手機(jī)越锈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)膘滨,“玉大人甘凭,你說(shuō)我怎么就攤上這事』鸬耍” “怎么了丹弱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)铲咨。 經(jīng)常有香客問(wèn)我躲胳,道長(zhǎng),這世上最難降的妖魔是什么纤勒? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任坯苹,我火速辦了婚禮,結(jié)果婚禮上摇天,老公的妹妹穿的比我還像新娘粹湃。我一直安慰自己恐仑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布再芋。 她就那樣靜靜地躺著菊霜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪济赎。 梳的紋絲不亂的頭發(fā)上鉴逞,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音司训,去河邊找鬼构捡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛壳猜,可吹牛的內(nèi)容都是我干的勾徽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼统扳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼喘帚!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起咒钟,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吹由,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后朱嘴,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體倾鲫,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年萍嬉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乌昔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡壤追,死狀恐怖磕道,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情行冰,我是刑警寧澤捅厂,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站资柔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏撵割。R本人自食惡果不足惜贿堰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望啡彬。 院中可真熱鬧羹与,春花似錦故硅、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至腾誉,卻和暖如春徘层,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背利职。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工趣效, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人猪贪。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓跷敬,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親热押。 傳聞我的和親對(duì)象是個(gè)殘疾皇子西傀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

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