AngularJS Performance in Large Applications翻譯

原文:https://www.airpair.com/angularjs/posts/angularjs-performance-large-applications#5-1-scopes-and-the-digest-cycle

1介紹

無(wú)論您是為大型的舊應(yīng)用程序編寫(xiě)Angular,還是您已有的Angular應(yīng)用程序在變得龐大,性能是一個(gè)重要的方面。 了解AngularJS應(yīng)用程序減慢的原因以及如何在開(kāi)發(fā)過(guò)程中做出權(quán)衡很重要。 本文將介紹AngularJS的一些常見(jiàn)的性能問(wèn)題,以及如何避免和修復(fù)的建議。

1.1要求,假設(shè)

本文將會(huì)假定你對(duì)JavaScript語(yǔ)言和AngularJS有些熟悉。 當(dāng)使用特定版本的功能時(shí),它們將被調(diào)用。 為了充分利用這篇文章,最好是用過(guò)一段時(shí)間Angular,但還沒(méi)有認(rèn)真對(duì)待性能。

2衡量工具

2.1基準(zhǔn)測(cè)試

jsPerf是一個(gè)很棒的用于對(duì)代碼進(jìn)行基準(zhǔn)測(cè)試的工具。 我將在相關(guān)部分結(jié)尾給出具體的測(cè)試鏈接,以便閱讀。

2.2 分析

Chrome開(kāi)發(fā)工具有一個(gè)很好的JavaScript分析器。 我強(qiáng)烈推薦閱讀本系列 文章。

2.3 Angular Batarang

Angular Batarang是一個(gè)專(zhuān)注于angular的調(diào)試器,由Angular Core Team維護(hù),可在GitHub上獲得。

3軟件性能

決定是否高性能軟件有兩個(gè)根本原因。
第一個(gè)是算法時(shí)間復(fù)雜度。 解決這個(gè)問(wèn)題很大程度上超出了本文的討論范圍,一般來(lái)說(shuō),時(shí)間復(fù)雜度是程序需要做多少計(jì)算來(lái)取得結(jié)果的一個(gè)衡量標(biāo)準(zhǔn)。 計(jì)算的數(shù)量越大,程序越慢。 一個(gè)簡(jiǎn)單的例子是線性搜索與二進(jìn)制搜索。 線性搜索需要對(duì)同一組數(shù)據(jù)進(jìn)行更多計(jì)算,因此將會(huì)更慢。 有關(guān)時(shí)間復(fù)雜性的詳細(xì)討論,請(qǐng)參閱維基百科文章
第二個(gè)原因就是算法空間復(fù)雜度。 這是計(jì)算機(jī)運(yùn)行算法需要多少“存儲(chǔ)空間”或內(nèi)存的衡量標(biāo)準(zhǔn)。 需要的內(nèi)存越多,解決方案越慢。 本文討論的大多數(shù)問(wèn)題在空間復(fù)雜性之下將會(huì)變得松動(dòng)。 詳細(xì)討論請(qǐng)看這里。
這句話(huà)不知道怎么翻譯,有知道的朋友請(qǐng)告知,謝謝。原文:

Most of the problems this article will talk to fall loosely under space complexity. For a detailed discussion, see here.

4 Javascript 性能

這里說(shuō)下關(guān)于JavaScript 性能的幾件事情,不一定局限于angular。

4.1 循環(huán)

避免在循環(huán)中調(diào)用。 如果循環(huán)內(nèi)的調(diào)用可以在循環(huán)之外執(zhí)行,那么把它放到循環(huán)之外將極大地加快您的系統(tǒng)。 例如:

var sum = 0;
for(var x = 0; x < 100; x++){ 
    var keys = Object.keys(obj); sum = sum + keys[x];
}

會(huì)顯著慢于:

var sum = 0;
var keys = Object.keys(obj);
for(var x = 0; x < 100; x++){ 
    sum = sum + keys[x];
}

http://jsperf.com/for-loop-perf-demo-basic

4.2 DOM訪問(wèn)

注意DOM訪問(wèn),這很重要。

angular.element( 'div.elementClass')

代價(jià)昂貴。雖然在AngularJS中出現(xiàn)這種問(wèn)題的幾率很小,但還是有必要了解這一點(diǎn)。這里要說(shuō)的第二件事就是在可能的情況下,DOM樹(shù)應(yīng)該保持較小。
最后,盡可能避免修改DOM和設(shè)置內(nèi)聯(lián)樣式。因?yàn)檫@會(huì)導(dǎo)致JavaScript重繪。重繪的深入討論超出了本文的范圍,但這里有一個(gè)很棒的參考

