從各大跨平臺(tái)技術(shù)說開去,我們真的需要虛擬 DOM 嗎课蔬?

前言

你有沒有留意到囱稽?優(yōu)秀的解決方案思想都是相通的:當(dāng)你研究 Flutter 渲染原理時(shí)會(huì)發(fā)現(xiàn) Flutter Rendering 層類似于 React 中的虛擬 DOM,當(dāng)你去看 Weex 工作原理時(shí)二跋,誒战惊,又發(fā)現(xiàn)了虛擬 DOM 的身影,更別提 VUE 響應(yīng)式視圖的核心也是虛擬 DOM 了同欠。

那這個(gè)虛擬 DOM 有什么用样傍?為什么這么多框架都應(yīng)用了它横缔?本質(zhì)上帶來了什么優(yōu)勢(shì)?本文將結(jié)合前端和移動(dòng)端來談?wù)劇?/p>

什么是 DOM衫哥?什么是虛擬 DOM茎刚?

DOM 就是文檔樹,與用戶界面控件樹對(duì)應(yīng)撤逢,在 web 開發(fā)中通常指 HTML 對(duì)應(yīng)的渲染樹膛锭,但廣義的 DOM 也可以指 Android 中的 XML 布局對(duì)應(yīng)的控件樹,而 DOM 操作就是指直接操作渲染樹(或控件樹)蚊荣。

虛擬 DOM 是一個(gè)用來表示真實(shí)的 DOM 結(jié)構(gòu)的數(shù)據(jù)結(jié)構(gòu)初狰。

思考

想當(dāng)年學(xué)前端的時(shí)候,還是 jQuery 的時(shí)代互例,想賦值奢入?改個(gè)樣式?取值媳叨?都是document.getElementById()咔咔一頓操作腥光。這樣直接操作 DOM 會(huì)有什么問題?

直接操作 DOM 帶來的問題

1. model 和 view 耦合

最直觀的問題之一糊秆, 把用戶請(qǐng)求的表現(xiàn)邏輯和控制層要實(shí)現(xiàn)的業(yè)務(wù)邏輯兩者混合起來了武福,兩部分的依賴非常強(qiáng)。

2. 高頻操作引起性能損耗

寫個(gè)簡單Demo痘番,我們看下效果捉片。

為什么會(huì)有性能損耗?

原因可以歸結(jié)為 2 點(diǎn):

1. 跨界交流損耗

把 DOM 和 ECMAScript 各自想象成一個(gè)島嶼汞舱,它們之間用收費(fèi)橋梁連接伍纫。
????????????????????????????????????????????????????????????????????????????????——《高性能JavaScript》

DOM 屬于渲染引擎,而 JS 又是屬于 JS 引擎兵拢,在瀏覽器內(nèi)核中他們彼此獨(dú)立翻斟。單獨(dú)來看,兩者都是很快的说铃,但當(dāng)我們用 JS 去操作 DOM 時(shí)访惜,引擎之間進(jìn)行了“跨界交流”。這個(gè)“跨界交流”的實(shí)現(xiàn)并不簡單腻扇,它依賴了橋接接口作為“橋梁”债热,如下圖:

既然是收費(fèi)橋梁,過“橋”就要收費(fèi)幼苛。我們每操作一次 DOM(不管是為了修改還是僅僅為了訪問其值)窒篱,都要過一次“橋”。次數(shù)一多就會(huì)產(chǎn)生比較明顯的性能問題。

那移動(dòng)端混合開發(fā)的情況呢墙杯?

就拿 RectNative 舉例配并,RectNative 是一套 UI 基于原生控件(非Web UI)業(yè)務(wù)邏輯基于 JS 的跨平臺(tái)技術(shù)解決方案,JS 中所寫控件標(biāo)簽不是真實(shí)控件高镐,會(huì)在 Native 端解析為原生控件溉旋,如<Text>標(biāo)簽對(duì)應(yīng) Android 中的 TextView 控件。

映射鏈條

