autoreleasepool梆造、分頁加載相結(jié)合解決卡頓崩潰優(yōu)化

? ? ? ? ?剛好端午節(jié)了如输,不想出去旅游看世界了,也不想把玩游戲了肠骆,也不想把妹(ps 其實是我沒有妹子可玩耍??尖坤,不要告訴別人溪窒,你知我知天知就好了???♂?)冬耿,剛好有時間靜下心來寫下在新公司的項目開發(fā)中遇到的問題和一些解決問題的心得舌菜,總結(jié)下來,也算是對那些被bug折磨的郁悶的日子的交代亦镶,同時也希望酷师,遇到同樣問題的你,因為看到這篇文章而少走彎路染乌,因為看到這篇文章而心花怒放,如此懂讯,我也倍感榮幸能幫到你荷憋!?

? ? 話不多說,下面我先簡略簡述下bug的背景和癥狀:

頁面如下:(原諒我對圖片做了必要的涂鴉??)

? ? ? ?一個tableView列表頁褐望,是一個群的成員列表頁面勒庄,UI元素很簡單,包含頭像瘫里、群角色实蔽、拼接的昵稱,原來業(yè)務代碼實現(xiàn)是一次性加載所有需要的數(shù)據(jù)源谨读,數(shù)據(jù)稍微多時局装,頁面卡頓,甚至會閃退劳殖,或者導致其他頁面不可測的卡頓铐尚、閃退,數(shù)據(jù)源大時哆姻,這個查看群組成員的功能基本報廢不能使用宣增,并且易導致app卡頓、閃退矛缨。

? ? ? 你一定會疑問爹脾,這不是及其簡單的頁面嘛帖旨,沒錯,你很聰明灵妨,這的確是極其簡單的頁面效果解阅;但是你看下群的成員是多少,沒錯是將近10萬人的群闷串,10萬瓮钥,也就意味著大量的數(shù)據(jù)源;可能你心里還在想烹吵,10萬人又咋了碉熄,我1000萬的數(shù)據(jù)源還處理過呢,分布加載不就解決問題了嘛肋拔;沒錯锈津,我完全相信你處理過1000萬的數(shù)據(jù)源,我也絕對相信你用分頁加載來控制用戶的行為來避免設備的cpu瞬時峰值過大凉蜂;但是琼梆,兄弟,不要慌窿吩,如你所以為的那樣茎杂,如果這個功能是我從0到1開發(fā),我也會如你所想的那樣分頁加載處理纫雁,可問題是煌往,這個項目是12年就運營的,目前代碼已經(jīng)小百萬行了轧邪,單單這個頁面控制器代碼也堆了足足1.4萬行刽脖,這里面牽涉了UI最終展示前的大量業(yè)務邏輯(比如踢人、新進群忌愚、群成員頭像/昵稱更換曲管、群成員角色變換等大概十來種業(yè)務)和相應業(yè)務操作對應的緩存處理邏輯,看到1.4萬行代碼外加十來種完全不知道的業(yè)務硕糊,兄弟院水,不用告訴我,我也知道你會一頭霧水(ps 技術(shù)溜的上云霄的小伙伴就自動屏蔽了?)癌幕;兄弟衙耕,也不要嗔怪為什么要在一個控制器里寫那么多代碼,接受當前的代碼事實是你應該也是唯一可做的事勺远,至于你看著不爽橙喘,決定要盤古開天劈地來重構(gòu)代碼,這是你接受事實后完全搞清楚這一塊功能后并且和相關(guān)開發(fā)端的同事評估效益比后才能想的事胶逢。眼下厅瞎,這邊領(lǐng)導給你說這問題很嚴重饰潜,要立即修復;那邊產(chǎn)品經(jīng)理過來說和簸,這個問題很嚴重彭雾,市場已經(jīng)嚴重抱怨甚至憤怒了,老板已經(jīng)嚴重關(guān)切這事了锁保,你要立刻馬上現(xiàn)在解決掉薯酝!所以,當前爽柒,你能做的就是梳理原來的業(yè)務代碼吴菠,找到造成卡頓、閃退的關(guān)鍵因素浩村,先臨時性修復這個問題做葵,后期可以再根據(jù)梳理結(jié)果來評估原來的代碼是否需要完全重構(gòu)!這是你最快也是應該唯一能最快解決這問題的態(tài)度心墅,盡管很難酿矢,依然要平靜的呼吸和說話,然后就埋頭讀代碼找坑點怎燥!