4.3變量作用域和垃圾回收

盡可能?chē)?yán)格地將所有變量聲明為局部作用域,以使JavaScript垃圾回收器能夠更快地釋放內(nèi)存。
這句我是參照上下文推斷出來(lái)的,翻譯的可能有點(diǎn)問(wèn)題??煽丛模?/p>

Scope all variables as tightly as possible to allow the JavaScript garbage collector to free up your memory sooner rather then later.

這是造成JavaScript,特別是Angular緩慢,滯后,不響應(yīng)非常常見(jiàn)的原因。請(qǐng)注意以下問(wèn)題:

function demo(){
    var b = {childFunction:function(){console.log('hi this is the child function')};
    b.childFunction();
    return b;
  }

當(dāng)函數(shù)終止時(shí),將不再有對(duì)b可用的引用,垃圾回收器將釋放內(nèi)存。但是,如果在其他地方有這樣的一行:

var cFunc = demo();

我們現(xiàn)在將對(duì)象綁定到一個(gè)變量并保持對(duì)它的引用,從而防止垃圾收集器清理它。雖然這可能是必要的,但重要的是要注意這對(duì)對(duì)象引用的影響。

4.4數(shù)組和對(duì)象

這里有很多事需要說(shuō)下。第一個(gè)也是最簡(jiǎn)單的,數(shù)組總是比對(duì)象快,數(shù)字訪問(wèn)比非數(shù)字訪問(wèn)更好。

for(var x = 0; x <arr.length; x ++){
    i = arr [x] .index;
}

上面的比下面的代碼快

for (var x=0; x<100; x++) {
    i = obj[x].index;
}

上面的又比接下來(lái)的代碼快

var keys = Object.keys(obj);
for(var x = 0; x <keys.length; x ++){
  i = obj [keys [x]]。index;
}

http://jsperf.com/array-vs-object-perf-demo
此外,請(qǐng)注意,在基于V8的現(xiàn)代瀏覽器中,具有很少屬性的對(duì)象表現(xiàn)得明顯更快,所以請(qǐng)將屬性數(shù)量保持在最低限度。
還要注意,JavaScript能讓你在數(shù)組中混合類(lèi)型,但這并不是一個(gè)好主意:

var oneType = [1,2,3,4,5,6]
var multiType = [“string”,1,2,3,{a:'x'}]

第二次的操作明顯比第一個(gè)慢得多,不僅僅是因?yàn)檫壿嫺鼜?fù)雜。
http://jsperf.com/array-types-compare-perf

還要避免使用刪除。例如,給出:

var arr = [1,2,3,4,5,6];
var arrDelete = [1,2,3,4,5,6];
delete arrDelete [3];

任何arrDelete的迭代都會(huì)比arr迭代慢。
http://jsperf.com/delet-is-slow
這將在數(shù)組中創(chuàng)建一個(gè)undefined值,從而使操作效率更低。

5重要概念

剛才我們已經(jīng)討論了JavaScript的性能,這對(duì)于理解一些關(guān)鍵的angular概念很重要。

5.1 Scopes 和 Digest 循環(huán)

在angular核心,angular Scopes只是簡(jiǎn)單JavaScript對(duì)象。他們遵循預(yù)定義的原型繼承方案,對(duì)此的深入討論超出了本文的范圍。與上述相關(guān)的是,小Scopes將比大Scopes更快。
在這一點(diǎn)上可以做出的另一個(gè)結(jié)論是,任何時(shí)間創(chuàng)建新的Scope,垃圾收集器將增加更多的值以便稍后回收。
一般來(lái)說(shuō),Digest循環(huán)對(duì)編寫(xiě)Angular JS應(yīng)用程序和性能尤其重要。實(shí)際上,每個(gè)Scope都存儲(chǔ)$$watchers函數(shù)的數(shù)組。
每次在一個(gè)Scope值上,或者一個(gè)綁定在DOM插值,一個(gè)ng-repeat,ng-switch,ng-if或者任何其他DOM屬性/元素調(diào)用$watch,一個(gè)函數(shù)將被添加到$$watchers數(shù)組的最內(nèi)層Scope。

