JavaScript 是如何工作:Shadow DOM 的內(nèi)部結(jié)構(gòu) + 如何編寫?yīng)毩⒌慕M件!

摘要: 深入JS系列17涎跨。

Fundebug經(jīng)授權(quán)轉(zhuǎn)載崭歧,版權(quán)歸原作者所有隅很。

這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第 17 篇。

如果你錯(cuò)過了前面的章節(jié)率碾,可以在這里找到它們:

image

概述

Web Components 是一套不同的技術(shù),允許你創(chuàng)建可重用的定制元素矮湘,它們的功能封裝在你的代碼之外斟冕,你可以在 Web 應(yīng)用中使用它們。

Web組件由四部分組成:

  • Shadow DOM(影子DOM)
  • HTML templates(HTML模板)
  • Custom elements(自定義元素)
  • HTML Imports(HTML導(dǎo)入)

在本文中主要講解 Shadow DOM(影子DOM)

Shadow DOM 這款工具旨在構(gòu)建基于組件的應(yīng)用缅阳。因此磕蛇,可為網(wǎng)絡(luò)開發(fā)中的常見問題提供解決方案:

  • 隔離 DOM:組件的 DOM 是獨(dú)立的(例如,document.querySelector() 不會(huì)返回組件 shadow DOM 中的節(jié)點(diǎn))十办。
  • 作用域 CSS:shadow DOM 內(nèi)部定義的 CSS 在其作用域內(nèi)秀撇。樣式規(guī)則不會(huì)泄漏,頁面樣式也不會(huì)滲入向族。
  • 組合:為組件設(shè)計(jì)一個(gè)聲明性呵燕、基于標(biāo)記的 API。
  • 簡化 CSS - 作用域 DOM 意味著您可以使用簡單的 CSS 選擇器件相,更通用的 id/類名稱再扭,而無需擔(dān)心命名沖突。

Shadow DOM

本文假設(shè)你已經(jīng)熟悉 DOM 及其它的 Api 的概念夜矗。如果不熟悉泛范,可以在這里閱讀關(guān)于它的詳細(xì)文章—— https://developer.mozilla.org...

陰影 DOM 只是一個(gè)普通的 DOM紊撕,除了兩個(gè)區(qū)別:

  • 創(chuàng)建/使用的方式

  • 與頁面其他部分有關(guān)的行為方式

    通常罢荡,你創(chuàng)建 DOM 節(jié)點(diǎn)并將其附加至其他元素作為子項(xiàng)。 借助于 shadow DOM,您可以創(chuàng)建作用域 DOM 樹柠傍,該 DOM 樹附加至該元素上麸俘,但與其自身真正的子項(xiàng)分離開來。這一作用域子樹稱為影子樹惧笛。被附著的元素稱為影子宿主从媚。 您在影子中添加的任何項(xiàng)均將成為宿主元素的本地項(xiàng),包括 <style>患整。 這就是 shadow DOM 實(shí)現(xiàn) CSS 樣式作用域的方式

通常拜效,創(chuàng)建 DOM 節(jié)點(diǎn)并將它們作為子元素追加到另一個(gè)元素中。借助于 shadow DOM各谚,創(chuàng)建一個(gè)作用域 DOM 樹紧憾,附該 DOM 樹附加到元素上,但它與實(shí)際的子元素是分離的昌渤。這個(gè)作用域的子樹稱為 影子樹赴穗,被附著的元素稱為影子宿主。向影子樹添加的任何內(nèi)容都將成為宿主元素的本地元素膀息,包括 <style>般眉,這就是 影子DOM 實(shí)現(xiàn) CSS 樣式作用域的方式。

創(chuàng)建 shadow DOM

影子根是附加到“宿主”元素的文檔片段潜支,元素通過附加影子根來獲取其 shadow DOM甸赃。要為元素創(chuàng)建陰影 DOM,調(diào)用 element.attachShadow() :

var header = document.createElement('header');
var shadowRoot = header.attachShadow({mode: 'open'});
var paragraphElement = document.createElement('p');

paragraphElement.innerText = 'Shadow DOM';
shadowRoot.appendChild(paragraphElement);

規(guī)范定義了元素列表冗酿,這些元素?zé)o法托管影子樹埠对,元素之所以在所選之列,其原因如下:

  • 瀏覽器已為該元素托管其自身的內(nèi)部 shadow DOM(<textarea>裁替、<input>)项玛。
  • 讓元素托管 shadow DOM 毫無意義 (<img>)。

