JS學(xué)習(xí)9(DOM)

DOM禀忆,文檔對象模型,是一個針對HTML和XML文檔的一個API呀潭,它描繪了一個層次化的節(jié)點樹械蹋。值得注意的是IE中的所有DOM對象都是使用COM對象實現(xiàn)的,這就造成了IE中的DOM對象與原生JS對象表現(xiàn)并不一致绸硕。

節(jié)點層次

文檔節(jié)點是每個文檔的根節(jié)點堂竟。在html文檔中,文檔節(jié)點只有一個子節(jié)點即html元素玻佩。這個元素我們稱之為文檔元素出嘹,每個文檔只有一個文檔元素,其他所有元素都包含在文檔元素中咬崔。
節(jié)點分為幾種不同的類型税稼,每種類型分別表示文檔中不同的信息及標記。
比如:元素節(jié)點垮斯,特性節(jié)點郎仆,文檔節(jié)點,注釋節(jié)點等兜蠕∪偶。總共有12種節(jié)點類型,這些類型都繼承自一個基類型熊杨。

Node類型

這是DOM1級定義的一個接口曙旭,DOM中所有類型節(jié)點都會實現(xiàn)這個接口。在JS中作為Node類型實現(xiàn)晶府,所有節(jié)點類型皆繼承自Node類型夷狰。不過IE直接訪問不到Node。Node類型由下面12個常量表示:

  • 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)
var htmlNode = document.getElementsByTagName("html")[0];
//本來標準的寫法應(yīng)該是與Node.ELEMENT_NODE這個常量做比較郊霎,但是由于IE訪問不到Node這個類型沼头,所以只好直接比較
if (htmlNode.nodeType == 1){
    alert("Node is an element.");
    alert(htmlNode.nodeName);  //HTML
    alert(htmlNode.nodeValue);  //null
}

這里查找html元素時使用的方法返回的是一個NodeList對象,基本對node類型的查找和獲取都會涉及到這個對象书劝。這個對象是一個類數(shù)組對象进倍,許多使用方法都和數(shù)組是一樣的,但是它并不是Array類型的實例购对。其特別的地方在于它其實是基于DOM結(jié)構(gòu)動態(tài)執(zhí)行查詢的結(jié)果猾昆,DOM結(jié)構(gòu)的變化可以自動反應(yīng)在NodeList中。想將NodeList轉(zhuǎn)換為數(shù)組骡苞,可以使用Array.prototype.slice()方法垂蜗。

var bodyNode = document.getElementsByTagName("body")[0];
var childList = bodyNode.childNodes;
var childListArray = Array.prototype.slice.call(childList,0);
alert(childList.length);  //8
alert(childListArray.length);  //8
bodyNode.removeChild(bodyNode.lastChild);
alert(childList.length);  //7
alert(childListArray.length);  //8

節(jié)點關(guān)系
就是父元素與子元素咯楷扬。

bodyNode.childNodes;
bodyNode.parentNode;
bodyNode.previousSibling;
bodyNode.nextSibling;
bodyNode.firstChild;
bodyNode.lastChild;
bodyNode.hasChildNodes();
bodyNode.ownerDocument;

不是每種節(jié)點都有子節(jié)點哦,有的不能有子節(jié)點的贴见。
操作節(jié)點
appendChild()用于向childNodes列表結(jié)尾添加一個節(jié)點烘苹。如果傳入到這個方法中的節(jié)點已經(jīng)是文檔的一部分了,那么該節(jié)點就會被移動到新節(jié)點片部。任何DOM節(jié)點不能同時出現(xiàn)在多個位置镣衡。

//someNode 有多個節(jié)點 
var returnedNode = someNode.appendChild(someNode.firstChild); 
alert(returnedNode == someNode.firstChild); //false 
alert(returnedNode == someNode.lastChild); //true

insertBefore()

var returnedNode = someNode.insertBefore(newNode, someNode.firstChild); 
alert(returnedNode == newNode); //true
alert(newNode == someNode.firstChild); //true

replaceChild()
在替換的過程中,該節(jié)點的所有關(guān)系指針都會從被它替換的節(jié)點復(fù)制過來档悠,被替換的節(jié)點還在文檔中廊鸥,但是失去了自己的位置。