當(dāng)scope里面的任何值發(fā)生變化時(shí),$$watchers數(shù)組中的所有watchers將觸發(fā),如果其中任何一個(gè)修改了觀察值,則它們將會(huì)再次全部觸發(fā)。 這將持續(xù)到$$watchers數(shù)組的不再改變并完整傳遞,或者AngularJS拋出異常。
另外,如果不是Angular代碼運(yùn)行$scope.$apply(),這將立即觸發(fā)digest 循環(huán)。
最后要注意的是,$ scope.evalAsync()將在異步循環(huán)中運(yùn)行代碼,該循環(huán)不會(huì)觸發(fā)另一個(gè)digest 循環(huán),并且將在當(dāng)前/下一個(gè)digest 循環(huán)結(jié)束時(shí)運(yùn)行。

6 常見(jiàn)問(wèn)題:設(shè)計(jì)時(shí)要注意

6.1大對(duì)象和服務(wù)器調(diào)用。

那么所有這些教導(dǎo)我們什么呢?第一個(gè)是考慮我們的數(shù)據(jù)模型,并限制對(duì)象的復(fù)雜性。這對(duì)于從服務(wù)器返回的對(duì)象尤其重要。
也就是說(shuō),返回整個(gè)數(shù)據(jù)庫(kù)行,并且強(qiáng)制性的使用.toJson()是非常簡(jiǎn)單而且誘人的。這不夠健壯:請(qǐng)不要這樣做。
而是使用自定義序列化程序只返回Angular應(yīng)用程序必須要用到的keys子集。

6.2觀察函數(shù)

另一個(gè)常見(jiàn)的問(wèn)題是在觀察者或綁定中使用函數(shù)。不要將任何東西(ng-show,ng-repeat等)直接綁定到一個(gè)函數(shù)上。不要直接觀察函數(shù)結(jié)果。這個(gè)函數(shù)將在每個(gè)digest 循環(huán)中運(yùn)行,可能會(huì)減慢應(yīng)用程序的爬網(wǎng)速度。

6.3觀察對(duì)象

類(lèi)似地,Angular提供了通過(guò)將第三個(gè)可選的true參數(shù)傳遞給scope.$watch來(lái)觀察整個(gè)對(duì)象的能力。這是一個(gè)很糟糕的主意。一個(gè)更好的解決方案是依靠服務(wù)和對(duì)象引用在scopes之間傳播對(duì)象更改。

7列表問(wèn)題

7.1長(zhǎng)列表

盡可能避免長(zhǎng)列表。 ng-repeat會(huì)執(zhí)行一些非常重的DOM操作(更不用說(shuō)污染的$$watchers),所以嘗試并保持渲染數(shù)據(jù)的列表盡量小,無(wú)論是通過(guò)分頁(yè)還是無(wú)限滾動(dòng)。

7.2過(guò)濾器

盡可能避免使用過(guò)濾器。它們?cè)诿總€(gè)digest 循環(huán)運(yùn)行兩次,一次是在有任何更改時(shí),另一次是收集進(jìn)一步更改,并且實(shí)際上沒(méi)有從內(nèi)存中刪除收集的任何部分,而只是使用CSS屏蔽過(guò)濾的項(xiàng)。
這使$ index無(wú)效,因?yàn)樗辉賹?duì)應(yīng)于實(shí)際的數(shù)組索引,而是排序的數(shù)組索引。它也阻止您放棄所有列表的scopes。

7.3更新ng-repeat

當(dāng)使用ng-repeat時(shí),避免全局列表刷新也很重要。ng-repeat將填充一個(gè)$$ hashKey屬性并標(biāo)識(shí)該集合中的項(xiàng)目。這意味著,做一些像scope.listBoundToNgRepeat = serverFetch()這樣的事情將導(dǎo)致整個(gè)列表的重新計(jì)算,導(dǎo)致運(yùn)行外部程序并且觀察者為每個(gè)單獨(dú)的元素觸發(fā)。這是一個(gè)非常昂貴、耗性能的。
這有兩種方法。一個(gè)是在過(guò)濾集上維護(hù)兩個(gè)集合和ng-repeat(更通用的,需要自定義同步邏輯,因此算法上更復(fù)雜和更少可維護(hù)),另一個(gè)是使用track by來(lái)指定自己的key(需要Angular 1.2+,略少通用,不需要自定義同步邏輯)。

簡(jiǎn)而言之:

scope.arr = mockServerFetch();

會(huì)慢于:

 var a = mockServerFetch();
    for(var i = scope.arr.length - 1; i >=0; i--){
      var result = _.find(a, function(r){
        return (r && r.trackingKey == scope.arr[i].trackingKey);
      });
      if (!result){
        scope.arr.splice(i, 1);
      } else {
        a.splice(a.indexOf(scope.arr[i]), 1);
      } 
    }
    _.map(a, function(newItem){
      scope.arr.push(newItem);
     });