例如弱判,以下方法行不通:

document.createElement('input').attachShadow({mode: 'open'});
// Error. `<input>` cannot host shadow dom.

Light DOM

這是組件用戶寫入的標(biāo)記稍计。該 DOM 不在組件 shadow DOM 之內(nèi),它是元素的實(shí)際孩子裕循。假設(shè)已經(jīng)創(chuàng)建了一個(gè)名為<extended-button> 的定制組件臣嚣,它擴(kuò)展了原生 HTML 按鈕組件,此時(shí)希望在其中添加圖像和一些文本剥哑。代碼如下:

<extended-button>
  <!--?the image and span are extended-button's light DOM -->
  <img src="boot.png" slot="image">
  <span>Launch</span>
</extended-button>

“extension -button” 是定義的定制組件硅则,其中的 HTML 稱為 Light DOM,該組件由用戶自己添加株婴。

這里的 Shadow DOM 是你創(chuàng)建的組件 extension-button怎虫。Shadow DOM是 組件的本地組件暑认,它定義了組件的內(nèi)部結(jié)構(gòu)、作用域 CSS 和 封裝實(shí)現(xiàn)細(xì)節(jié)大审。

扁平 DOM 樹

瀏覽器將用戶創(chuàng)建的 Light DOM 分發(fā)到 Shadow DOM蘸际,并對(duì)最終產(chǎn)品進(jìn)行渲染。扁平樹是最終在 DevTools 中看到的以及頁面上呈渲染的對(duì)象徒扶。

<extended-button>
  #shadow-root
  <style>…</style>
  <slot name="image">
    <img src="boot.png" slot="image">
  </slot>
  <span id="container">
    <slot>
      <span>Launch</span>
    </slot>
  </span>
</extended-button>

模板 (Templates)

如果需要 Web 頁面上重復(fù)使用相同的標(biāo)簽結(jié)構(gòu)時(shí)粮彤,最好使用某種類型的模板,而不是一遍又一遍地重復(fù)相同的結(jié)構(gòu)姜骡。這在以前也是可以實(shí)現(xiàn)导坟,但是 HTML <template> 元素(在現(xiàn)代瀏覽器中得到了很好的支持)使它變得容易得多。此元素及其內(nèi)容不在 DOM 中渲染圈澈,但可以使用 JavaScript 引用它惫周。

一個(gè)簡單的例子:

<template id="my-paragraph">
  <p> Paragraph content. </p>
</template>

這不會(huì)出現(xiàn)在頁面中,直到使用 JavaScrip t引用它康栈,然后使用如下方式將其追加到 DOM 中:

var template = document.getElementById('my-paragraph');
var templateContent = template.content;
document.body.appendChild(templateContent);

到目前為止递递,已經(jīng)有其他技術(shù)可以實(shí)現(xiàn)類似的行為,但是啥么,正如前面提到的登舞,將其原生封裝起來是非常好的,Templates 也有相當(dāng)不錯(cuò)的瀏覽器支持:

image

模板本身是有用的饥臂,但它們與自定義元素配合會(huì)更好。 可以 customElement Api 能定義一個(gè)自定義元素似踱,并且告知 HTML 解析器如何正確地構(gòu)造一個(gè)元素隅熙,以及在該元素的屬性變化時(shí)執(zhí)行相應(yīng)的處理。

讓我們定義一個(gè) Web 組件名為 <my-paragraph>核芽,該組件使用之前模板作為它的 Shadow DOM 的內(nèi)容:

customElements.define('my-paragraph',
 class extends HTMLElement {
   constructor() {
     super();

     let template = document.getElementById('my-paragraph');
     let templateContent = template.content;
     const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(templateContent.cloneNode(true));
  }
});

這里需要注意的關(guān)鍵點(diǎn)是囚戚,我們向影子根添加了模板內(nèi)容的克隆,影子根是使用 Node.cloneNode() 方法創(chuàng)建的轧简。

因?yàn)閷⑵鋬?nèi)容追加到一個(gè) Shadow DOM 中驰坊,所以可以在模板中使用 元素的形式包含一些樣式信息,然后將其封裝在自定義元素中哮独。如果只是將其追加到標(biāo)準(zhǔn) DOM 中拳芙,它是無法工作。