? ?暴露了瘫筐,暴露了我曾當過個把月iOS講師的事實??,講個bug解決點铐姚,講了一通在著手讀代碼找坑點前的心理活動和獨白严肪,加的戲份太多了,下面直接貼出來簡略的業(yè)務代碼:(代碼有點長谦屑,前方高能,請做好提前預警??)

// 讀取本地緩存數(shù)據(jù)源

- (void)getCacheContent{

?//?當前線程為主線程

?// 一頓業(yè)務操作略過細節(jié)

?// 從本地緩存讀取數(shù)據(jù) 獲得群組成員列表信息數(shù)組resultArray

NSDictionary* responseObject = [NSDictionary dictionaryWithContentsOfFile:kCachefilePath];?// kCachefilePath 為本地緩存文件地址

? ? NSMutableArray *resultArray = [NSMutableArray arrayWithArray:[responseObject objectForKey:@"info"]];

?// usersInfoDic是一個存放FriendInfoStructure成員個體對象的字典  tableview的數(shù)據(jù)源

?if?(!usersInfoDic) {

? ? ? ? usersInfoDic = [NSMutableDictionary dictionary];

? ? }

?//?tips 1?下面這一頓操作 是遍歷本地群組成員列表并對照本地數(shù)據(jù)庫做查詢對比處理 生成群組成員個人對象FriendInfoStructure 會創(chuàng)建大量對象

?for?(NSDictionary* dic?in?resultArray) {

//autoreleasepool 自動釋放池 能夠讓對象及時的銷毀 避免內(nèi)存峰值過高而閃退 ?這是我規(guī)避內(nèi)存峰值添加的?

//@autoreleasepool?{

? ? ? ? NSInteger userID = [[dic objectForKey:@"uid"] intValue];

? ? ? ? NSString* userIdString = [dic objectForKey:@"uid"];

?// 創(chuàng)建對象

? ? ? ? FriendInfoStructure* infoStructure = [FriendInfoStructure new];

?? ? ? ??infoStructure = [usersInfoDic objectForKey:userIdString];??

?if?(!infoStructure) {

?// 這一步是查詢本地數(shù)據(jù)庫 比對并做必要的一些處理

? ? ? ? ? ? infoStructure =

[self?getCacheInfoFromFMDB:userID];

? ? ? ? ? ? [usersInfoDic setObject:infoStructure forKey:userIdString];? ? ??

}?else?if?(infoVersion != infoStructure.groupInfoVersion) {

? ? ? ? ? ? infoStructure.groupInfoVersion = infoVersion;

?} ? ? ?}

? }

?}

? ? [tableView reloadData];

?// 從網(wǎng)絡上獲取最新的群組成員列表信息

?// 網(wǎng)絡數(shù)據(jù)請求放在這的目的就是 加載本地緩存的同時進行網(wǎng)絡最新數(shù)組加載 用戶先看到緩存數(shù)據(jù) 當網(wǎng)絡最新數(shù)據(jù)加載下來時再刷新 展示最新數(shù)據(jù)

[self?getTableData];

}


// 網(wǎng)絡數(shù)據(jù)源處理和本地數(shù)據(jù)源比對篇梭、更換處理