這將比簡(jiǎn)單地添加更慢:

<div ng-repeat =“a in arr track by a.trackingKey”>

代替:

<div ng-repeat =“a in arr”>

這里可以找到這三種方法的全功能演示。
只需在三個(gè)選項(xiàng)之間點(diǎn)擊并要求重新獲取就可以很好地顯示出來(lái)。需要注意的是,track by方法僅在這個(gè)字段可以保證在循環(huán)對(duì)象上唯一時(shí)才起作用。對(duì)于服務(wù)器數(shù)據(jù),id屬性用作自然跟蹤器。如果這不可能,不幸的是,自定義同步邏輯是唯一的辦法。

8 渲染問(wèn)題

Angular應(yīng)用程序慢的常見(jiàn)原因是ng-hide和ng-show 以及 ng-if或ng-switch的不正確使用。這種區(qū)別是不容易的,并且對(duì)性能的重要性不能夸大。
ng-hide和ng-show只是切換CSS display 屬性。這在實(shí)踐中意味著,任何顯示或隱藏的東西仍然在頁(yè)面上,盡管看不見(jiàn)。任何scopes 將存在,所有的$$watchers都將觸發(fā)等。
ng-if和ng-switch實(shí)際上完全刪除或添加DOM。用ng-if刪除的東西將沒(méi)有scope。雖然性能優(yōu)勢(shì)應(yīng)該是顯而易見(jiàn)的,但是有一個(gè)需要抓住的點(diǎn)。具體來(lái)說(shuō),切換顯示/隱藏比較便宜,但切換if / switch相對(duì)較貴。不幸的是,這導(dǎo)致了需要在一個(gè)個(gè)用例中權(quán)衡。作出這個(gè)決定需要回答的問(wèn)題是:
這個(gè)變化有多頻繁? (越頻繁,ng-if 越糟糕)。
scope有多重? (越重,ng-if更適合)。

9。Digest 循環(huán)問(wèn)題

9.1綁定

嘗試并盡量減少綁定。從Angular 1.3開(kāi)始,有一個(gè)新的語(yǔ)法,單向綁定 {{::scopeValue}}。這將從scope添加一次,而不向觀察者數(shù)組添加觀察器。

9.2 $digest() 和$apply()

scope.$apply是一個(gè)強(qiáng)大的工具,允許您將Angular外的值引入到應(yīng)用程序中。在所有事件(ng-click等)下,它會(huì)觸發(fā)。問(wèn)題在于,scope.$apply從$rootScope開(kāi)始,并遍歷整個(gè)scope鏈,導(dǎo)致每個(gè)scope都會(huì)觸發(fā)每個(gè)觀察者。
scope.$digest 則起始于調(diào)用它的具體scope,只從那里向下傳播。性能優(yōu)勢(shì)應(yīng)該是相當(dāng)明顯的。當(dāng)然,任何父級(jí)scopes 將不會(huì)收到此更新,直到下一個(gè)digest 循環(huán)。

9.3 $watch()

scope.$watch()已經(jīng)討論過(guò)幾次了。一般來(lái)說(shuō),scope.$watch是一個(gè)表現(xiàn)糟糕的架構(gòu)。當(dāng)服務(wù)和引用綁定的某些組合在較低的開(kāi)銷(xiāo)時(shí)也能達(dá)到相同的結(jié)果,并且開(kāi)銷(xiāo)更少。很少有不能達(dá)到相同結(jié)果的情況。如果您必須創(chuàng)建一個(gè)觀察者,請(qǐng)始終記住在第一時(shí)間解除綁定。您可以通過(guò)調(diào)用$watch函數(shù)來(lái)解除綁定。

var unbinder = scope.$watch('scopeValueToBeWatcher', function(newVal, oldVal){});
unbinder(); //this line removes the watch from $$watchers.

如果你不能盡早解綁,請(qǐng)記得在$on('$destroy')中解綁。

9.4 $on, $broadcast , 和 $emit

像$watch一樣,這些都是緩慢的,因?yàn)槭录撛诘兀┍仨毐榧罢麄€(gè)scope 層次結(jié)構(gòu)。除此之外,GOTO還可以讓您的應(yīng)用程序成為一個(gè)復(fù)雜的調(diào)試問(wèn)題。幸運(yùn)的是,像$watch一樣,他們可以調(diào)用返回的函數(shù)解綁(請(qǐng)記住在$on('$destroy') 中解除綁定),并且?guī)缀蹩梢员苊馐褂梅?wù)和scope 繼承。

