Javascript操作DOM常用API總結(jié)

概述:

DOM 是 JavaScript 操作網(wǎng)頁的接口,全稱為“文檔對象模型”(Document Object Model)蜓洪。它的作用是將網(wǎng)頁轉(zhuǎn)為一個 JavaScript 對象,從而可以用腳本進行各種操作(比如增刪內(nèi)容)赋朦。



Node類型

DOM1級定義了一個Node接口拧略,該接口由DOM中所有節(jié)點類型實現(xiàn)芦岂。這個Node接口在JS中是作為Node類型實現(xiàn)的。在IE9以下版本無法訪問到這個類型垫蛆,JS中所有節(jié)點都繼承自Node類型禽最,都共享著相同的基本屬性和方法。

Node有一個屬性nodeType表示Node的類型袱饭,它是一個整數(shù)川无,其數(shù)值分別表示相應(yīng)的Node類型,具體如下:

Node.ELEMENT_NODE:1

Node.ATTRIBUTE_NODE:2

Node.TEXT_NODE:3

Node.CDATA_SECTION_NODE:4

Node.ENTITY_REFERENCE_NODE:5

Node.ENTITY_NODE:6

Node.PROCESSING_INSTRUCTION_NODE:7

Node.COMMENT_NODE:8

Node.DOCUMENT_NODE:9

Node.DOCUMENT_TYPE_NODE:10

Node.DOCUMENT_FRAGMENT_NODE:11

Node.NOTATION_NODE:12

假設(shè)我們要判斷一個Node是不是元素舀透,我們可以這樣判斷:


這些Node類型中,我們最常用的就是element走贪,text坠狡,attribute继找,comment幻锁,document哄尔,document_fragment這幾種類型。

我們簡單來介紹一下這幾種類型:

Element類型

Element提供了對元素標(biāo)簽名,子節(jié)點和特性的訪問,我們常用HTML元素比如div入偷,span,a等標(biāo)簽就是element中的一種体捏。Element有下面幾條特性:

(1)nodeType為1

(2)nodeName為元素標(biāo)簽名沃呢,tagName也是返回標(biāo)簽名

(3)nodeValue為null

(4)parentNode可能是Document或Element

(5)子節(jié)點可能是Element某抓,Text,Comment备禀,Processing_Instruction赋续,CDATASection或EntityReference

Text類型

Text表示文本節(jié)點柴淘,它包含的是純文本內(nèi)容敛熬,不能包含html代碼,但可以包含轉(zhuǎn)義后的html代碼。Text有下面的特性:

(1)nodeType為3

(2)nodeName為#text

(3)nodeValue為文本內(nèi)容

(4)parentNode是一個Element

(5)沒有子節(jié)點

Attr類型

Attr類型表示元素的特性归园,相當(dāng)于元素的attributes屬性中的節(jié)點晤揣,它有下面的特性:

(1)nodeType值為2

(2)nodeName是特性的名稱

(3)nodeValue是特性的值

(4)parentNode為null

Comment類型

Comment表示HTML文檔中的注釋钠四,它有下面的幾種特征:

(1)nodeType為8

(2)nodeName為#comment

(3)nodeValue為注釋的內(nèi)容

(4)parentNode可能是Document或Element

(5)沒有子節(jié)點

Document

Document表示文檔,在瀏覽器中,document對象是HTMLDocument的一個實例,表示整個頁面处嫌,它同時也是window對象的一個屬性。Document有下面的特性:

(1)nodeType為9

(2)nodeName為#document

(3)nodeValue為null

(4)parentNode為null

(5)子節(jié)點可能是一個DocumentType或Element

DocumentFragment類型

DocumentFragment是所有節(jié)點中唯一一個沒有對應(yīng)標(biāo)記的類型,它表示一種輕量級的文檔,可能當(dāng)作一個臨時的倉庫用來保存可能會添加到文檔中的節(jié)點骗卜。DocumentFragment有下面的特性:

(1)nodeType為11

(2)nodeName為#document-fragment

(3)nodeValue為null

(4)parentNode為null

我們簡單地介紹了幾種常見的Node類型烤宙,要記住服猪,HTML中的節(jié)點并不只是包括元素節(jié)點,它還包括文本節(jié)點,注釋節(jié)點等等。在這里我們只是簡單地說明了幾種常見的節(jié)點恬砂,想要進一步學(xué)習(xí)的同學(xué)可以查找一下相關(guān)資料。


節(jié)點創(chuàng)建型api