在布局過程中 RN 需要在 JS 和 Native 之間通信嫉髓,如果遇到滑動(dòng)和拖動(dòng)的情況观腊,劣勢(shì)就很明顯了,這和在瀏覽器中要 JS 頻繁操作 DOM 所帶來的問題是相同的算行,都會(huì)帶來比較可觀的性能開銷梧油。

UI 控件屬于原生層,邏輯 JS 屬于 JS 層州邢,也屬于“跨界交流”

2. DOM 修改引起重繪或重排

修改 DOM 屬性的代價(jià)更是昂貴儡陨,它會(huì)導(dǎo)致渲染引擎重新計(jì)算幾何變化(重排和重繪)。我們來看下渲染步驟:

渲染過程

在頁面生成時(shí)量淌,至少會(huì)進(jìn)行一次布局和渲染迄委,后面用戶操作時(shí),如果修改了 DOM 節(jié)點(diǎn)类少,會(huì)觸發(fā)渲染樹(Render Tree)的變化,從而進(jìn)行上圖的步驟2渔扎、3硫狞、4、5雁乡,因此如果在 js 中存在很多 DOM 操作囤官,就會(huì)不斷地觸發(fā)重繪或重排总放,影響頁面性能。

在移動(dòng)端泣侮,情況也好不到哪里去。

布局中的任何一個(gè) View 一旦發(fā)生屬性變化紧唱,都可能引起很大的連鎖反應(yīng)(如果所在的控件層級(jí)非常復(fù)雜的話)活尊。例如某個(gè) btn 的大小突然增加一倍,有可能會(huì)導(dǎo)致兄弟視圖的位置變化漏益,也有可能導(dǎo)致父視圖的大小發(fā)生改變蛹锰。當(dāng)大量的 layout() 操作被頻繁調(diào)用執(zhí)行時(shí),會(huì)引起整個(gè) View 頻繁地重渲绰疤,最終導(dǎo)致丟幀或 UI 卡頓铜犬。

解決辦法

針對(duì)以上的問題,我們一一提出解決方案:

1. 減少跨界過橋次數(shù),合并操作

ECMAScript 每次訪問 DOM癣猾,都要經(jīng)過這座橋敛劝,并交納“過橋費(fèi)”,訪問 DOM 的次數(shù)越多纷宇,費(fèi)用也就越高夸盟。因此,推薦的做法是盡量減少過橋的次數(shù)呐粘,努力呆在 ECMAScript 島上满俗。???????????????????????????????????????????????????——《高性能JavaScript》

我們來分析下,怎么減少“過橋的次數(shù)”作岖?過橋次數(shù)之所以頻繁唆垃,和頻繁的 DOM 操作有關(guān)。

比如我們給列表加數(shù)據(jù)痘儡,最差的方式就是這樣:

  for (var i = 0; i < N; i++) {
        var li = document.createElement("li");
        li.innerHTML = arr[i];
        ul.appendChild(li);
    }

這里會(huì)操作 N 次 DOM 觸發(fā) N 次重繪辕万。重渲肯定是無法避免的,我們的目標(biāo)是最小化重繪和重排次數(shù)沉删。

那能不能不要立即去操作 DOM 呢渐尿?

將這 N 次更新的內(nèi)容保存到一個(gè) js 對(duì)象中,最終將這個(gè) js 對(duì)象一次性 attach 到 DOM 樹上矾瑰,通知瀏覽器去執(zhí)行繪制工作砖茸。這樣無論多么復(fù)雜的 DOM 操作,最終都只會(huì)觸發(fā)一次渲染全流程殴穴,避免了大量的無謂計(jì)算量凉夯,這樣不就可以了么!(欣喜若狂.jpg)

但優(yōu)化 DOM 操作方式很多采幌,不一定要依賴虛擬 DOM劲够,所以這不是我們需要虛擬 DOM 的根本原因,根本的原因還是響應(yīng)式需求休傍。

2. 響應(yīng)式

如果通過 JS 直接操作 DOM 的話征绎,勢(shì)必會(huì)造成視圖數(shù)據(jù)和模型數(shù)據(jù)的不匹配,我們能不能讓開發(fā)者只關(guān)心狀態(tài)(數(shù)據(jù))變化磨取,而無需關(guān)心控件操作呢人柿?當(dāng)然可以!