var returnedNode = someNode.replaceChild(newNode, someNode.firstChild);

removeChild()
同樣的辖所,被移除的節(jié)點還是歸文檔所有惰说,沒有位置了。

var formerFirstChild = someNode.removeChild(someNode.firstChild);

cloneNode()
這個方法接受一個布爾值表示是否進行深復(fù)制缘回,深復(fù)制就是復(fù)制節(jié)點及其子節(jié)點樹助被。要注意的是,復(fù)制后的節(jié)點沒有父節(jié)點切诀,是孤獨的節(jié)點揩环。。需要使用上面提到的方法添加幅虑。
normalize()
這個方法是處理文檔樹中的文本節(jié)點丰滑。

Document類型

document是window的一個屬性,是Document的實例倒庵。

  • nodeType:9
  • nodeName:"#document"
  • nodeValue:null
  • parentNode:null
  • ownerDocument:null
  • 其子節(jié)點可以是:DocumentType(最多一個)褒墨、Element(最多一個)、ProcessingInstruction擎宝、Comment

文檔的子節(jié)點

document.documentElement//指向html元素
document.body//指向body元素 
document.doctype;//指向<!DOCTYPE>

文檔信息

document.title = "New page title";
document.URL;
document.domain;
document.referrer;//來自哪個頁面的URL

其中只有title和domain是可寫的郁妈。
domain對寫入的值是有限制的,只能寫入當前域的父域绍申。

//來自p2p.wrox.com  
document.domain = "wrox.com";   //成功
document.domain = "nczonline.net"; //報錯
document.domain = "p2p.wrox.com "; //報錯

對于包含來自其他子域框架的頁面這個很有用噩咪,因為來自不同域的頁面不能通過JavaScript通信,所以通過將domain設(shè)置為同一個父域极阅,就可以實現(xiàn)互相訪問對方的JS對象胃碾。
查找元素

//這個返回一個元素
document.getElementById("myDiv");
//這個返回元素列表HTMLCollectioin
document.getElementsByTagName("img");
//找到name屬性符合的元素。這個返回元素列表HTMLCollectioin
document.getElementsByName("color");
var ul = document.getElementById("myList");
//可以直接在元素里查找
var items = ul.getElementsByTagName("li");

一些特殊集合:

document.anchors
document.applets
document.forms
document.images
document.links

DOM一致性檢測
用來檢測瀏覽器實現(xiàn)了DOM的哪些部分筋搏。DOM1提供了一個方法仆百。將要檢測的功能和版本號傳入。

var hasXmlDom = document.implementation.hasFeature("XML", "1.0");

不過這個方法并不保險奔脐,有的瀏覽器對沒實現(xiàn)的功能也返回true俄周,所以建議對不確定的直接進行能力檢測吁讨。
文檔寫入
將輸出流寫入到網(wǎng)頁中的功能。有4個方法:write()峦朗、writeln()建丧、open()、close()甚垦。

<html>
    <head>
        <title>document.write() Example 3</title>
    </head>
    <body>
        <script type="text/javascript">
            document.write("<strong>" + (new Date()).toString() + "</strong>");
        </script>
    </body>
</html>

在文檔加載過程中使用茶鹃,則會加載內(nèi)容到當前位置涣雕,在文檔加載結(jié)束后再執(zhí)行則會覆蓋掉整個文檔

Element類型

Element就是我們最常用的元素

  • nodeType:1
  • nodeName:元素的標簽名
  • nodeValue:null
  • parentNode:Document或Element
  • ownerDocument:Document
  • 其子節(jié)點可以是:Element艰亮、Text、Comment挣郭、ProcessingInstruction迄埃、CDATASection、EntityReference

HTML元素
所有HTML元素都是HTMLElement或其子類兑障。HTMLElement直接繼承自Element侄非。有這么幾個通用屬性:

//<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div>
var div = document.getElementById("myDiv");
alert(div.id); //"myDiv""
alert(div.className); //"bd"
alert(div.title); //"Body text"
alert(div.lang); //"en"
alert(div.dir); //"ltr"

取得特性
getAttribute()、setAttribute()流译、removeAttribute()

alert(div.getAttribute("id"));
alert(div.getAttribute("class"));
alert(div.getAttribute("title"));
alert(div.getAttribute("lang"));
alert(div.getAttribute("data_myOwnAttr"));
alert(div.data_myOwnAttr); //undefined(除IE)