在這里演痒,我將常用的DOM操作api進行分類器虾,首先要介紹的是創(chuàng)建型的api欧芽。這一類型的api,簡而言之就是用來創(chuàng)建節(jié)點的。

createElement

createElement通過傳入指定的一個標(biāo)簽名來創(chuàng)建一個元素,如果傳入的標(biāo)簽名是一個未知的,則會創(chuàng)建一個自定義的標(biāo)簽护昧,注意:IE8以下瀏覽器不支持自定義標(biāo)簽熊昌。

使用如下:


使用createElement要注意:通過createElement創(chuàng)建的元素并不屬于html文檔,它只是創(chuàng)建出來铁坎,并未添加到html文檔中傀顾,要調(diào)用appendChild或insertBefore等方法將其添加到HTML文檔樹中。

createTextNode

createTextNode用來創(chuàng)建一個文本節(jié)點,用法如下:


createTextNode接收一個參數(shù)咐汞,這個參數(shù)就是文本節(jié)點中的文本几晤,和createElement一樣,創(chuàng)建后的文本節(jié)點也只是獨立的一個節(jié)點,同樣需要appendChild將其添加到HTML文檔樹中

cloneNode

cloneNode是用來返回調(diào)用方法的節(jié)點的一個副本,它接收一個bool參數(shù),用來表示是否復(fù)制子元素,使用如下:


這段代碼通過cloneNode復(fù)制了一份parent元素炮姨,其中cloneNode的參數(shù)為true芦圾,表示parent的子節(jié)點也被復(fù)制洪乍,如果傳入false茫经,則表示只復(fù)制了parent節(jié)點。

例如:


這段代碼很簡單,主要是綁定button事件,事件內(nèi)容是復(fù)制了一個parent,修改其id,然后添加到文檔中鹃共。

這里有幾點要注意:

(1)和createElement一樣蓝纲,cloneNode創(chuàng)建的節(jié)點只是游離有html文檔外的節(jié)點锹漱,要調(diào)用appendChild方法才能添加到文檔樹中

(2)如果復(fù)制的元素有id,則其副本同樣會包含該id,由于id具有唯一性坎弯,所以在復(fù)制節(jié)點后必須要修改其id

(3)調(diào)用接收的bool參數(shù)最好傳入,如果不傳入該參數(shù),不同瀏覽器對其默認值的處理可能不同

除此之外,我們還有一個需要注意的點:

如果被復(fù)制的節(jié)點綁定了事件,則副本也會跟著綁定該事件嗎?這里要分情況討論:

(1)如果是通過addEventListener或者比如onclick進行綁定事件,則副本節(jié)點不會綁定該事件

(2)如果是內(nèi)聯(lián)方式綁定比如


這樣的話,副本節(jié)點同樣會觸發(fā)事件谦趣。

createDocumentFragment

createDocumentFragment方法用來創(chuàng)建一個DocumentFragment峭梳。在前面我們說到DocumentFragment表示一種輕量級的文檔,它的作用主要是存儲臨時的節(jié)點用來準(zhǔn)備添加到文檔中。

createDocumentFragment方法主要是用于添加大量節(jié)點到文檔中時會使用到。假設(shè)要循環(huán)一組數(shù)據(jù),然后創(chuàng)建多個節(jié)點添加到文檔中,比如示例:


這段代碼將按鈕綁定了一個事件咐熙,這個事件創(chuàng)建了100個li節(jié)點,然后依次將其添加HTML文檔中。這樣做有一個缺點:每次一創(chuàng)建一個新的元素,然后添加到文檔樹中土陪,這個過程會造成瀏覽器的回流。所謂回流簡單說就是指元素大小和位置會被重新計算鸦做,如果添加的元素太多,會造成性能問題却音。這個時候,就是使用createDocumentFragment了矢炼。

DocumentFragment不是文檔樹的一部分,它是保存在內(nèi)存中的阿纤,所以不會造成回流問題。我們修改上面的代碼如下:


優(yōu)化后的代碼主要是創(chuàng)建了一個fragment欠拾,每次生成的li節(jié)點先添加到fragment胰锌,最后一次性添加到list,大家可以看示例藐窄。

創(chuàng)建型API總結(jié)

創(chuàng)建型api主要包括createElement资昧,createTextNode,cloneNode和createDocumentFragment四個方法荆忍,需要注意下面幾點:

(1)它們創(chuàng)建的節(jié)點只是一個孤立的節(jié)點格带,要通過appendChild添加到文檔中

(2)cloneNode要注意如果被復(fù)制的節(jié)點是否包含子節(jié)點以及事件綁定等問題