- (void)getTableData{

?//當前線程為子線程

?//一頓網(wǎng)絡請求的操作 返回字典類型的數(shù)據(jù)responseObject

? ? NSDictionary *responseObject;

?// 將網(wǎng)絡上下載的最新的群組成員信息存儲在本地緩存數(shù)據(jù)中 (注意氢橙,這個過程包含了替換原來的本地緩存數(shù)據(jù))

[responseObject writeToFile:kCachefilePath atomically:YES];

?// 解析到網(wǎng)路上獲取到的最新的群組成員信息列表resultArray

? ? resultArray = [NSMutableArray arrayWithArray:[responseObject objectForKey:@"info"]];

?if?(!usersInfoDic) {

? ? ? ? usersInfoDic = [NSMutableDictionary dictionary];

? ? }

std::vector<int> uid_vector;?// 注意 這是c++代碼?正如中國外交部的聲明一樣 字越少 信息量越大?因為我們項目架構(gòu)是?底層(數(shù)據(jù)層是c++代碼) + 中間層(c++代碼和oc代碼組成,目的是建立抽象層,使底層能兼容PC恬偷、Andriod悍手、Apple三端) + 高層(UI層),因此有c++代碼 這是一個巨坑 后面我會解釋為什么是一個巨坑

?//?tips 11下面的也是遍歷網(wǎng)絡上獲得的數(shù)據(jù) 并和本地緩存數(shù)據(jù)庫比對 會大量創(chuàng)建群組成員個人信息FriendInfoStructure對象

?for?(int?a = 0; a < (int)[resultArray count];

?? ? ? ? a++) {

//autoreleasepool 自動釋放池 能夠讓對象及時的銷毀 避免內(nèi)存峰值過高而閃退 ?這是我規(guī)避內(nèi)存峰值添加的?

//@autoreleasepool?{

? ? ? ? NSDictionary* dic =

? ? ? ? [resultArray objectAtIndex:a];

? ? ? ? NSInteger userID = [[dic objectForKey:@"uid"] intValue];

? ? ? ? NSString* userIdString = [dic objectForKey:@"uid"];

?// ?創(chuàng)建對象

? ? ? ? FriendInfoStructure* infoStructure = [FriendInfoStructure new];

? ? ? ? infoStructure = [usersInfoDic objectForKey:userIdString];


?if?(!infoStructure) {

?// 和本地緩存數(shù)據(jù)庫比對

? ? ? ? ? ? infoStructure =

[self?getCacheInfoFromFMDB:userID];

? ? ? ? ? ? [usersInfoDic setObject:infoStructure forKey:userIdString];? ? ? ? ??

//if?(self.needRequest) {

?self.needRequest =?NO;

uid_vector.push_back(userID);?//?這是上面c++ 代碼對應的業(yè)務 也是字越少 信息量越大

? ? ? // ? ? ? ? ? }? ? ? ??

}?else?if?(infoVersion != infoStructure.groupInfoVersion) {

? ? ? ? ? ? infoStructure.groupInfoVersion = infoVersion;

? ? ? ? }?? ? ? ?

? ? }??

?// 當所有網(wǎng)絡數(shù)據(jù)比對完 刷新UI

? ? [[NSOperationQueue mainQueue]

?? ? addOperationWithBlock:^{

?//?這兩行代碼及其關(guān)鍵 通過中間層觸發(fā)c++底層查詢?nèi)航M成員信息的條件 這是一個很不容易發(fā)現(xiàn)的坑 當初定位到這兩行代碼花費了我五六個小時的時間

?? ? ? ? [[[[AppDelegate appDelegate]

? ? ? ? ? ? sharedProtoEngine] sharedGroupEngine]

getGroupUserCardVecForGId:self.groupId

? ? ? ? ? forUserIdVec:uid_vector];??

?// 這個就是常規(guī)操作 刷新UI

?? ? ? ? [weakTableView reloadData];?? ? ? ?

?? ? }];

}


? ? 下面是我排查的思路:首先入手UI層袍患,然后分析數(shù)據(jù)層

1坦康、從UI層排查