例如皮璧,可以將模板更改為:

<template id="my-paragraph">
  <style>
    p {
      color: white;
      background-color: #666;
      padding: 5px;
    }
  </style>
  <p>Paragraph content. </p>
</template>

現(xiàn)在自定義組件可以這樣使用:

<my-paragraph></my-paragraph>

<slot> 元素

模板有一些缺點(diǎn)舟扎,主要是靜態(tài)內(nèi)容,它不允許我們渲染變量/數(shù)據(jù)悴务,好可以讓我們按照一般使用的標(biāo)準(zhǔn) HTML 模板的習(xí)慣來編寫代碼睹限。Slot 是組件內(nèi)部的占位符,用戶可以使用自己的標(biāo)記來填充。讓我們看看上面的模板怎么使用 slot

<template id="my-paragraph">
  <p> 
    <slot name="my-text">Default text</slot> 
  </p>
</template>

如果在標(biāo)記中包含元素時(shí)沒有定義插槽的內(nèi)容羡疗,或者瀏覽器不支持插槽染服,<my-paragraph> 就只展示文本 “Default text”

為了定義插槽的內(nèi)容叨恨,應(yīng)該在 <my-paragraph> 元素中包含一個(gè) HTML 結(jié)構(gòu)柳刮,其中的 slot 屬性的值為我們定義插槽的名稱:

<my-paragraph>
 <span slot="my-text">Let's have some different text!</span>
</my-paragraph>

可以插入插槽的元素稱為 Slotable; 當(dāng)一個(gè)元素插入一個(gè)插槽時(shí),它被稱為開槽 (slotted)特碳。

注意诚亚,在上面的例子中,插入了一個(gè) <span> 元素午乓,它是一個(gè)開槽元素站宗,它有一個(gè)屬性 slot,它等于 my-text益愈,與模板中的 slot 定義中的 name 屬性的值相同梢灭。

在瀏覽器中渲染后,上面的代碼將構(gòu)建以下扁平 DOM 樹:

<my-paragraph>
  #shadow-root
  <p>
    <slot name="my-text">
      <span slot="my-text">Let's have some different text!</span>
    </slot>
  </p>
</my-paragraph>

設(shè)定樣式

使用 shadow DOM 的組件可通過主頁來設(shè)定樣式蒸其,定義其自己的樣式或提供鉤子(以 CSS 自定義屬性的形式)讓用戶替換默認(rèn)值敏释。

代碼部署后可能存在的BUG沒法實(shí)時(shí)知道,事后為了解決這些BUG摸袁,花了大量的時(shí)間進(jìn)行l(wèi)og 調(diào)試钥顽,這邊順便給大家推薦一個(gè)好用的BUG監(jiān)控工具 Fundebug

組件定義的樣式

作用域 CSS 是 Shadow DOM 最大的特性之一:

  • 外部頁面的 CSS 選擇器不應(yīng)用于組件內(nèi)部
  • 組件內(nèi)定義的樣式不會(huì)影響頁面的其他元素靠汁,它們的作用域是宿主元素

shadow DOM 內(nèi)部使用的 CSS 選擇器在本地應(yīng)用于組件實(shí)際上蜂大,這意味著我們可以再次使用公共vid/類名,而不用擔(dān)心頁面上其他地方的沖突,最佳做法是在 Shadow DOM 內(nèi)使用更簡單的 CSS 選擇器,它們?cè)谛阅苌弦膊诲e(cuò)蝶怔。

看看在 #shadow-root 定義了一些樣式的:

#shadow-root
<style>
  #container {
    background: white;
  }
  #container-items {
    display: inline-flex;
  }
</style>

<div id="container"></div>
<div id="container-items"></div>

上面例子中的所有樣式都是#shadow-root的本地樣式奶浦。使用<link>元素在#shadow-root中引入樣式表,這些樣式表也都屬于本地的踢星。

:host 偽類選擇器

使用 :host 偽類選擇器澳叉,用來選擇組件宿主元素中的元素 (相對(duì)于組件模板內(nèi)部的元素)。

<style>
  :host {
    display: block; /* by default, custom elements are display: inline */
  }
</style>