(3)使用createDocumentFragment來解決添加大量節(jié)點時的性能問題




頁面修改型API

前面我們提到創(chuàng)建型api,它們只是創(chuàng)建節(jié)點刹枉,并沒有真正修改到頁面內(nèi)容叽唱,而是要調(diào)用appendChild來將其添加到文檔樹中。我在這里將這類會修改到頁面內(nèi)容歸為一類微宝。

修改頁面內(nèi)容的api主要包括:appendChild棺亭,insertBefore,removeChild蟋软,replaceChild镶摘。

appendChild

appendChild我們在前面已經(jīng)用到多次嗽桩,就是將指定的節(jié)點添加到調(diào)用該方法的節(jié)點的子元素的末尾。調(diào)用方法如下:


child節(jié)點將會作為parent節(jié)點的最后一個子節(jié)點凄敢。

appendChild這個方法很簡單碌冶,但是還有有一點需要注意:如果被添加的節(jié)點是一個頁面中存在的節(jié)點,則執(zhí)行后這個節(jié)點將會添加到指定位置贡未,其原本所在的位置將移除該節(jié)點种樱,也就是說不會同時存在兩個該節(jié)點在頁面上,相當(dāng)于把這個節(jié)點移動到另一個地方俊卤。我們來看例子:


這段代碼主要是獲取頁面上的child節(jié)點嫩挤,然后添加到指定位置,可以看到原本的child節(jié)點被移動到parent中了消恍。

這里還有一個要注意的點:如果child綁定了事件岂昭,被移動時,它依然綁定著該事件狠怨。

insertBefore

insertBefore用來添加一個節(jié)點到一個參照節(jié)點之前约啊,用法如下:


parentNode表示新節(jié)點被添加后的父節(jié)點

newNode表示要添加的節(jié)點

refNode表示參照節(jié)點,新節(jié)點會添加到這個節(jié)點之前

我們來看這個例子:


這段代碼創(chuàng)建了一個新節(jié)點佣赖,然后添加到child節(jié)點之前恰矩。

和appendChild一樣,如果插入的節(jié)點是頁面上的節(jié)點憎蛤,則會移動該節(jié)點到指定位置外傅,并且保留其綁定的事件。

關(guān)于第二個參數(shù)參照節(jié)點還有幾個注意的地方:

(1)refNode是必傳的俩檬,如果不傳該參數(shù)會報錯

(2)如果refNode是undefined或null萎胰,則insertBefore會將節(jié)點添加到子元素的末尾

removeChild

removeChild顧名思義,就是刪除指定的子節(jié)點并返回棚辽,用法如下:


deletedChild指向被刪除節(jié)點的引用技竟,它等于node,被刪除的節(jié)點仍然存在于內(nèi)存中屈藐,可以對其進行下一步操作榔组。

注意:如果被刪除的節(jié)點不是其子節(jié)點,則程序?qū)箦e联逻。我們可以通過下面的方式來確贝苫迹可以刪除:


通過節(jié)點自己獲取節(jié)點的父節(jié)點,然后將自身刪除遣妥。

replaceChild

replaceChild用于使用一個節(jié)點替換另一個節(jié)點擅编,用法如下


newChild是替換的節(jié)點,可以是新的節(jié)點,也可以是頁面上的節(jié)點爱态,如果是頁面上的節(jié)點谭贪,則其將被轉(zhuǎn)移到新的位置

oldChild是被替換的節(jié)點



頁面修改型API總結(jié)

頁面修改型api主要是這四個接口,要注意幾個特點:

(1)不管是新增還是替換節(jié)點锦担,如果新增或替換的節(jié)點是原本存在頁面上的俭识,則其原來位置的節(jié)點將被移除,也就是說同一個節(jié)點不能存在于頁面的多個位置

(2)節(jié)點本身綁定的事件會不會消失洞渔,會一直保留著套媚。

節(jié)點查詢型API

節(jié)點查詢型API也是非常常用的api,下面我們分別說明一下每一個api的使用磁椒。

document.getElementById

這個接口很簡單堤瘤,根據(jù)元素id返回元素,返回值是Element類型浆熔,如果不存在該元素本辐,則返回null。

使用這個接口有幾點要注意:

(1)元素的Id是大小寫敏感的医增,一定要寫對元素的id

(2)HTML文檔中可能存在多個id相同的元素慎皱,則返回第一個元素

(3)只從文檔中進行搜索元素,如果創(chuàng)建了一個元素并指定id叶骨,但并沒有添加到文檔中茫多,則這個元素是不會被查找到的