?是個列表tableView,首先找到對應的數(shù)據(jù)源代理诡延,然后找對應的tableViewCell,看下cell內(nèi)部的UI控件繪制是否存在過度繪制滞欠、重復繪制、耗時繪制情況肆良,發(fā)現(xiàn)UI層都是常規(guī)操作筛璧,造成卡頓逸绎、閃退的不可能,當然如果是一直存在刷新的話夭谤,可能會因為cpu超負荷了而卡頓棺牧,但是這種極端情況幾乎不可能發(fā)生,即便發(fā)生了朗儒,cell是被動繪制颊乘,一定是其他地方觸發(fā)了一直刷新,原因在造成不停刷新的地方醉锄。UI的原因暫時沒有可能性

2乏悄、數(shù)據(jù)層排查

最開始,排查數(shù)據(jù)層我沒有采用額外的手段榆鼠,就是在xcode的對應的群組成員信息列表控制器過目下所有的方法纲爸,找到與數(shù)據(jù)源處理相關(guān)的方法,重點關(guān)注數(shù)據(jù)源的set方法入口處和get方法出口處妆够,然后识啦,一眼就看到上面讀取本地數(shù)據(jù)源的方法- (void)getCacheContent表tips 1處存在for循環(huán),然后在for循環(huán)里又執(zhí)行了創(chuàng)建對象的操作神妹,職業(yè)直覺颓哮,很顯然,當數(shù)據(jù)源很多時鸵荠,這里大量創(chuàng)建對象冕茅,并且是主線程中執(zhí)行的,必然的蛹找,數(shù)據(jù)源多時姨伤,for循環(huán)會耗費很長時間,自然出現(xiàn)卡頓庸疾,同時乍楚,由于短時間內(nèi)創(chuàng)建了大量對象,導致設備運行內(nèi)存急劇上升届慈,當時我用6p測試徒溪,當運行內(nèi)存達到650M左右時就閃退了,同時cpu甚至200%的超負荷運行金顿,不卡頓不閃退才怪臊泌!

同理,在- (void)getTableData tips 11處?網(wǎng)絡數(shù)據(jù)請求完也存在這樣的for循環(huán)揍拆,更為驚人的是渠概,這個for循環(huán)也放在主線程了,如此嫂拴,這樣大量消耗內(nèi)存和cpu的操作高氮,必然導致卡頓和閃退了慧妄,在某些數(shù)量的數(shù)據(jù)源區(qū)間里,app不會閃退剪芍,但是造成卡頓塞淹,cpu在設計時也有自己的保護機制,當其持續(xù)處于超負荷工作一段時間后罪裹,即便再進入超低負荷(如10%)運行也會有一定時間的卡頓饱普,直到cpu的保護機制閥值達到了,卡頓才會解除状共,因此當從群成員列表頁面退出后再進入其他頁面套耕,app其他頁面不明原因的卡頓也就不足為奇了!

因此峡继,為了規(guī)避內(nèi)存峰值過高而閃退冯袍,我在for循環(huán)里使用了autoreleasepool 自動釋放池 ,讓每個臨時創(chuàng)建的對象及時的銷毀碾牌,保證app不會內(nèi)存峰值過高康愤;?

?到這問題解決完了嘛,并沒有舶吗,遠著呢征冷!如果你仔細看了,你會發(fā)現(xiàn)誓琼,在for循環(huán)里存在從本地緩存數(shù)據(jù)庫中查找比對字段的操作检激,沒錯,存在這種操作的腹侣,并且是大量的查詢本地數(shù)據(jù)庫叔收,試想一個存有10萬條數(shù)據(jù)的數(shù)據(jù)庫去查找,是多么耗時傲隶,cpu會長時間超負荷工作的今穿,卡頓是必然的,因此伦籍,必須限制數(shù)據(jù)源加載的方式,保證一定時間內(nèi)不能有太多這種操作腮出,因此帖鸦,我改變了原來的數(shù)據(jù)交互方式,采用分頁加載的方式胚嘲,小手機每次加載50條數(shù)據(jù)作儿,大手機每次加載100條數(shù)據(jù),這樣就不會因為本地數(shù)據(jù)庫查詢而導致cpu超負荷工作了馋劈!