當(dāng)涉及到 :host 選擇器時(shí)沐悦,應(yīng)該小心一件事:父頁面中的規(guī)則具有比元素中定義的 :host 規(guī)則具有更高的優(yōu)先級(jí)成洗,這允許用戶從外部覆蓋頂級(jí)樣式。而且 :host 只在影子根目錄下工作藏否,所以你不能在Shadow DOM 之外使用它泌枪。

如果 :host(<selector>) 的函數(shù)形式與 <selector> 匹配,你可以指定宿主秕岛,對(duì)于你的組件而言碌燕,這是一個(gè)很好的方法误证,它可讓你基于宿主將對(duì)用戶互動(dòng)或狀態(tài)的反應(yīng)行為進(jìn)行封裝,或?qū)?nèi)部節(jié)點(diǎn)進(jìn)行樣式設(shè)定:

<style>
  :host {
    opacity: 0.4;
  }
  
  :host(:hover) {
    opacity: 1;
  }
  
  :host([disabled]) { /* style when host has disabled attribute. */
    background: grey;
    pointer-events: none;
    opacity: 0.4;
  }
  
  :host(.pink) > #tabs {
    color: pink; /* color internal #tabs node when host has class="pink". */
  }
</style>

:host-context(<selector>)

:host-context(<selector>) 或其任意父級(jí)與 <selector> 匹配修壕,它將與組件匹配愈捅。 例如,在文檔的元素上可能有一個(gè)用于表示樣式主題 (theme) 的 CSS 類慈鸠,而我們應(yīng)當(dāng)基于它來決定組件的樣式蓝谨。
比如,很多人都通過將類應(yīng)用到 <html> 或 <body> 進(jìn)行主題化:

<body class="lightheme">
  <custom-container>
  …
  </custom-container>
</body>

在下面的例子中青团,只有當(dāng)某個(gè)祖先元素有 CSS 類theme-light時(shí)譬巫,我們才會(huì)把background-color樣式應(yīng)用到組件內(nèi)部的所有元素中:

:host-context(.theme-light) h2 {
  background-color: #eef;
}

/deep/

組件樣式通常只會(huì)作用于組件自身的 HTML 上,我們可以使用 /deep/ 選擇器督笆,來強(qiáng)制一個(gè)樣式對(duì)各級(jí)子組件的視圖也生效芦昔,它不但作用于組件的子視圖师郑,也會(huì)作用于組件的內(nèi)容泊窘。

在下面例子中,我們以所有的元素為目標(biāo)泥畅,從宿主元素到當(dāng)前元素再到 DOM 中的所有子元素:

:host /deep/ h3 {
  font-style: italic;
}

/deep/ 選擇器還有一個(gè)別名 >>>料扰,可以任意交替使用它們凭豪。

/deep/>>> 選擇器只能被用在仿真 (emulated)模式下。 這種方式是默認(rèn)值晒杈,也是用得最多的方式嫂伞。

從外部為組件設(shè)定樣式

有幾種方法可從外部為組件設(shè)定樣式:最簡單的方法是使用標(biāo)記名稱作為選擇器,如下

custom-container {
  color: red;
}

外部樣式比在 Shadow DOM 中定義的樣式具有更高的優(yōu)先級(jí)拯钻。

例如帖努,如果用戶編寫選擇器:

custom-container {
  width: 500px;
}

它將覆蓋組件的樣式:

:host {
  width: 300px;
}

對(duì)組件本身進(jìn)行樣式化只能到此為止。但是如果人想要對(duì)組件的內(nèi)部進(jìn)行樣式化说庭,會(huì)發(fā)生什么情況呢然磷?為此郑趁,我們需要 CSS 自定義屬性刊驴。

使用 CSS 自定義屬性創(chuàng)建樣式鉤子

如果組件的開發(fā)者通過 CSS 自定義屬性提供樣式鉤子,則用戶可調(diào)整內(nèi)部樣式寡润。其思想類似于<slot>捆憎,但適用于樣式。

看看下面的例子:

<!--?main page -->
<style>
  custom-container {
    margin-bottom: 60px;
     -?custom-container-bg: black;
  }
</style>

<custom-container background>…</custom-container>

在其 shadow DOM 內(nèi)部:

:host([background]) {
  background: var(?-?custom-container-bg, #CECECE);
  border-radius: 10px;
  padding: 10px;
}

在本例中梭纹,該組件將使用 black 作為背景值躲惰,因?yàn)橛脩糁付嗽撝担駝t变抽,背景顏色將采用默認(rèn)值 #CECECE础拨。