document.getElementsByTagName

這個接口根據(jù)元素標(biāo)簽名獲取元素,返回一個即時的HTMLCollection類型忽刽,什么是即時的HTMLCollection類型呢天揖?我們來看看這個示例:


這段代碼中有兩個按鈕,一個按鈕是顯示HTMLCollection元素的個數(shù)缔恳,另一個按鈕可以新增一個div標(biāo)簽到文檔中。前面提到HTMLCollcetion元素是即時的表示該集合是隨時變化的洁闰,也就是是文檔中有幾個div歉甚,它會隨時進行變化,當(dāng)我們新增一個div后扑眉,再訪問HTMLCollection時纸泄,就會包含這個新增的div。

使用document.getElementsByTagName這個方法有幾點要注意:

(1)如果要對HTMLCollection集合進行循環(huán)操作腰素,最好將其長度緩存起來聘裁,因為每次循環(huán)都會去計算長度,暫時緩存起來可以提高效率

(2)如果沒有存在指定的標(biāo)簽弓千,該接口返回的不是null衡便,而是一個空的HTMLCollection

(3)“*”表示所有標(biāo)簽

document.getElementsByName

getElementsByName主要是通過指定的name屬性來獲取元素,它返回一個即時的NodeList對象。

使用這個接口主要要注意幾點:

(1)返回對象是一個即時的NodeList镣陕,它是隨時變化的

(2)在HTML元素中谴餐,并不是所有元素都有name屬性,比如div是沒有name屬性的呆抑,但是如果強制設(shè)置div的name屬性岂嗓,它也是可以被查找到的

(3)在IE中,如果id設(shè)置成某個值鹊碍,然后傳入getElementsByName的參數(shù)值和id值一樣厌殉,則這個元素是會被找到的,所以最好不好設(shè)置同樣的值給id和name

document.getElementsByClassName

這個API是根據(jù)元素的class返回一個即時的HTMLCollection侈咕,用法如下:


這個接口有下面幾點要注意:

(1)返回結(jié)果是一個即時的HTMLCollection瞬沦,會隨時根據(jù)文檔結(jié)構(gòu)變化

(2)IE9以下瀏覽器不支持

(3)如果要獲取2個以上classname浮声,可傳入多個classname,每個用空格相隔,例如



document.querySelector和document.querySelectorAll

這兩個api很相似鸽疾,通過css選擇器來查找元素,注意選擇器要符合CSS選擇器的規(guī)則蹈集。

首先來介紹一下document.querySelector闺兢。

document.querySelector返回第一個匹配的元素,如果沒有匹配的元素帽揪,則返回null硝清。

注意,由于返回的是第一個匹配的元素转晰,這個api使用的深度優(yōu)先搜索來獲取元素芦拿。我們來看這個例子:


這個例子很簡單,就是兩個class都包含“test”的元素查邢,一個在文檔樹的前面蔗崎,但是它在第三級,另一個在文檔樹的后面扰藕,但它在第一級缓苛,通過querySelector獲取元素時,它通過深度優(yōu)先搜索邓深,拿到文檔樹前面的第三級的元素未桥。

document.querySelectorAll的不同之處在于它返回的是所有匹配的元素,而且可以匹配多個選擇符芥备,我們來看看下面這個例子:


這段代碼通過querySelectorAll冬耿,使用id選擇器和class選擇器選擇了兩個元素,并依次輸出其內(nèi)容萌壳。要注意兩點:

(1)querySelectorAll也是通過深度優(yōu)先搜索亦镶,搜索的元素順序和選擇器的順序無關(guān)

(2)返回的是一個非即時的NodeList日月,也就是說結(jié)果不會隨著文檔樹的變化而變化

兼容性問題:querySelector和querySelectorAll在ie8以下的瀏覽器不支持。



節(jié)點關(guān)系型api

在html文檔中的每個節(jié)點之間的關(guān)系都可以看成是家譜關(guān)系染乌,包含父子關(guān)系山孔,兄弟關(guān)系等等,下面我們依次來看看每一種關(guān)系荷憋。

父關(guān)系型api

parentNode:每個節(jié)點都有一個parentNode屬性台颠,它表示元素的父節(jié)點。Element的父節(jié)點可能是Element勒庄,Document或DocumentFragment串前。

parentElement:返回元素的父元素節(jié)點,與parentNode的區(qū)別在于实蔽,其父節(jié)點必須是一個Element荡碾,如果不是,則返回null

兄弟關(guān)系型api

