從項目的整體架構來看,要選擇適合項目背景的極速。如果項目背景不適合使用狀態管理器,那就沒有一定的必要性去使用,比如微信小程序等,可以從以下幾個維度來看
什么是渲染劫持,渲染劫持的概念是控制組件從另一個組件輸出的能力,當然這個概念一般和react中的高階組件(HOC)放在一起解釋比較有明了。
高階組件可以在render函數中做非常多的操作,從而控制原組件的渲染輸出,只要改變了原組件的渲染,我們都將它稱之為一種渲染劫持。
實際上,在高階組件中,組合渲染和條件渲染都是渲染劫持的一種,通過反向繼承,不僅可以實現以上兩點,還可以增強由原組件 render 函數產生的 React元素。
實際的操作中通過操作 state、props 都可以實現渲染劫持
依賴于 i18next 的方案,對于龐大的業務項目有個很蛋疼的問題,那就是 json 文件的維護。每次產品迭代都需要增加新的配置,那么這份配置由誰來維護,怎么維護,都會有很多問題,而且如果你的項目要支持幾十個國家的語言,那么這幾十份文件又怎么維護。
所以現在大廠比較常用的方案是,使用 AST,每次開發完新版本,通過 AST 去掃描所有的代碼,找出代碼中的中文,以中文為 key,調用智能翻譯服務,去幫項目自動生成 json 文件。這樣,再也不需要人為去維護 json 文件,一切都依賴工具進行自動化。目前已經有大廠開源,比如滴滴的 di18n,阿里的 kiwi
我認為 react 的拆分前提是代碼目錄設計規范,模塊定義規范,代碼設計規范,符合程序設計的一般原則,例如高內聚、低耦合等等。
在我們的react項目中:
官網例子:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染能夠顯示降級后的 UI
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 你同樣可以將錯誤日志上報給服務器
logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// 你可以自定義降級后的 UI 并渲染
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
使用
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
但是錯誤邊界不會捕獲:
try{}catch(err){}
///異步代碼(例如 setTimeout 或 requestAnimationFrame 回調函數)
///服務端渲染
///它自身拋出來的錯誤(并非它的子組件)
保證react的單向數據流的設計模式,使狀態更可預測。如果允許自組件修改,那么一個父組件將狀態傳遞給好幾個子組件,這幾個子組件隨意修改,就完全不可預測,不知道在什么地方修改了狀態,所以我們必須像純函數一樣保護 props 不被修改
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App() {
const [data, setData] = useState({ hits: [] });
useEffect(async () => {
const result = await axios(
'https://api/url/to/data',
);
setData(result.data);
});
return (
<ul>
{data.hits.map(item => (
<li key={item.objectID}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
);
}
export default App;
不要在循環,條件或嵌套函數中調用 Hook, 確保總是在你的 React 函數的最頂層調用他們。
不要在普通的 JavaScript 函數中調用 Hook。你可以:
React15 的 StackReconciler 方案由于遞歸不可中斷問題,如果 Diff 時間過長(JS計算時間),會造成頁面 UI 的無響應(比如輸入框)的表現,vdom 無法應用到 dom 中。
為了解決這個問題,React16 實現了新的基于 requestIdleCallback 的調度器(因為 requestIdleCallback 兼容性和穩定性問題,自己實現了 polyfill),通過任務優先級的思想,在高優先級任務進入的時候,中斷 reconciler。
為了適配這種新的調度器,推出了 FiberReconciler,將原來的樹形結構(vdom)轉換成 Fiber 鏈表的形式(child/sibling/return),整個 Fiber 的遍歷是基于循環而非遞歸,可以隨時中斷。
更加核心的是,基于 Fiber 的鏈表結構,對于后續(React 17 lane 架構)的異步渲染和 (可能存在的)worker 計算都有非常好的應用基礎
參考官網
官網回答:
Hook 解決了我們五年來編寫和維護成千上萬的組件時遇到的各種各樣看起來不相關的問題。無論你正在學習 React,或每天使用,或者更愿嘗試另一個和 React 有相似組件模型的框架,你都可能對這些問題似曾相識。
React 沒有提供將可復用性行為“附加”到組件的途徑(例如,把組件連接到 store)。如果你使用過 React 一段時間,你也許會熟悉一些解決此類問題的方案,比如 render props 和 高階組件。但是這類方案需要重新組織你的組件結構,這可能會很麻煩,使你的代碼難以理解。如果你在 React DevTools 中觀察過 React 應用,你會發現由 providers,consumers,高階組件,render props 等其他抽象層組成的組件會形成“嵌套地獄”。盡管我們可以在 DevTools 過濾掉它們,但這說明了一個更深層次的問題:React 需要為共享狀態邏輯提供更好的原生途徑。
你可以使用 Hook 從組件中提取狀態邏輯,使得這些邏輯可以單獨測試并復用。Hook 使你在無需修改組件結構的情況下復用狀態邏輯。 這使得在組件間或社區內共享 Hook 變得更便捷。
我們經常維護一些組件,組件起初很簡單,但是逐漸會被狀態邏輯和副作用充斥。每個生命周期常常包含一些不相關的邏輯。例如,組件常常在 componentDidMount 和 componentDidUpdate 中獲取數據。但是,同一個 componentDidMount 中可能也包含很多其它的邏輯,如設置事件監聽,而之后需在 componentWillUnmount 中清除。相互關聯且需要對照修改的代碼被進行了拆分,而完全不相關的代碼卻在同一個方法中組合在一起。如此很容易產生 bug,并且導致邏輯不一致。
在多數情況下,不可能將組件拆分為更小的粒度,因為狀態邏輯無處不在。這也給測試帶來了一定挑戰。同時,這也是很多人將 React 與狀態管理庫結合使用的原因之一。但是,這往往會引入了很多抽象概念,需要你在不同的文件之間來回切換,使得復用變得更加困難。
為了解決這個問題,Hook 將組件中相互關聯的部分拆分成更小的函數(比如設置訂閱或請求數據),而并非強制按照生命周期劃分。你還可以使用 reducer 來管理組件的內部狀態,使其更加可預測。
除了代碼復用和代碼管理會遇到困難外,我們還發現 class 是學習 React 的一大屏障。你必須去理解 JavaScript 中 this 的工作方式,這與其他語言存在巨大差異。還不能忘記綁定事件處理器。沒有穩定的語法提案,這些代碼非常冗余。大家可以很好地理解 props,state 和自頂向下的數據流,但對 class 卻一籌莫展。即便在有經驗的 React 開發者之間,對于函數組件與 class 組件的差異也存在分歧,甚至還要區分兩種組件的使用場景。
另外,React 已經發布五年了,我們希望它能在下一個五年也與時俱進。就像 Svelte,Angular,Glimmer等其它的庫展示的那樣,組件預編譯會帶來巨大的潛力。尤其是在它不局限于模板的時候。最近,我們一直在使用 Prepack 來試驗 component folding,也取得了初步成效。但是我們發現使用 class 組件會無意中鼓勵開發者使用一些讓優化措施無效的方案。class 也給目前的工具帶來了一些問題。例如,class 不能很好的壓縮,并且會使熱重載出現不穩定的情況。因此,我們想提供一個使代碼更易于優化的 API。
為了解決這些問題,Hook 使你在非 class 的情況下可以使用更多的 React 特性。 從概念上講,React 組件一直更像是函數。而 Hook 則擁抱了函數,同時也沒有犧牲 React 的精神原則。Hook 提供了問題的解決方案,無需學習復雜的函數式或響應式編程技術
React 官網是這么簡介的。JavaScript library for building user interfaces.專注 view 層 的特點決定了它不是一個全能框架,相比 angular 這種全能框架,React 功能較簡單,單一。比如說沒有前端路由,沒有狀態管理,沒有一站式開發文檔等。
react 組件是根據 state (或者 props)去渲染頁面的,類似于一個函數,輸入 state,輸出 view。不過這不是完整意義上的 MDV(Model Driven View),沒有完備的 model 層。順便提一句,感覺現在的組件化和 MDV 在前端開發中正火熱,大勢所趨...
從我們最開始寫 React 開始,就了解這條特點了。state 流向是自組件從外到內,從上到下的,而且傳遞下來的 props 是只讀的,如果你想更改 props,只能上層組件傳下一個包裝好的 setState 方法。不像 angular 有 ng-model, vue 有 v-model, 提供了雙向綁定的指令。React 中的約定就是這樣,你可能覺得這很繁瑣,不過 state 的流向卻更清晰了,單向數據流在大型 spa 總是要討好一些的。
這些特點決定了,React 本身是沒有提供強大的狀態管理功能的,原生大概是三種方式。
它沒有提供生命周期概念,不像 class 組件繼承 React.component,可以讓你使用生命周期以及特意強調相關概念
使用字典樹持久化數據結構,更新時可優化對象生成邏輯,降低成本
dangerouslySetInnerHTML
react 基于虛擬 DOM 和高效 Diff算法的完美配合,實現了對 DOM最小粒度的更新,大多數情況下,React對 DOM的渲染效率足以我們的業務日常
復雜業務場景下,性能問題依然會困擾我們。此時需要采取一些措施來提升運行性能,避免不必要的渲染則是業務中常見的優化手段之一
在實際開發過程中,前端性能問題是一個必須考慮的問題,隨著業務的復雜,遇到性能問題的概率也在增高
除此之外,建議將頁面進行更小的顆粒化,如果一個過大,當狀態發生修改的時候,就會導致整個大組件的渲染,而對組件進行拆分后,粒度變小了,也能夠減少子組件不必要的渲染
高階函數(Higher-order function),至少滿足下列一個條件的函數
在React中,高階組件即接受一個或多個組件作為參數并且返回一個組件,本質也就是一個函數,并不是一個組件
const EnhancedComponent = highOrderComponent(WrappedComponent);
上述代碼中,該函數接受一個組件 WrappedComponent 作為參數,返回加工過的新組件 EnhancedComponent
高階組件的這種實現方式,本質上是一個裝飾者設計模式
Refs 在計算機中稱為彈性文件系統(英語:Resilient File System,簡稱ReFS)
React 中的 Refs提供了一種方式,允許我們訪問 DOM節點或在 render方法中創建的 React元素
本質為ReactDOM.render()返回的組件實例,如果是渲染組件則返回的是組件實例,如果渲染dom則返回的是具體的dom節點
class
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref="myref" />;
}
}
hooks
function App(props) {
const myref = useRef()
return (
<>
<div ref={myref}></div>
</>
)
}
作者:野生程序猿江辰
鏈接:https://juejin.cn/post/7280439887962144820
大型網站架構演化歷程:
架構演化-分布式服務
演化的價值觀
誤區
模式的關鍵在于模式的可重復性
架構是“最高層次的規劃,難以改變的規定”。主要關注五個要素:
下面依次對這五個要素進行歸納
性能的測試指標主要有:
性能測試方法:
性能測試曲線
性能優化,根據網站分層架構,可以分為三大類:
大型網站的“大型”是指:
伸縮性的分為如下幾個方面
系統架構設計層面的“開閉原則”
XSS 攻擊和 SQL 注入攻擊是構成網站應用攻擊最主要的兩種手段,此外還包括 CSRF,Session 劫持等手段。
最后針對于上面的知識點我總結出了 “怎樣學架構更有效” 做成了文檔和架構視頻資料免費分享給大家
希望能幫助到您提高自己的技術升職加薪,也節省大家在網上搜索資料的時間來學習,也可以關注我一下以后會有更多干貨分享。
轉發+關注私信回復【架構資料】領取技術資料【面試資料】
者: 彭道寬
轉發鏈接:https://mp.weixin.qq.com/s/dtmZv4YcQitbKajjNbW_Pg
*請認真填寫需求信息,我們會在24小時內與您取得聯系。