作為組件的作者氮块,是有責(zé)任讓開發(fā)人員了解他們可以使用的 CSS 定制屬性,將其視為組件的公共接口的一部分诡宗。

在 JS 中使用 slot

Shadow DOM API 提供了使用 slot 和分布式節(jié)點(diǎn)的實(shí)用程序滔蝉,這些實(shí)用程序在編寫自定義元素時(shí)遲早派得上用場。

slotchange 事件

當(dāng) slot 的分布式節(jié)點(diǎn)發(fā)生變化時(shí)塔沃,slotchange 事件將觸發(fā)蝠引。例如,如果用戶從 light DOM 中添加/刪除子元素蛀柴。

var slot = this.shadowRoot.querySelector('#some_slot');
slot.addEventListener('slotchange', function(e) {
  console.log('Light DOM change');
});

要監(jiān)視對(duì) light DOM 的其他類型的更改,可以在元素的構(gòu)造函數(shù)中使用 MutationObserver鸽疾。以前討論過 MutationObserver 的內(nèi)部結(jié)構(gòu)以及如何使用它

assignedNodes() 方法

有時(shí)候肮韧,了解哪些元素與 slot 相關(guān)聯(lián)非常有用。調(diào)用 slot.assignedNodes() 可查看 slot 正在渲染哪些元素弄企。 {flatten: true} 選項(xiàng)將返回 slot 的備用內(nèi)容(前提是沒有分布任何節(jié)點(diǎn))。

讓我們看看下面的例子:

<slot name=’slot1’><p>Default content</p></slot>

假設(shè)這是在一個(gè)名為 <my-container> 的組件中拘领。

看看這個(gè)組件的不同用法,以及調(diào)用 assignedNodes() 的結(jié)果是什么:

在第一種情況下约素,我們將向 slot 中添加我們自己的內(nèi)容:

<my-container>
  <span slot="slot1"> container text </span>
</my-container>

調(diào)用 assignedNodes() 會(huì)得到 [<span slot= " slot1 " > container text </span>],注意士葫,結(jié)果是一個(gè)節(jié)點(diǎn)數(shù)組。

在第二種情況下慢显,將內(nèi)容置空:

<my-container> </my-container>

調(diào)用 assignedNodes() 的結(jié)果將返回一個(gè)空數(shù)組 []

在第三種情況下荚藻,調(diào)用 slot.assignedNodes({flatten: true}),得到結(jié)果是: [<p>默認(rèn)內(nèi)容</p>]应狱。

此外,要訪問 slot 中的元素祠丝,可以調(diào)用 assignedNodes() 來查看元素分配給哪個(gè)組件 slot疾呻。

事件模型

值得注意的是除嘹,當(dāng)發(fā)生在 Shadow DOM 中的事件冒泡時(shí),會(huì)發(fā)生什么岸蜗。

當(dāng)事件從 Shadow DOM 中觸發(fā)時(shí)憾赁,其目標(biāo)將會(huì)調(diào)整為維持 Shadow DOM 提供的封裝。也就是說散吵,事件的目標(biāo)重新進(jìn)行了設(shè)定龙考,因此這些事件看起來像是來自組件,而不是來自 Shadow DOM 中的內(nèi)部元素矾睦。

下面是從 Shadow DOM 傳播出去的事件列表(有些沒有):

  • 聚焦事件:blur晦款、focus、focusin枚冗、focusout
  • 鼠標(biāo)事件:click缓溅、dblclick、mousedown赁温、mouseenter坛怪、mousemove,等等
  • 滾輪事件:wheel
  • 輸入事件:beforeinput股囊、input
  • 鍵盤事件:keydown袜匿、keyup
  • 組合事件:compositionstart、compositionupdate稚疹、compositionend
  • 拖放事件:dragstart居灯、drag、dragend内狗、drop怪嫌,等等

自定義事件

默認(rèn)情況下,自定義事件不會(huì)傳播到 Shadow DOM 之外柳沙。如果希望分派自定義事件并使其傳播岩灭,則需要添加 bubbles: truecomposed: true 選項(xiàng)。

讓我們看看派發(fā)這樣的事件是什么樣的:

var container = this.shadowRoot.querySelector('#container');
container.dispatchEvent(new Event('containerchanged', {bubbles: true, composed: true}));