previousSibling:節(jié)點的前一個節(jié)點局装,如果該節(jié)點是第一個節(jié)點坛吁,則為null。注意有可能拿到的節(jié)點是文本節(jié)點或注釋節(jié)點铐尚,與預(yù)期的不符拨脉,要進行處理一下。

previousElementSibling:返回前一個元素節(jié)點宣增,前一個節(jié)點必須是Element玫膀,注意IE9以下瀏覽器不支持。

nextSibling:節(jié)點的后一個節(jié)點爹脾,如果該節(jié)點是最后一個節(jié)點帖旨,則為null。注意有可能拿到的節(jié)點是文本節(jié)點灵妨,與預(yù)期的不符解阅,要進行處理一下。

nextElementSibling:返回后一個元素節(jié)點泌霍,后一個節(jié)點必須是Element货抄,注意IE9以下瀏覽器不支持。

子關(guān)系型api

childNodes:返回一個即時的NodeList烹吵,表示元素的子節(jié)點列表碉熄,子節(jié)點可能會包含文本節(jié)點桨武,注釋節(jié)點等肋拔。

children:一個即時的HTMLCollection,子節(jié)點都是Element呀酸,IE9以下瀏覽器不支持凉蜂。

firstNode:第一個子節(jié)點

lastNode:最后一個子節(jié)點

hasChildNodes方法:可以用來判斷是否包含子節(jié)點。

元素屬性型api

setAttribute

setAttribute:根據(jù)名稱和值修改元素的特性,用法如下:


其中name是特性名窿吩,value是特性值茎杂。如果元素不包含該特性,則會創(chuàng)建該特性并賦值纫雁。

如果元素本身包含指定的特性名為屬性煌往,則可以世界訪問屬性進行賦值,比如下面兩條代碼是等價的:



getAttribute

getAttribute返回指定的特性名相應(yīng)的特性值轧邪,如果不存在刽脖,則返回null或空字符串。用法如下:



元素樣式型api

window.getComputedStyle

window.getComputedStyle是用來獲取應(yīng)用到元素后的樣式忌愚,假設(shè)某個元素并未設(shè)置高度而是通過其內(nèi)容將其高度撐開曲管,這時候要獲取它的高度就要用到getComputedStyle,用法如下:


element是要獲取的元素硕糊,pseudoElt指定一個偽元素進行匹配院水。

返回的style是一個CSSStyleDeclaration對象。

通過style可以訪問到元素計算后的樣式

getBoundingClientRect

getBoundingClientRect用來返回元素的大小以及相對于瀏覽器可視窗口的位置简十,用法如下:


clientRect是一個DOMRect對象檬某,包含left,top勺远,right橙喘,bottom,它是相對于可視窗口的距離胶逢,滾動位置發(fā)生改變時厅瞎,它們的值是會發(fā)生變化的。除了IE9以下瀏覽器初坠,還包含元素的height和width等數(shù)據(jù)和簸,具體可查看MDN。

參考鏈接:http://luopq.com/2015/11/30/javascript-dom/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碟刺,一起剝皮案震驚了整個濱河市锁保,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌半沽,老刑警劉巖爽柒,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異者填,居然都是意外死亡浩村,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門占哟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來心墅,“玉大人酿矢,你說我怎么就攤上這事≡踉铮” “怎么了瘫筐?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铐姚。 經(jīng)常有香客問我策肝,道長,這世上最難降的妖魔是什么隐绵? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任驳糯,我火速辦了婚禮,結(jié)果婚禮上氢橙,老公的妹妹穿的比我還像新娘酝枢。我一直安慰自己,他們只是感情好悍手,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布帘睦。 她就那樣靜靜地躺著,像睡著了一般坦康。 火紅的嫁衣襯著肌膚如雪竣付。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天滞欠,我揣著相機與錄音古胆,去河邊找鬼。 笑死筛璧,一個胖子當(dāng)著我的面吹牛逸绎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播夭谤,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼棺牧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了朗儒?” 一聲冷哼從身側(cè)響起颊乘,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎醉锄,沒想到半個月后乏悄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡恳不,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年檩小,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妆够。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡识啦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出神妹,到底是詐尸還是另有隱情颓哮,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布鸵荠,位于F島的核電站冕茅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蛹找。R本人自食惡果不足惜姨伤,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望庸疾。 院中可真熱鬧乍楚,春花似錦、人聲如沸届慈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽金顿。三九已至臊泌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間揍拆,已是汗流浹背渠概。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嫂拴,地道東北人播揪。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像筒狠,于是被迫代替她去往敵國和親剪芍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355