React 中提出一個(gè)重要思想:狀態(tài)改變則 UI 隨之自動(dòng)改變忙厌。

每次狀態(tài)有變動(dòng)就重構(gòu)用戶界面顷扩,重渲整個(gè) view。如果沒有虛擬 DOM慰毅,簡單粗暴的做法就是直接重置 innerHTML隘截,在大部分?jǐn)?shù)據(jù)都變了的情況下,重置 innerHTML 還算合理,但如果只有一行數(shù)據(jù)變了婶芭,顯然就有大量的浪費(fèi)东臀。

這是我們需要虛擬 DOM 的原因,用它來代替開發(fā)者的手工操作犀农,確保只對(duì)真正有變化的部分進(jìn)行實(shí)際的 DOM 操作(局部刷新)惰赋。

3. 總結(jié)

開發(fā)者對(duì)數(shù)據(jù)和狀態(tài)所做的任何改動(dòng),都會(huì)被自動(dòng)且高效的同步到虛擬 DOM(自動(dòng)同步呵哨,體現(xiàn)響應(yīng)式)赁濒,最后再批量同步到真實(shí) DOM 中,而不是每次改變都去操作一下 DOM(批量同步孟害,體現(xiàn)合并操作)

  1. 不需要直接操作控件拒炎,通過數(shù)據(jù)驅(qū)動(dòng)視圖
  2. 最大程度降低對(duì)最終視圖的修改,提高頁面渲染效率

怎么利用虛擬 DOM挨务?

1. React

當(dāng) React UI 渲染時(shí)击你,先渲染一個(gè)虛擬 DOM,這是一個(gè)輕量的純 js 的對(duì)象結(jié)構(gòu)谎柄,并沒有完全實(shí)現(xiàn) DOM丁侄,最主要的還是保留了節(jié)點(diǎn)之間的層次關(guān)系和一些基本屬性,因?yàn)?DOM 實(shí)在是太復(fù)雜朝巫,實(shí)際在做最后繪制時(shí)鸿摇,這些都是不需要關(guān)心的。所以虛擬 DOM 里每一個(gè)節(jié)點(diǎn)只有幾個(gè)簡單屬性劈猿,哪怕是直接把虛擬 DOM 刪了户辱,根據(jù)新傳進(jìn)來的數(shù)據(jù)重新創(chuàng)建一個(gè)新的虛擬 DOM 都非常快糙臼。

當(dāng)有變化時(shí),生成一個(gè)新的虛擬 DOM恩商。這個(gè)新的虛擬DOM反應(yīng)了數(shù)據(jù)模型的新狀態(tài)”涮樱現(xiàn)在我們有 2 個(gè)虛擬DOM:新的和老的。對(duì)比 DOM 樹差異得到一個(gè) Patch怠堪,把這個(gè) Patch 打到真實(shí)的 DOM 上去揽乱,這有點(diǎn)像版本控制打patch的思路。

那我們?cè)趺幢容^出兩顆 DOM 樹的差異呢粟矿? Diff 算法凰棉!

即給定任意兩棵樹,找到最少的轉(zhuǎn)換步驟陌粹。但是標(biāo)準(zhǔn)的 Diff 算法復(fù)雜度需要 O(n^3)撒犀,這顯然無法滿足性能要求。Facebook 工程師結(jié)合 Web 界面的特點(diǎn)做出了兩個(gè)簡單的假設(shè),使得 Diff 算法復(fù)雜度直接降低到 O(n)或舞。

  1. 兩個(gè)相同組件產(chǎn)生類似的 DOM 結(jié)構(gòu)荆姆,不同的組件產(chǎn)生不同的 DOM 結(jié)構(gòu);
  2. 對(duì)于同一層次的一組子節(jié)點(diǎn)映凳,它們可以通過唯一的 id 進(jìn)行區(qū)分胆筒。

算法上的優(yōu)化是 React 整個(gè)界面 Render 的基礎(chǔ),事實(shí)也證明這兩個(gè)假設(shè)是合理而精確的诈豌,保證了整體界面構(gòu)建的性能仆救。

