1.vue-router 和 react-router的區(qū)別
首先,我們先看一下在vue-router和react-router中的用法本質(zhì)
Vue-Router
- hash:使用URL hash值來作路由涯鲁。默認(rèn)模式
- history:依賴HTML5 History API和服務(wù)器配置晶丘。查看HTML5 History模式。
- abstract:支持所有的JavaScript運(yùn)行環(huán)境跛十,入Node.js服務(wù)器端
React-Router
- <HashRouter>URL格式為Hash路由組件
- <MemoryRouter>內(nèi)存路由組件
- <NativeRouter>Native的路由組件
- <StaticRouter>地址不改變的靜態(tài)路由組件
了解以上知識后彤路,我們看一下前端路由的本質(zhì):
前端路由本質(zhì)的兩種支持:(改變視圖的同時不會向后端發(fā)出請求)
1.hash——即地址欄URL中的#符號以及之后的數(shù)據(jù)。
2.history——利用了HTML5 History Interface中新增的pushState()和replaceState()方法芥映。(使用需要注意兼容性)(Apache或者Nginx需要配置)
前端路由洲尊,簡單來說,就是當(dāng)瀏覽器的url產(chǎn)生變化時奈偏,不向服務(wù)器進(jìn)行請求坞嘀,而是直接控制前端頁面產(chǎn)生變化,以期待前端在比如功能切換時惊来,產(chǎn)生類似頁面跳轉(zhuǎn)等效果丽涩。
典型代碼:
vue-router
JS:
const Foo = { template: '<div>foo</div>' } //聲明的組件
const Bar = { template: '<div>bar</div>' }
const routes = [ //聲明的路由數(shù)據(jù),數(shù)組包對象
{ path: '/foo', component: Foo }, //路徑+組件 需要的數(shù)據(jù)
{ path: '/bar', component: Bar }
]
const router = new VueRouter({ //new了一個路由實(shí)例,傳入?yún)?shù)routes
routes
})
const app = new Vue({ //new一個vue實(shí)例矢渊,傳入一個router參數(shù)
router
}).$mount('#app')//掛載到#app dom上
HTML:
<div id="app">
<h1>Hello App!</h1>
<p>
<router-linkto="/foo">Go to Foo</router-link> //路由跳轉(zhuǎn)組件继准,點(diǎn)擊跳到/foo
<router-linkto="/bar">Go to Bar</router-link>
</p>
<!-- 路由出口-->
<router-view></router-view> // 展示匹配到的組件
</div>
react-router
JS/JSX:
// modules/Foo.js
import React from 'react'
export default React.createClass({ //導(dǎo)出一個類組件
render() {
return<div>Foo</div>
}
})
// modules/Bar.js
import React from 'react'
export default React.createClass({ //導(dǎo)出一個bar
render() {
return<div>Bar</div>
}
})
// index.js
// ...配置路由信息 , 需要引入配置的組件
render((
<Routerhistory={hashHistory}> //聲明路由使用模式
<Route path="/" component={App}> //主路由入口
<Route path="/foo" component={Foo}/> //子路由
<Route path="/bar" component={Bar}/>
</Route>
</Router>
), document.getElementById('app'))
// modules/App.js
// ...
render() {
return (
<div>
<h1>React RouterTutorial</h1>
<ulrole="nav">
<li><Linkto="/foo">Go To Foo</Link></li> //linkto 跳轉(zhuǎn)到foo
<li><Linkto="/bar">Go To Bar</Link></li> //linkto 跳轉(zhuǎn)到bar
</ul>
{/* 路由匹配到的組件將渲染在這里 */}
{this.props.children} //子組件作為children傳入父組件
</div>
)
}
// ...
接下來我們回到主題:vue-router和react-router的區(qū)別
本質(zhì)區(qū)別:
- vue-router是全局配置方式矮男,react-router是全局組件方式
- vue-router僅支持對象形式的配置移必,react-router支持對象形式和jsx語法的組件形式配置。
- vue-router任何組件都會被渲染到<router-view/>的位置毡鉴,react-router子組件作為children被傳入父組件崔泵。而根組件被渲染到<Router/>位置。
- 使用方式上的不同猪瞬,獲取參數(shù)的方式不同
vue-router 使用:<router-link> <router-view>
reacrt-router使用:router包裹憎瘸,<linkto="" > <route>
vue-router獲取參數(shù):this.$router //全局路由的實(shí)例 this.$route //當(dāng)前的路由信息
react-router獲取參數(shù):import {userParams} from "react-router-dom" let {id}=useParams()
2.如果你是管理員,做管理系統(tǒng)項目撑螺,vue和react你會怎么選擇
vue適合webapp含思,適合做用戶交互多,各種動態(tài)效果變化豐富的應(yīng)用甘晤。特別是PC含潘、手機(jī)的網(wǎng)頁版,商城等頁面线婚。
原因:vue實(shí)現(xiàn)邏輯復(fù)雜的功能比較簡單遏弱。
react適合oa系統(tǒng),適合大批量的數(shù)據(jù)展示塞弊、適合做大型應(yīng)用漱逸。特別適合公司的后臺管理系統(tǒng)。
原因:react對那種比較復(fù)雜的交互游沿,實(shí)現(xiàn)起來比較麻煩饰抒,沒有vue方便。同時react的渲染原理是渲染整個組件樹诀黍,所以袋坑,一方面是費(fèi)性能,而且代碼寫起來邏輯復(fù)雜眯勾。但是react對批量數(shù)據(jù)操作很厲害枣宫。
總而言之,項目要求比較高的適合使用react吃环,因?yàn)閞eact的社區(qū)更活躍一些也颤,尤其是各種UI框架比較穩(wěn)定、系統(tǒng)郁轻,可以信賴翅娶。Vue的社區(qū)也很活躍,但相對而言各種組件五花八門,大多數(shù)不夠完善故觅,缺乏系統(tǒng)性和迭代性厂庇,對于項目的后期維護(hù)和新手入手都不太友好渠啊。
從應(yīng)用上來看输吏,react打出來的包會大一些,相對來說替蛉,vue的包小一些贯溅,如果項目場景對加載速度由要求,建議使用vue躲查。
3.react的生命周期
掛載
constructor():組件的初始化
componentWillMount:組件將要掛載時促發(fā)
render()渲染
componentDidMount:組件第一次掛載完成時觸發(fā)
更新
shouldComponentDidMount:是否需要更新數(shù)據(jù)它浅,返回false則不更新
componentWillUpdate:將要更新數(shù)據(jù)觸發(fā)
componentDidUpdate:組件更新完成觸發(fā)
卸載
componentWillUnmount:組件銷毀的時候觸發(fā)
16.3版本后新增:getDerivedStateFrinOrios前面要加上static保留字,聲明為靜態(tài)方法镣煮,不然會被react忽略掉姐霍,不常用,componentWillMount典唇,componentWillUpdate棄用
4.渲染一個react組件的過程
1.在組件渲染過程中镊折,會先走constructor處理里面的邏輯,如:設(shè)置初始的state
2.再執(zhí)行g(shù)etDeriveStateFromProps鉤子介衔,return prevProps的操作就是將props的內(nèi)容映射到state中恨胚,使用getDeriveStateFromProps鉤子,需要先使用this.state
3.組件渲染的過程中都會走一遍componentDidMount鉤子
4.如果有觸發(fā)state更新炎咖,鉤子會從getDeriveStateFromProps開始處理
5.再執(zhí)行shouldComponentUpdate鉤子赃泡,滿足條件后返回true觸發(fā)更新走render函數(shù)
6.render之后還要看是否有進(jìn)一步的更新操作
7.看是否有g(shù)etSnapshotBeforeUpdate鉤子攔截 它的返回值是componentDidupdate鉤子的第三個參數(shù)snapshot
8.不管有咩有g(shù)etSnapshotBeforeUpdate,都會走到componentDidUpdate鉤子乘盼,如果再這個過程中還有操作引起state的內(nèi)容變化升熊,會再次從getDerivedStateFromProps --- shouldComponentUpdate --- render ---getSnapshotBeforeUpdate --- componentDidUpdate
5.如果進(jìn)行三次setState會發(fā)生什么,循環(huán)執(zhí)行setState組件會一直重新渲染嗎
setState這個方法是用來告訴react組件數(shù)據(jù)有更新绸栅,有可能需要重新渲染级野。它是異步的,react通常會集齊一批需要更新的組件阴幌,然后一次性更新來保證渲染的性能勺阐,所以進(jìn)行三次只有一次的效果,并不會導(dǎo)致多次渲染矛双。
此外再使用setState改變狀態(tài)之后渊抽,立刻使用this.state去拿最新的狀態(tài)往往是拿不到的,如果需要最新的state做業(yè)務(wù)的話议忽,可以在componentDidUpdate或者setState的回調(diào)函數(shù)里獲取懒闷。(官方推薦第一種)
6.react diff的原理
1.React通過制定大膽的diff策略,將 O(n3) 復(fù)雜度的問題轉(zhuǎn)換成 O(n) 復(fù)雜度的問題;
React是如何將O(n3) 復(fù)雜度的問題轉(zhuǎn)換成 O(n) 的愤估?
-只進(jìn)行同級比較
-不同類的React組件會被當(dāng)做完全不同的DOM結(jié)構(gòu)而被完全替換
-key prop:開發(fā)人員可以通過給Virtual DOM一個唯一的key屬性暗示React這是同一個DOM結(jié)構(gòu)帮辟,反之若key值不同則會被當(dāng)做完全不同的DOM結(jié)構(gòu)。
2.React通過分層求異的策略玩焰,對tree diff進(jìn)行算法優(yōu)化由驹;
3.React通過相同類生成相似樹形結(jié)構(gòu),不同類生成不同樹形結(jié)構(gòu)的策略昔园,對component diff進(jìn)行算法優(yōu)化蔓榄。
4.React通過設(shè)置唯一key的策略,對element diff進(jìn)行算法優(yōu)化默刚;
5.建議疹鳄,在開發(fā)組件時蜒谤,保持穩(wěn)定的DOM結(jié)構(gòu)會有助于性能的提升;
6.建議,在開發(fā)過程中虑乖,盡量減少類似將最后一個節(jié)點(diǎn)移動到列表首部的操作声离,當(dāng)節(jié)點(diǎn)數(shù)量過大或更新操作過于頻繁時楣铁,在一定程度上會影響React的渲染性能侈百。