要注意的是逞怨,只有公認的特性才能通過屬性名的方式來訪問,自定義的特性除IE外的瀏覽器不會為他們創(chuàng)建屬性福澡。
對于style這個屬性叠赦,直接訪問屬性得到的是一個對象,便于訪問各個樣式革砸;而getAttribute("style")則返回字符串除秀。
對于onclick這樣的事件處理特性,直接訪問屬性得到的是一個函數(shù)算利,getAttribute()則返回字符串册踩。
所以在訪問非自定義屬性時推薦使用直接訪問元素屬性的方法。
設(shè)置特性

div.setAttribute("id", "someOtherId");
div.id = "someOtherId";

同樣效拭,通過屬性來設(shè)置自定義特性是無效的暂吉。
刪除特性

div.removeAttribute("class");

attributes屬性
只有Element類型有這個屬性。這個屬性中包含一個NameNodeMap缎患。元素的每一個特性由一個Attr節(jié)點表示借笙,每個節(jié)點都保存在NameNodeMap對象中较锡。

//獲取特性
var id = element.attributes.getNamedItem("id").nodeValue;
var id = element.attributes["id"].nodeValue;
//修改特性
element.attributes["id"].nodeValue = "someOtherId";
var oldAttr = element.attributes.removeNamedItem("id");
element.attributes.setNamedItem(newAttr);

創(chuàng)建元素

var div = document.createElement("div");
div.id = "myNewDiv";
div.className = "box";
document.body.appendChild(div);
//在IE中也可以這樣
var div = document.createElement("<div id=\"myNewDiv\" class=\"box\"></div >");

遍歷子節(jié)點

<ul id="myList">
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
</ul>
<ul id="myList"><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>

對于上面的兩個ul元素childNodes包含的數(shù)目可能不同俯邓,IE外的瀏覽器對第一個會包含3個li和4個文本節(jié)點。如果你真的要遍歷朦蕴,你可以在遍歷的同時判斷下節(jié)點的類型。

Text類型

包含純文本內(nèi)容

  • nodeType:3
  • nodeName:"#text"
  • nodeValue:文本內(nèi)容
  • parentNode:Element
  • ownerDocument:Document
  • 無子節(jié)點
<div>Hello World!</div>
var textNode = div.firstChild;
//獲取或設(shè)置文本的值
div.firstChild.nodeValue = "Some other message";
div.firstChild.data = "Some other message";

創(chuàng)建文本節(jié)點

var element = document.createElement("div");
element.className = "message";
//這里的大于小于號之類的會被轉(zhuǎn)義伦连,不會被解釋為元素標簽
var textNode = document.createTextNode("<strong>Hello</strong> world!");
element.appendChild(textNode);
//多個相鄰文本節(jié)點會被拼接
var anotherTextNode = document.createTextNode("Yippee!");
element.appendChild(anotherTextNode);
document.body.appendChild(element);
//多個相鄰節(jié)點導(dǎo)致混亂
alert(element.childNodes.length);    //2
//這個方法合并相鄰文本節(jié)點
element.normalize();
alert(element.childNodes.length);    //1
alert(element.firstChild.nodeValue);

分割文本節(jié)點
被分割出來的新節(jié)點于原來的有相同的父節(jié)點额港。

var element = document.createElement("div");
element.className = "message";
var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);
document.body.appendChild(element);
var newNode = element.firstChild.splitText(5);

其他方法
appendData(text)
deleteData(offset, count)
insertData(offset, text)
replaceData(offset, count, text)
substringData(offset, count)
length
這些方法都是用來獲取或修改文本節(jié)點中的內(nèi)容的。

Comment類型

在DOM中的注釋通過這個類型來表示

  • nodeType:8
  • nodeName:"#comment"
  • nodeValue:注釋文本內(nèi)容
  • parentNode:Document或Element
  • ownerDocument:Document
  • 無子節(jié)點
  • 與text類型有相同的基類叹哭,所以上面的字符串方法它也有
<div id="myDiv"><!--A comment --></div>
var div = document.getElementById("myDiv");
var comment = div.firstChild;
alert(comment.data); 

CDATASection類型

DocumentType類型