由這一對(duì)不同類型的節(jié)點(diǎn)的處理邏輯我們很容易得到推論,那就是 React 的 DOM Diff 算法實(shí)際上只會(huì)對(duì)樹進(jìn)行逐層比較矫渔,如下圖:

React 只會(huì)對(duì)相同顏色方框內(nèi)的 DOM 節(jié)點(diǎn)進(jìn)行比較彤蔽,即同一個(gè)父節(jié)點(diǎn)下的所有子節(jié)點(diǎn)。當(dāng)發(fā)現(xiàn)節(jié)點(diǎn)已經(jīng)不存在蚌斩,則該節(jié)點(diǎn)及其子節(jié)點(diǎn)會(huì)被完全刪除掉铆惑,不會(huì)用于進(jìn)一步的比較。這樣只需要對(duì)樹進(jìn)行一次遍歷送膳,便能完成整個(gè) DOM 樹的比較员魏。

實(shí)際實(shí)踐起來,Diff 算法并沒有這么簡單叠聋,感興趣的小伙伴可以在文末的推文去深入了解撕阎。

那跨平臺(tái)方案的情況呢?

2. RN

上文已經(jīng)提到 RN 是 React 在原生移動(dòng)應(yīng)用平臺(tái)的衍生產(chǎn)物碌补,那兩者主要的區(qū)別是什么呢虏束?主要的區(qū)別在于虛擬 DOM 映射的對(duì)象是什么。React 中虛擬 DOM 最終會(huì)映射為瀏覽器 DOM 樹厦章,而 RN 中虛擬 DOM 會(huì)通過 JavaScriptCore 映射為原生控件樹镇匀。

步驟如下:

  1. 布局消息傳遞:將虛擬 DOM 布局信息傳遞給原生;
  2. 原生根據(jù)布局信息袜啃,映射成對(duì)應(yīng)原生控件樹汗侵,渲染控件樹。

至此群发,RN 便實(shí)現(xiàn)了跨平臺(tái)晰韵。

3. weex

weex 一定程度上用 JS 實(shí)現(xiàn)了 vue 一統(tǒng)天下的效果。

可以看到熟妓,weex 會(huì)編譯構(gòu)建虛擬 DOM雪猪,并發(fā)送渲染指令給 RenderEngine 層,這樣起愈,同樣一份 JSON 數(shù)據(jù)只恨,在不同平臺(tái)的渲染引擎中能夠渲染成不同版本的 UI译仗,這是 Weex 可以實(shí)現(xiàn)動(dòng)態(tài)化的原因。

weex工作原理

那三端的語法都不一樣坤次,Weex是怎么統(tǒng)一的古劲?重點(diǎn)在于 JS Framework!

weex 在 RN 的 JS V8 引擎基礎(chǔ)上缰猴,多了 JS Framework 承當(dāng)了重要的職責(zé)产艾,它主要負(fù)責(zé):管理 Weex 的生命周期;解析 JS Bundle滑绒,轉(zhuǎn)為 Virtual DOM闷堡,再通過所在平臺(tái)不同的 API 構(gòu)建頁面;進(jìn)行雙向的數(shù)據(jù)交互和響應(yīng)疑故。

這使得上層具備統(tǒng)一性杠览,在開發(fā)過程中,代碼模式纵势、編譯過程踱阿、模板組件、數(shù)據(jù)綁定钦铁、生命周期等上層語法是一致的软舌。得益于上層的統(tǒng)一,只需要在 JS Framework 層的最后判斷是由 Vue.js 生成真實(shí)的 DOM牛曹,還是通過 Native Api 渲染組件即可佛点。

4. Flutter

RN 和 React 原理相通,那 Flutter 呢黎比?Flutter Widget 的中心思想是用 Widget 構(gòu)建你的UI(非原生控件)超营。 那少了原生控件層和 js 層的通信損耗,不需要用虛擬 DOM 了吧阅虫?

非也演闭! Flutter Widget 從 React 中獲得了靈感,也是采用現(xiàn)代響應(yīng)式框架構(gòu)建颓帝。