9.5 $ destroy

如上所述,您應(yīng)該總是明確地調(diào)用 $on('$destroy'),解除所有觀察者和事件偵聽(tīng)器的綁定,并取消任何$timeout或其他異步正在進(jìn)行的交互的實(shí)例。這不僅是確保安全的良好做法,更快地標(biāo)示垃圾收集的scope 。不這樣做會(huì)讓他們?cè)诤笈_(tái)運(yùn)行,浪費(fèi)你的CPU和RAM。
特別重要的是要記住在$destroy函數(shù)調(diào)用中取消綁定在directives元素上定義的任何DOM事件偵聽(tīng)器。否則會(huì)導(dǎo)致舊版瀏覽器中的內(nèi)存泄漏,并在現(xiàn)代瀏覽器中減慢您的垃圾收集器。一個(gè)非常重要的推論是在刪除DOM之前調(diào)用scope.$destroy。

9.6 $evalAsync

scope.$evalAsync是一個(gè)強(qiáng)大的工具,可以讓您在當(dāng)前digest 循環(huán)結(jié)束時(shí)將操作排隊(duì)執(zhí)行,而不會(huì)使另一個(gè)digest 循環(huán)的scope 變臟。需要根據(jù)具體情況考慮這一點(diǎn),但是,如果這是預(yù)期的效果,evalAsync可以大大提高頁(yè)面的性能。

10指令問(wèn)題

10.1獨(dú)立作用域和嵌入

獨(dú)立作用域和嵌入是Angular最令人興奮的事情。它們?cè)试S構(gòu)建可重復(fù)使用的封裝組件,它們?cè)谡Z(yǔ)法和概念上都很優(yōu)雅,是Angular的核心部分。
但是,他們也是需要權(quán)衡的。默認(rèn)情況下,指令不會(huì)創(chuàng)建一個(gè)作用域,而是使用與其父元素相同的作用域。通過(guò)使用Isolate Scope或Transclusion創(chuàng)建新的scope,我們會(huì)創(chuàng)建一個(gè)新對(duì)象來(lái)跟蹤,并添加新的觀察者,這減慢我們的應(yīng)用程序。所以在使用這些技術(shù)之前,請(qǐng)先停下來(lái)思考。

10.2編譯周期

指令的compile函數(shù)在scope 附加之前運(yùn)行,是運(yùn)行任何DOM操作(例如綁定事件)的理想場(chǎng)所。 從性能的角度來(lái)看,重要的是,傳遞給編譯函數(shù)的元素和屬性表示原始的html模板,在進(jìn)行任何angular的更改之前。 這意味著在這里完成的DOM操作將運(yùn)行一次,并始終傳播。 經(jīng)常被忽略的另一個(gè)重點(diǎn)是prelink和postlink之間的區(qū)別。 簡(jiǎn)而言之,prelinks 從外而內(nèi)運(yùn)行,postlinks 而從內(nèi)而外運(yùn)行。 因此,prelinks提供輕微的性能提升,因?yàn)楫?dāng)父級(jí)修改prelink中的scope時(shí),它們會(huì)阻止內(nèi)部指令運(yùn)行第二個(gè)digest 循環(huán)。 但是,子DOM可能是不可用的。

11 DOM事件問(wèn)題

Angular提供了許多預(yù)先定義的DOM事件指令。 ng-click,ng-mouseenter,ng-mouseleave等。 所有這些調(diào)用scope.$apply() 每當(dāng)發(fā)生事件時(shí)。 一個(gè)更有效的方法是直接與addEventListener綁定,然后根據(jù)需要使用scope.$digest。

12總結(jié)

12.1 AngularJS:糟粕

  • ng-click 和 other DOM events
  • scope.$watch
  • scope.$on
  • Directive postLink
  • ng-repeat
  • ng-show and ng-hide

12.2 AngularJS:精華

  • track by
  • :: 單次綁定
  • compile 和 preLink
  • $evalAsync
  • Services, scope inheritance, passing objects by reference
  • $destroy
  • unbinding watches 和 event listeners
  • ng-if 和 ng-switch
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評(píng)論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,980評(píng)論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 64,064評(píng)論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評(píng)論 6 414
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 56,109評(píng)論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,287評(píng)論 0 291
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評(píng)論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評(píng)論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,327評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,667評(píng)論 1 296
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評(píng)論 2 380

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