? ?到這攻锰,采用自動釋放池技術(shù)和分頁加載的交互方式晾嘶,從理論上,內(nèi)存過高和cpu滿負荷工作的因素都消除了娶吞,貌似可以6的飛起的運行app了垒迂。哼著小曲、滿心歡喜的comman + r 運行妒蛇,感覺自己已經(jīng)溜的飛起机断,從1.4萬行代碼和十多種業(yè)務交叉中竟找到了核心卡點,溜的不行不行的......結(jié)果绣夺,下一秒中吏奸,定睛一看,懷疑了人生陶耍,又卡了奋蔚、又閃退了,只是卡和閃退的時間點滯后了烈钞,不該呀泊碑、不會呀,都這么處理了怎么還不行呢棵磷,抓狂中抓狂中??????......

抓狂過后蛾狗,清醒了,不是卡頓仪媒、閃退滯后了嘛沉桌,說明數(shù)據(jù)源到UI刷新間還有坑點沒找到,說明整個卡頓算吩、閃退背后留凭,除了for循環(huán)和數(shù)據(jù)庫查詢導致外,還有其他原因偎巢!讀代碼中打斷點調(diào)試排查中......就這樣三四小時過去了蔼夜,還是沒定位到關(guān)鍵問題代碼處,這種通過讀代碼和打斷點調(diào)試的方式不行了压昼,效率太低求冷,也不容易找到問題點了。好窍霞,我就打開了xcode自帶的調(diào)試工具instruments匠题,然后然后在xcode --> Product ?--> Profile,打開instruments,選擇Time profile,運行app但金,發(fā)現(xiàn)tableView的reloadData,很長時間一直在執(zhí)行韭山,主線程一直滿負荷運行,沒錯,一定是哪個地方一直在觸發(fā)reloadData钱磅,在刷新相關(guān)處梦裂,通過打斷點、注釋代碼盖淡,終于找到關(guān)鍵代碼年柠,還記得前面我代碼里寫的c++代碼嘛,沒錯禁舷,就是 std::vector<int> uid_vector 和

?? ? ? ? [[[[AppDelegate appDelegate]

? ? ? ? ? ? sharedProtoEngine] sharedGroupEngine]

getGroupUserCardVecForGId:self.groupId

? ? ? ? ? forUserIdVec:uid_vector];??

后者是中間層的代碼彪杉,會調(diào)用底層(c++)獲取群組成員信息的api,然后牵咙,底層以每次10條數(shù)據(jù)返回客戶端派近,客戶端注冊了一個與之對應的觀察者,這樣底層每10條數(shù)據(jù)通知一下洁桌,列表就刷新一下渴丸,直至該群組成員信息下發(fā)完畢才停止下發(fā)數(shù)據(jù),列表才停止刷新另凌;后面的卡頓的原因就是這谱轨,底層數(shù)據(jù)回調(diào)的原因造成,然后就改變uid_vector.push_back(userID)的使用范圍(ps 改變奇執(zhí)行范圍吠谢,上述代碼中只是一部分)土童,至此,相信你也理解我在上面代碼中引用人們評價中國外交部的名言了:字越少 信息量越大 工坊,正是c++和oc語言的面向?qū)ο蟮奶匦韵缀梗阒荒芸吹綄ο笞罱K的使用,具體細節(jié)你不知道王污,當你知道你作用時罢吃,一切都好用,像我剛遇到的那樣昭齐,剛?cè)胧猪椖磕蛘校且徊糠謈++?代碼業(yè)務邏輯都沒人知道,自己入坑了也渾然不知阱驾,直到疼了才發(fā)現(xiàn)是入坑了就谜,這也是沒辦法的辦法,尤其對一些比較老且業(yè)務復雜的項目里覆,中間都不知換了多少波人了丧荐,很多代碼都沒人知道了,如此租谈,這樣只能自己先進坑,疼了再修復出坑了,沒辦法割去,古老的項目就是這樣的窟却,所以,老項目的問題修復及其的漫長且艱難郁悶呻逆。