先看看 Flutter 中三顆重要的樹:

Flutter的三顆樹
  • Widget 樹:控件樹米碰,表示了我們?cè)?dart 代碼中所寫的控件的結(jié)構(gòu),但這只是描述信息躲履,渲染引擎是不認(rèn)識(shí)的。

    Widget 被開發(fā)人員配置了多個(gè)屬性來定義它的展現(xiàn)形式聊闯,例如配置 Text 組件需要顯示的字符串工猜,配置輸入框組件需要顯示的內(nèi)容……Element 樹會(huì)記錄這些配置信息。

  • Element 數(shù):實(shí)際控件樹

    在手機(jī)屏幕上顯示的控件并非我們?cè)诖a中所寫的 Widget菱蔬,F(xiàn)lutter 會(huì)根據(jù) Widget 樹信息生成控件對(duì)應(yīng)的 Element 樹篷帅,在 Flutter 中史侣,一個(gè) Widget 通過多次復(fù)用可以對(duì)應(yīng)多個(gè) Element 實(shí)例,Element 才是我們真正在屏幕上顯示的元素魏身。

    Element 與 Widget 另一個(gè)區(qū)別在于惊橱,Widget 是不可變的,它的改變就意味著要重建箭昵,而其重建也非常頻繁税朴,如果我們將更多的任務(wù)交給它,將會(huì)對(duì)性能造成很大的損耗家制,因此我們把 Widget 樹當(dāng)作一個(gè)虛擬 DOM 樹正林,真正被渲染在屏幕上的其實(shí)是 ElememtTree,它持有其對(duì)應(yīng) Widget 的引用颤殴,如果對(duì)應(yīng)的 Widget 發(fā)生改變觅廓,它就會(huì)被標(biāo)記為 dirty Element,下一次更新視圖時(shí)根據(jù)這個(gè)狀態(tài)只更新被修改的內(nèi)容涵但,這樣就把可變狀態(tài)與 Widget 關(guān)聯(lián)起來杈绸,從而達(dá)到提升性能的效果。

  • RenderObject 樹:渲染樹矮瘟,做組件布局渲染工作瞳脓,包含渲染搭配、布局約束等信息芥永。

簡而言之篡殷,F(xiàn)lutter 引入虛擬 DOM 的目的是為了確定底層渲染樹從一個(gè)狀態(tài)轉(zhuǎn)換到下一個(gè)狀態(tài)所需的最小更改。

虛擬 DOM 對(duì)跨平臺(tái)技術(shù)的意義

那分析完各種跨平臺(tái)技術(shù)埋涧,你對(duì)虛擬 DOM 有了怎樣的認(rèn)識(shí)了呢板辽?

為什么使用虛擬 DOM?

是因?yàn)榭旒撸浚▽?shí)際上不一定快)

是因?yàn)榻怦睿?/p>

是因?yàn)轫憫?yīng)式劲弦?

對(duì)跨平臺(tái)技術(shù)來說,更重要的意義在于:

虛擬 DOM 是 DOM 在內(nèi)存中的一種輕量級(jí)表達(dá)方式醇坝,是一種統(tǒng)一約定邑跪!可以通過不同的渲染引擎生成不同平臺(tái)下的 UI!

虛擬 DOM 的可移植性非常好呼猪,這意味著可以渲染到 DOM 以外的任何端画畅,發(fā)揮你的想象力,可以做的事情很多宋距。

再次審視虛擬 DOM

虛擬 DOM 真正的價(jià)值從來都不是性能轴踱,而是不管數(shù)據(jù)怎么變化,都可以用最小的代價(jià)來更新 DOM谚赎,而且掩蓋了底層的 DOM 操作淫僻,讓你用更聲明式的方式來描述你的目的诱篷,從而讓你的代碼更容易維護(hù)。

虛擬 DOM 帶來了很多好思路雳灵,打開了通向有趣架構(gòu)的大門棕所,例如將視圖視為狀態(tài)函數(shù)。它讓我們編寫代碼悯辙,就像重新呈現(xiàn)整個(gè)場景一樣琳省。這不禁讓我感慨,沒有什么是加中間件不能解決的笑撞,如果有岛啸,那就再加多個(gè)中間件。