瀏覽器支持

如希望獲得 shadow DOM 檢測功能赂鲤,請(qǐng)查看是否存在 attachShadow:

const supportsShadowDOMV1 = !!HTMLElement.prototype.attachShadow;
image

有史以來第一次噪径,我們擁有了實(shí)施適當(dāng) CSS 作用域蛤袒、DOM 作用域的 API 原語妙真,并且有真正意義上的組合荚守。 與自定義元素等其他網(wǎng)絡(luò)組件 API 組合后,shadow DOM 提供了一種編寫真正封裝組件的方法锈候,無需花多大的功夫或使用如 <iframe> 等陳舊的東西泵琳。

關(guān)于Fundebug

Fundebug專注于JavaScript、微信小程序谷市、微信小游戲迫悠、支付寶小程序创泄、React Native括蝠、Node.js和Java線上應(yīng)用實(shí)時(shí)BUG監(jiān)控忌警。 自從2016年雙十一正式上線,F(xiàn)undebug累計(jì)處理了9億+錯(cuò)誤事件感混,付費(fèi)客戶有Google弧满、360庭呜、金山軟件犀忱、百姓網(wǎng)等眾多品牌企業(yè)阴汇。歡迎大家免費(fèi)試用

[圖片上傳失敗...(image-a6bff-1548725834164)]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拐纱,一起剝皮案震驚了整個(gè)濱河市秸架,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚂子,老刑警劉巖缆镣,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件董瞻,死亡現(xiàn)場離奇詭異钠糊,居然都是意外死亡壹哺,警方通過查閱死者的電腦和手機(jī)管宵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門箩朴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炸庞,“玉大人,你說我怎么就攤上這事查牌≈窖眨” “怎么了绎橘?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵浊洞,是天一觀的道長法希。 經(jīng)常有香客問我靶瘸,道長怨咪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任唉匾,我火速辦了婚禮巍膘,結(jié)果婚禮上峡懈,老公的妹妹穿的比我還像新娘肪康。我一直安慰自己撩穿,他們只是感情好食寡,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布冻河。 她就那樣靜靜地躺著,像睡著了一般锭弊。 火紅的嫁衣襯著肌膚如雪味滞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天昨凡,我揣著相機(jī)與錄音便脊,去河邊找鬼哪痰。 笑死晌杰,一個(gè)胖子當(dāng)著我的面吹牛筷弦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惋啃,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼边灭,長吁一口氣:“原來是場噩夢啊……” “哼绒瘦!你這毒婦竟也來了惰帽?” 一聲冷哼從身側(cè)響起父虑,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤呜魄,失蹤者是張志新(化名)和其女友劉穎莱衩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睹晒,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伪很,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年锉试,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炫彩。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖昨忆,靈堂內(nèi)的尸體忽然破棺而出邑贴,到底是詐尸還是另有隱情,我是刑警寧澤奖磁,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布咖为,位于F島的核電站躁染,受9級(jí)特大地震影響架忌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜饰恕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一懂盐、第九天 我趴在偏房一處隱蔽的房頂上張望莉恼。 院中可真熱鬧,春花似錦俐银、人聲如沸捶惜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽景醇。三九已至三痰,卻和暖如春窜管,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背获搏。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工常熙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留症概,地道東北人早芭。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓退个,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舱馅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子代嗤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML標(biāo)準(zhǔn)宜猜。 注意:講述HT...
    kismetajun閱讀 27,445評(píng)論 1 45
  • 前端開發(fā)面試題 <a name='preface'>前言</a> 只看問題點(diǎn)這里 看全部問題和答案點(diǎn)這里 本文由我...
    自you是敏感詞閱讀 756評(píng)論 0 3
  • 簡介瀏覽器可以被認(rèn)為是使用最廣泛的軟件徽缚,本文將介紹瀏覽器的工 作原理,我們將看到膀藐,從你在地址欄輸入google.c...
    聽風(fēng)閣閱讀 3,276評(píng)論 0 7
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案红省? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,734評(píng)論 1 92
  • 今天是二十四節(jié)氣中的“大雪”吧恃,入冬以來最冷的一天痕寓。盡管沒有下雪呻率,但冷風(fēng)嗖嗖地刮著呻引,路上的行人都包裹得嚴(yán)嚴(yán)實(shí)...
    小軒仔0808閱讀 109評(píng)論 0 0