DocumentFragment類型

這個類型在文檔中沒有對應(yīng)的標記,是一個輕量級的文檔,可以包含和控制節(jié)點。它不能被直接添加到文檔中盈滴,但是可以作為一個倉庫來使用,在里面保存將來會用到的節(jié)點。

  • nodeType:11
  • nodeName:"#document-fragment"
  • nodeValue:null
  • parentNode:null
  • ownerDocument:Document
  • 子節(jié)點可以是Element咬展、ProcessingInstruction瞒斩、Comment破婆、Text济瓢、CDATASection妹卿、EntityReference

Node的各種DOM節(jié)點操作方法文檔片段都繼承了。
文檔片段的一個使用場景就是當我們循環(huán)添加節(jié)點時夺克,如果直接將節(jié)點添加到文檔中箕宙,那么每次添加都會導(dǎo)致瀏覽器的重新渲染铺纽。如果我們先把要循環(huán)的節(jié)點添加到一個文檔片段中陷寝,拼好了再添加到文檔中呢,這個問題就解決了褐奥。

var fragment = document.createDocumentFragment();
var ul = document.getElementById("myList");
var li = null;
for (var i=0; i < 3; i++){
    li = document.createElement("li");
    li.appendChild(document.createTextNode("Item " + (i+1)));
    fragment.appendChild(li);
}
//當你將一個文檔片段添加到文檔中時,會把文檔片段中的所有節(jié)點添加至文檔的當前位置,而文檔片段本身永遠不會出現(xiàn)在文檔中
ul.appendChild(fragment);

Attr類型

元素的特性在DOM中以Attr類型來表示咖耘。從技術(shù)角度講,特性就是存在于元素的attributes中的節(jié)點撬码。盡管它們是節(jié)點儿倒,但不認為它們是DOM文檔樹的一部分。

var ul = document.getElementById("myList");
//特性節(jié)點不會出現(xiàn)在文檔樹中
alert(ul.childNodes.length);
alert(ul.attributes["class"].value);
//alert(ul.attributes["align"].value);會報錯
//添加特性節(jié)點
var attr = document.createAttribute("align");
attr.value = "left";
ul.setAttributeNode(attr);
alert(ul.attributes["align"].value);

一般只使用之前提到的getAttribute()呜笑、setAttribute()夫否、remveAttribute()方法找筝,很少直接引用特性節(jié)點。

DOM操作技術(shù)

動態(tài)腳本

指的是頁面加載時并不存在慷吊,但將來的某一時刻通過修改DOM動態(tài)添加的腳本袖裕。動態(tài)添加同樣有兩種方式,添加外部文件和行內(nèi)代碼溉瓶。
外部文件:

function loadScript(url){
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = url;
    document.body.appendChild(script);
}
loadScript("client.js");

腳本加載完成就可以使用了急鳄,但是這里我們并不能判斷是否加載完成了,需要借助一些事件來判斷堰酿。
行內(nèi)代碼:

function loadScriptString(code){
    var script = document.createElement("script");
    script.type = "text/javascript";
    try {
    //由于IE將script視作一個特殊的元素疾宏,不允許DOM訪問其子節(jié)點,這樣在IE中會報錯
        script.appendChild(document.createTextNode(code));
    } catch (ex){
    //直接設(shè)置text屬性有的瀏覽器不支持触创,但IE肯定支持
        script.text = code;
    }
    document.body.appendChild(script);
}
loadScriptString("function sayHi(){alert('hi');}");

動態(tài)樣式

外部文件:

function loadStyles(url){
    var link = document.createElement("link");
    link.rel = "stylesheet";
    link.type = "text/css";
    link.href = url;
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(link);
}
loadStyles("styles.css");

內(nèi)聯(lián)樣式:
IE同樣有BUG

function loadStyleString(css){
    var style = document.createElement("style");
    style.type = "text/css";
try{   
    style.appendChild(document.createTextNode(css));
    } catch (ex){
        style.styleSheet.cssText = css;
    }
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(style);
}
loadStyleString("body{background-color:red}");

操作表格

DOM為表格添加了一些屬性和方法坎藐,以便我們可以更好的操作表格。
table元素的:
caption
tBodies
tFoot
tHead
rows
createTHead()
createTFoot()
createCaption()
deleteTFoot()
deleteCaption()
deleteRow(pos)
insertRow(pos)
body元素的:
rows
deleteRow(pos)
insertRow(pos)
cells
deleteCell(pos)
insertCell(pos)