5 個(gè)詞語概括下意義:

可維護(hù)性茴肥、最小的代價(jià)坚踩、效率、函數(shù)式UI瓤狐、數(shù)據(jù)驅(qū)動(dòng)

進(jìn)一步思考

虛擬 DOM 的說明已經(jīng)結(jié)束了瞬铸,但是對(duì)于虛擬 DOM 的思考遠(yuǎn)沒有結(jié)束。

Rect 的方式有兩大缺點(diǎn):

  1. 每次數(shù)據(jù)更改础锐,哪怕改動(dòng)很小嗓节,都會(huì)生成完整的虛擬 DOM,如果 DOM 很復(fù)雜皆警,這個(gè)過程就會(huì)白白浪費(fèi)很多計(jì)算資源拦宣;

  2. 比較虛擬 DOM 差異的過程,既慢又容易出錯(cuò)信姓。因?yàn)?React 持有的新舊虛擬 DOM 相互獨(dú)立鸵隧,React 并不知道數(shù)據(jù)源發(fā)生了什么操作,只能根據(jù)兩個(gè)虛擬 DOM 來猜測需要執(zhí)行的操作意推。自動(dòng)的猜測算法既不準(zhǔn)又慢豆瘫,必須要前端開發(fā)者手動(dòng)提供 key 屬性和一些額外的方法實(shí)現(xiàn)來幫助 React 猜對(duì)。

那么菊值?

留個(gè)思考題外驱,vue 是怎么利用虛擬 DOM 的?針對(duì)以上缺點(diǎn)怎么做改進(jìn)腻窒?大家可以去了解一下昵宇。

還想了解更多?

本篇完成耗時(shí) 26 個(gè)番茄鐘( 650分鐘)


我是 FeelsChaotic杭煎,一個(gè)寫得了代碼 p 得了圖,剪得了視頻畫得了畫的程序媛卒落,致力于追求代碼優(yōu)雅羡铲、架構(gòu)設(shè)計(jì)和 T 型成長。

歡迎關(guān)注 FeelsChaotic 的簡書掘金儡毕,如果我的文章對(duì)你哪怕有一點(diǎn)點(diǎn)幫助也切,歡迎 ??!你的鼓勵(lì)是我寫作的最大動(dòng)力腰湾!

最最重要的雷恃,請(qǐng)給出你的建議或意見,有錯(cuò)誤請(qǐng)多多指正费坊!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末倒槐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子附井,更是在濱河造成了極大的恐慌讨越,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件永毅,死亡現(xiàn)場離奇詭異把跨,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)沼死,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門着逐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人意蛀,你說我怎么就攤上這事耸别。” “怎么了浸间?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵太雨,是天一觀的道長。 經(jīng)常有香客問我魁蒜,道長囊扳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任兜看,我火速辦了婚禮锥咸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘细移。我一直安慰自己搏予,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布弧轧。 她就那樣靜靜地躺著雪侥,像睡著了一般碗殷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上速缨,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天锌妻,我揣著相機(jī)與錄音,去河邊找鬼旬牲。 笑死仿粹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的原茅。 我是一名探鬼主播吭历,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼擂橘!你這毒婦竟也來了晌区?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤通贞,失蹤者是張志新(化名)和其女友劉穎契讲,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滑频,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捡偏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了峡迷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片银伟。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绘搞,靈堂內(nèi)的尸體忽然破棺而出彤避,到底是詐尸還是另有隱情,我是刑警寧澤夯辖,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布琉预,位于F島的核電站,受9級(jí)特大地震影響蒿褂,放射性物質(zhì)發(fā)生泄漏圆米。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一啄栓、第九天 我趴在偏房一處隱蔽的房頂上張望娄帖。 院中可真熱鬧,春花似錦昙楚、人聲如沸近速。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽削葱。三九已至奖亚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間析砸,已是汗流浹背遂蛀。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留干厚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓螃宙,卻偏偏與公主長得像蛮瞄,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谆扎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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