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