使用NodeList

NodeList以及其近親NamedNodeMap和HTMLCollection都是動態(tài)的哼绑,也就是說每當文檔發(fā)生變化時岩馍,對他們的查詢始終返回最新的信息。這也就導(dǎo)致了一些問題抖韩,

var divs = document.getElementsByTagName("div"),
    i,
    div;
for (i=0; i < divs.length; i++){
    div = document.createElement("div");
    document.body.appendChild(div);
}

在這段代碼中每次增加一個div節(jié)點蛀恩,divs中的元素也會同時增加一個,divs.length永遠會比當前的循環(huán)大茂浮。

// 這樣就不會有問題了
var divs = document.getElementsByTagName("div"),
    i,
    len,
    div;
var divtemp = divs;
for (i=0, len=divs.length; i < len; i++){
    div = document.createElement("div");
    document.body.appendChild(div);
}

這也提醒了我們双谆,使用nodeList要謹慎,因為每次使用都會引起一次查詢席揽。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末顽馋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子幌羞,更是在濱河造成了極大的恐慌寸谜,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件新翎,死亡現(xiàn)場離奇詭異程帕,居然都是意外死亡,警方通過查閱死者的電腦和手機地啰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門愁拭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人亏吝,你說我怎么就攤上這事岭埠。” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵惜论,是天一觀的道長许赃。 經(jīng)常有香客問我,道長馆类,這世上最難降的妖魔是什么混聊? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮乾巧,結(jié)果婚禮上句喜,老公的妹妹穿的比我還像新娘。我一直安慰自己沟于,他們只是感情好咳胃,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著旷太,像睡著了一般展懈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上供璧,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天存崖,我揣著相機與錄音,去河邊找鬼嗜傅。 笑死金句,一個胖子當著我的面吹牛檩赢,可吹牛的內(nèi)容都是我干的吕嘀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼贞瞒,長吁一口氣:“原來是場噩夢啊……” “哼偶房!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起军浆,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤棕洋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后乒融,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掰盘,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年赞季,在試婚紗的時候發(fā)現(xiàn)自己被綠了愧捕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡申钩,死狀恐怖次绘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤邮偎,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布管跺,位于F島的核電站,受9級特大地震影響禾进,放射性物質(zhì)發(fā)生泄漏豁跑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一泻云、第九天 我趴在偏房一處隱蔽的房頂上張望贩绕。 院中可真熱鬧,春花似錦壶愤、人聲如沸淑倾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽娇哆。三九已至,卻和暖如春勃救,著一層夾襖步出監(jiān)牢的瞬間碍讨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工蒙秒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留勃黍,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓晕讲,卻偏偏與公主長得像覆获,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瓢省,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

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

  • 本章內(nèi)容 理解包含不同層次節(jié)點的 DOM 使用不同的節(jié)點類型 克服瀏覽器兼容性問題及各種陷阱 DOM 是針對 HT...
    悶油瓶小張閱讀 638評論 0 1
  • 節(jié)點層次 DOM 可以將任何 HTML 和 XML 文檔描繪成一個由多層節(jié)點構(gòu)成的結(jié)構(gòu)弄息。節(jié)點分為幾種不同的類型,每...
    云之外閱讀 539評論 0 1
  • DOM(文檔對象模型)是針對 HTML 和 XML 文檔的一個 API勤婚。DOM 描繪了一個層次化的節(jié)點樹摹量,允許開發(fā)...
    劼哥stone閱讀 772評論 8 6
  • 在雞湯還是雞湯的時候缨称,它只有大補這一項功能。 內(nèi)陸姑娘內(nèi)心OS是這樣的:雞湯能補什么啊祝迂,姑娘我想吃鮑魚好嗎睦尽。 于是...
    檸檬七閱讀 177評論 0 2
  • 高中時,曾認真的不止一遍讀過錢鐘書先生的《圍城》液兽,經(jīng)過歲月的歷練沉淀骂删,反復(fù)的品味實踐掌动,愈感覺:圍城無處不在!婚姻宁玫、...
    突刺閱讀 238評論 0 1