??以上就是前段時間遇到的一個比價典型的復合型bug夸赫,同一個問題現(xiàn)象,但是導致其出現(xiàn)的原因是一層又一層的咖城,就這個卡頓茬腿、閃退bug,聽產(chǎn)品經(jīng)理和技術(shù)老大說宜雀,已經(jīng)困繞了他們幾年了切平,只從用戶量過百萬后就一直存在,但是一直沒人能耐心處理掉.....哦辐董,好吧悴品,暴露了,我承認我太老實了??简烘,他們竟然把我忽悠進坑給他們填坑了苔严,怪不的他們都把這個問題都立項了,修復完后孤澎,我才恍然大悟届氢,原來坑這么大,他們讓我成功入坑覆旭,還好我修復了成功出坑了???♂?

? ? 如果你能有耐心讀到這退子,并且還能保持著共鳴,我相信你在處理一些問題時姐扮,會有一個比較清晰的思路和心理預期絮供;再次感謝你耐心讀完這篇文章,寫的有點不像技術(shù)文章了??茶敏,倒像一篇bug產(chǎn)生到毀滅的回憶錄了??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壤靶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子惊搏,更是在濱河造成了極大的恐慌贮乳,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恬惯,死亡現(xiàn)場離奇詭異向拆,居然都是意外死亡,警方通過查閱死者的電腦和手機酪耳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門浓恳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刹缝,“玉大人,你說我怎么就攤上這事颈将∩液唬” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵晴圾,是天一觀的道長颂砸。 經(jīng)常有香客問我,道長死姚,這世上最難降的妖魔是什么人乓? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮都毒,結(jié)果婚禮上色罚,老公的妹妹穿的比我還像新娘。我一直安慰自己温鸽,他們只是感情好保屯,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涤垫,像睡著了一般姑尺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蝠猬,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天切蟋,我揣著相機與錄音,去河邊找鬼榆芦。 笑死柄粹,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的匆绣。 我是一名探鬼主播驻右,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼崎淳!你這毒婦竟也來了堪夭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤拣凹,失蹤者是張志新(化名)和其女友劉穎森爽,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嚣镜,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡爬迟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了菊匿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片付呕。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡计福,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出徽职,到底是詐尸還是另有隱情棒搜,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布活箕,位于F島的核電站,受9級特大地震影響可款,放射性物質(zhì)發(fā)生泄漏育韩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一闺鲸、第九天 我趴在偏房一處隱蔽的房頂上張望筋讨。 院中可真熱鬧,春花似錦摸恍、人聲如沸悉罕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壁袄。三九已至,卻和暖如春媚媒,著一層夾襖步出監(jiān)牢的瞬間嗜逻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工缭召, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留栈顷,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓嵌巷,卻偏偏與公主長得像萄凤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子搪哪,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

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

  • 使用Webpack的代碼分離實現(xiàn)Vue懶加載 當一個Vue的項目體積變得十分龐大的時候靡努,使用Webpack的代碼分...
    zdqlucky閱讀 156評論 0 0
  • if 的判斷 代碼示例 對于括號里的表達式,會被強制轉(zhuǎn)換為布爾類型噩死。轉(zhuǎn)換結(jié)果如下 Undefined:falseN...
    淺夢二十五夜閱讀 113評論 0 0
  • 第一章 項目介紹和前期準備 SpringBoot整合微信支付開發(fā)在線教育站點介紹 中大型公司里面項目開發(fā)流程 需求...
    LJasperliet閱讀 308評論 0 0
  • 女人一直喜用精致的骨瓷喝著純粹的水颤难,只因喜那份簡單而純粹。在這簡單中已维,滑過了青蔥年歲行嗤。許是年輪的變遷,許是某刻的歡...
    心中那片海藍藍閱讀 269評論 0 1
  • 今天的收獲: 1.規(guī)則是雙向的垛耳。 2.幫助孩子先敲門栅屏。 3.相信相信的力量飘千。 4.溫和而堅定。 5.不批評不指導不...
    尤占芳閱讀 53評論 0 0