摘要:前言距離我進(jìn)新公司也有一個(gè)多月,這一個(gè)月的事件使用寫了一個(gè)項(xiàng)目,期間斷斷續(xù)續(xù)重構(gòu)了兩三次,目前已經(jīng)完成第一階段測(cè)試,也總結(jié)分享一些使用的一些坑。因?yàn)樗牟豢勺兲攸c(diǎn),我們不會(huì)在不經(jīng)意見不小心改變了,而引起不必要的問題。
前言
距離我進(jìn)新公司也有一個(gè)多月,這一個(gè)月的事件使用react寫了一個(gè)項(xiàng)目,期間斷斷續(xù)續(xù)重構(gòu)了兩三次,目前已經(jīng)完成第一階段測(cè)試,也總結(jié)分享一些使用react的一些坑。
react先啰嗦幾句講一下react原理,新人可以認(rèn)真看下,老鳥可跳過。
react并沒有像其他如vue,ng一樣采用MVVM模式,所謂MVVM模式,狹義來說就是將模板與數(shù)據(jù)綁定在一起,當(dāng)數(shù)據(jù)發(fā)生改變時(shí),模板自動(dòng)更新,這是中間的VM,最左邊的M可以理解為我們看到的頁(yè)面,而最右邊的M可以理解為原始數(shù)據(jù)(例如數(shù)據(jù)庫(kù)數(shù)據(jù))。
其實(shí)要知道,這些框架模式歸根結(jié)底的目的希望使代碼更容易開發(fā)和維護(hù)。當(dāng)你寫一個(gè)小頁(yè)面你不覺得什么,但是當(dāng)你的頁(yè)面越來越龐大,越來越復(fù)雜,開發(fā)人員走了一批又一批的時(shí)候,你就會(huì)明白了。而如何解決,現(xiàn)在比較公認(rèn)的理念一個(gè)是組件化,將頁(yè)面拆分成一個(gè)個(gè)組件,其實(shí)拆分成組件的目的并不全是為了復(fù)用,我覺得更多是為了維護(hù);一個(gè)就是希望讓應(yīng)用層的編程能更專注于業(yè)務(wù)邏輯,那么這些框架都去做了處理,減少了大量DOM操作,讓業(yè)務(wù)開發(fā)更加專注。
那么我們看看react采用的是什么原理。其實(shí)react采用的方法簡(jiǎn)單粗暴:它并沒有對(duì)模板做數(shù)據(jù)綁定,而是每當(dāng)數(shù)據(jù)變化時(shí),就重新渲染模板。這有一個(gè)很大的好處就是每當(dāng)數(shù)據(jù)變化時(shí),對(duì)頁(yè)面來說只有一次IO操作,而單純的雙向綁定更新DOM會(huì)有很多次;但有一個(gè)問題,如果只改變了一個(gè)dom的數(shù)據(jù),整個(gè)模板都會(huì)重新渲染。那react解決的方法是每當(dāng)數(shù)據(jù)改變時(shí),就進(jìn)行對(duì)比。
那么該如何對(duì)比呢,最簡(jiǎn)單的方法是每當(dāng)數(shù)據(jù)改變,就去頁(yè)面獲取相應(yīng)的DOM信息,然后與現(xiàn)在的DOM信息做比較。這個(gè)方法有個(gè)致命的缺點(diǎn)就是每次有DOM改變,就會(huì)有許多讀取操作,IO操作太多,很影響性能。那么可以通過空間換時(shí)間的方法,將DOM信息保存起來,就避免了去頁(yè)面獲取信息的IO操作。那么我們看看一個(gè)真實(shí)DOM有多少數(shù)據(jù)
虛擬DOM如果我們把所有原生DOM緩存起來進(jìn)行比較顯然內(nèi)存會(huì)爆炸,而我們所需要的僅僅是幾個(gè)為數(shù)不多的狀態(tài)信息(例如style啊這些),這時(shí)虛擬DOM應(yīng)運(yùn)而生,如果說原生DOM是一塊豬肉,那么虛擬DOM就是這塊豬肉中多精肉,他剔除了那些對(duì)我們來說沒有太多意義相反還占內(nèi)存的狀態(tài)信息,而只將我們所需要的內(nèi)容留了下來。那虛擬DOM該如何比較呢,就涉及到了虛擬DOM的diff算法。
diff算法簡(jiǎn)單來說兩個(gè)模板就像兩棵樹一樣,傳統(tǒng)的樹對(duì)比的時(shí)間復(fù)雜度是O^3,也就是說要整棵樹遍歷三次,那react根據(jù)DOM的特點(diǎn):跨層級(jí)的操作較少。什么叫跨層級(jí),舉個(gè)例子一個(gè)組件有三個(gè)層級(jí)關(guān)系(嵌套三層),把第二層的div放到第三層就屬于跨層級(jí)操作。這種操作其實(shí)還是比較少的,react官方也不推薦這么寫。那么利用這個(gè)特點(diǎn),react只diff同層級(jí)的DOM。這里涉及以下幾種情況
tag變化(標(biāo)簽變化)
屬性變化
第二種沒什么好說,就是進(jìn)行同層級(jí)對(duì)比。這里詳細(xì)說一下第一種變化,react的方法是當(dāng)前層級(jí)往下全部刪除替換,簡(jiǎn)單暴力。在業(yè)務(wù)開發(fā)來看,你同層級(jí)類型都不同了,比如div變成了input,那么你的子組件相同的幾率也較小,因此不如整個(gè)替換簡(jiǎn)單暴力。同時(shí)這也說明為什么列表需要key屬性,因?yàn)榱斜砗芏嗟膭h除操作對(duì)于react來說是不知道的,它需要一個(gè)key來了解到底誰(shuí)是誰(shuí)。
踩過的一些坑 state作為前端,拿到原型第一件事就是要與你的產(chǎn)品充分溝通,評(píng)估該項(xiàng)目是否需要引入redux,那么如何確定需要引入redux呢,這邊有幾點(diǎn):
頁(yè)面之間組件之間通信較多,且是跨層級(jí)的;
頁(yè)面的交互邏輯較復(fù)雜,且經(jīng)常引起多處組件變化。
再然后就是對(duì)state的設(shè)計(jì)。對(duì)于后臺(tái)的返回的數(shù)據(jù),你并不知道到底哪些是有用的,哪些可能現(xiàn)在沒用以后有用,因此我的建議是對(duì)于每個(gè)api都將它存在一個(gè)object里。那么組件該如何去獲取,首先不能全部通過頂部container獲取依次往下傳,也不能粒度很細(xì)的去一個(gè)個(gè)connect,我的建議是對(duì)于一個(gè)object,可以用一個(gè)container去connect,粒度把握主要看你的業(yè)務(wù)需求。
還有一個(gè)要不要全局都使用redux。我的觀點(diǎn)是否定的,我認(rèn)為對(duì)于局部一個(gè)組件內(nèi)的狀態(tài)完全可以通過setState來滿足。
圖片處理首先將圖片做一些劃分。例如以500k作為分界,小于500k為小圖片,否則是大圖片。對(duì)于小圖片,我們需要做如下判斷:
頁(yè)面是否重復(fù)使用?是就用雪碧圖,否則轉(zhuǎn)base64.
對(duì)于大圖片,可以進(jìn)行壓縮后使用。
base64可以用webpack的url-loader替換。
舉個(gè)例子
require("url?limit=250!./xxx.png") //這里就會(huì)使用url-loader,假如圖片小于250,就會(huì)轉(zhuǎn)為base64移動(dòng)端適配
對(duì)于適配,我所知比較好的方法是利用rem作為單位,將頁(yè)面寬度等分成10個(gè)rem,根據(jù)頁(yè)面動(dòng)態(tài)的用js去改變font-size,達(dá)到適配不同瀏覽器的目的。例如愛瘋寬320px,那么font-size設(shè)置為32px。那么10rem就是等于整個(gè)屏幕的寬度。但是有一個(gè)特例就是高清屏,一般高清屏的物理像素是實(shí)際像素的2倍,那么當(dāng)你想顯示一個(gè)寬度為1的邊框時(shí),在普通屏幕是1px,在高清屏可以有0.5px(問題是很多瀏覽器不支持,為將0.5px認(rèn)為是0)。雖然都使用1px在兩者屏幕上實(shí)際上是一樣的,但是高清屏里的1px在射雞師眼里是無法達(dá)到他對(duì)于1的要求的。于是就有一些解決方案,比較簡(jiǎn)單是是使用transform:scale(0.5)。那么還有一種解決方案就是阿里的移動(dòng)端解決方案,原理是將頁(yè)面整體scale縮小,然后放大font-size,來保證rem為單位的布局不變,但是px為單位的會(huì)被縮小。
性能提升首先先確定需求,確實(shí)有這個(gè)需求的時(shí)候再談。
懶加載webpack其實(shí)會(huì)幫我們做第三方依賴的懶加載處理,那么針對(duì)react,我們可以通過現(xiàn)成的庫(kù)來實(shí)現(xiàn)懶加載react-lazyload,或者使用webpack現(xiàn)成的
require.ensure([],()=>{ require("public.js") })
來實(shí)現(xiàn)。
shouldComponentUpdate其實(shí)這個(gè)鉤子可以極大的幫助我們?nèi)ヌ嵘阅?,由于它的存在,我們可以自己判斷哪些是我們組件需要的state,哪些是不需要的,那么這就可以阻止react進(jìn)行不必要diff。但是有一個(gè)問題就是對(duì)于對(duì)象我們很難去判斷他們是否相等,那么可以通過immutableJs的fromJS和is方法來解決這個(gè)問題。其實(shí)immutableJs的好處遠(yuǎn)不止于此,目前我也尚在填坑中。
創(chuàng)建組件的痛點(diǎn)使用不可變數(shù)據(jù),可以更好的達(dá)到函數(shù)式編程,不僅利于單元測(cè)試,也更有利于后期維護(hù)整個(gè)大的state。因?yàn)樗牟豢勺兲攸c(diǎn),我們不會(huì)在不經(jīng)意見不小心改變了state,而引起不必要的問題。
為了使組件中的css作用域相互獨(dú)立,一般采用Css Module,那么為了使組件看上去更像組件,并且易于后期維護(hù),一般我們會(huì)這樣結(jié)構(gòu)化組件文件:
那么對(duì)于每一個(gè)初始的jsx,我們大多會(huì)這樣初始化
import s from "./App.scss" import{Component} from "react";//得到組件方法 class App extends Component{ render(){ return () } } export default App;
不難發(fā)現(xiàn),對(duì)于每一個(gè)組件,我都需要去手動(dòng)的創(chuàng)建這些文件和文件夾,而這些操作其實(shí)是重復(fù)且無意義的勞動(dòng),于是我造了一個(gè)小輪子,一個(gè)命令行小工具,來解決這個(gè)痛點(diǎn)。
react-component-maker,歡迎猛戳點(diǎn)star!
困了,本寶寶要睡覺了,還有的內(nèi)容下次再說吧,再見。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/91104.html
摘要:同構(gòu)的關(guān)鍵要素完善的屬性及生命周期與客戶端的時(shí)機(jī)是同構(gòu)的關(guān)鍵。的一致性在前后端渲染相同的,將輸出一致的結(jié)構(gòu)。以上便是在同構(gòu)服務(wù)端渲染的提供的基礎(chǔ)條件??梢詫⒎庋b至的中,在服務(wù)端上生成隨機(jī)數(shù)并傳入到這個(gè)中,從而保證隨機(jī)數(shù)在客戶端和服務(wù)端一致。 原文地址 React 的實(shí)踐從去年在 PC QQ家校群開始,由于 PC 上的網(wǎng)絡(luò)及環(huán)境都相當(dāng)好,所以在使用時(shí)可謂一帆風(fēng)順,偶爾遇到點(diǎn)小磕絆,也能夠...
摘要:前端每周清單半年盤點(diǎn)之與篇前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開發(fā)教程工程實(shí)踐深度閱讀開源項(xiàng)目巔峰人生等欄目。與求同存異近日,宣布將的構(gòu)建工具由遷移到,引發(fā)了很多開發(fā)者的討論。 前端每周清單半年盤點(diǎn)之 React 與 ReactNative 篇 前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為...
摘要:之前分享過幾篇關(guān)于技術(shù)棧的原創(chuàng)文章解析前端架構(gòu)學(xué)習(xí)復(fù)雜場(chǎng)景數(shù)據(jù)設(shè)計(jì)干貨總結(jié)打造單頁(yè)應(yīng)用一個(gè)項(xiàng)目理解最前沿技術(shù)棧真諦一個(gè)工程實(shí)例今天進(jìn)一步剖析一個(gè)實(shí)際案例移動(dòng)網(wǎng)頁(yè)版。目前面臨的問題在于提高產(chǎn)品的各方面性能體驗(yàn)。 之前分享過幾篇關(guān)于React技術(shù)棧的原創(chuàng)文章: 解析Twitter前端架構(gòu) 學(xué)習(xí)復(fù)雜場(chǎng)景數(shù)據(jù)設(shè)計(jì) React Conf 2017 干貨總結(jié)1: React + ES next ...
摘要:利用中間件實(shí)現(xiàn)異步請(qǐng)求,實(shí)現(xiàn)兩個(gè)用戶角色實(shí)時(shí)通信。目前還未深入了解的一些概念。往后會(huì)寫更多的前后臺(tái)聯(lián)通的項(xiàng)目。刪除分組會(huì)連同組內(nèi)的所有圖片一起刪除。算是對(duì)自己上次用寫后臺(tái)的一個(gè)強(qiáng)化,項(xiàng)目文章在這里。后來一直沒動(dòng),前些日子才把后續(xù)的完善。 歡迎訪問我的個(gè)人網(wǎng)站:http://www.neroht.com/? 剛學(xué)vue和react時(shí),利用業(yè)余時(shí)間寫的關(guān)于這兩個(gè)框架的訓(xùn)練,都相對(duì)簡(jiǎn)單,有的...
摘要:將它開源出來,希望能給某些同學(xué)帶來幫助,如果有設(shè)計(jì)的不好的地方,也希望能及時(shí)指出,共同進(jìn)步。和為組件,下的文件一般為直接配合路由使用的包裝組件,為具體業(yè)務(wù)組件,這個(gè)地方有的規(guī)范將組件分為三層,我個(gè)人認(rèn)為這個(gè)必要性不大。 個(gè)人學(xué)習(xí)使用react已經(jīng)有一段時(shí)間了,雖然沒有在真正的產(chǎn)品項(xiàng)目中大規(guī)模使用react,但是在自己的博客、小網(wǎng)站、一些開源項(xiàng)目中已經(jīng)使用過好幾次了,使用react創(chuàng)建項(xiàng)...
閱讀 2970·2021-10-14 09:42
閱讀 3672·2021-10-11 10:59
閱讀 3009·2019-08-30 11:25
閱讀 3137·2019-08-29 16:25
閱讀 3280·2019-08-26 17:40
閱讀 1322·2019-08-26 13:30
閱讀 1214·2019-08-26 11:46
閱讀 1385·2019-08-23 15:22