人妻少妇乱子伦精品_日韩人妻潮喷视频网站_日本最新最全无码不卡免费_日韩AV无码中文

當前位置: 首頁 > 科技新聞 >

從事前端多年,我是這樣看待三大框架的

時間:2020-06-23 17:42來源:網(wǎng)絡(luò)整理 瀏覽:
Vue、Angular、React對比前端在復(fù)雜性日增的今天,三個框架被我們熟知,Vue、React、Angular,三個經(jīng)常經(jīng)常被我們拿來
Vue、Angular、React對比

前端在復(fù)雜性日增的今天,三個框架被我們熟知,Vue、React、Angular,三個經(jīng)常經(jīng)常被我們拿來討論,對比,比如學(xué)習(xí)哪個?

從事前端多年,我是這樣看待三大框架的

前端框架解決的核心問題

在我入門的時候,第一個學(xué)習(xí)的就是Vue,基本跳過了后臺php、jsp結(jié)合JQuery,三個框架成為了開發(fā)三選一的問題,在后面的工作和學(xué)習(xí)中,我逐漸意識到前框框架解決的核心問題在于數(shù)據(jù)和視圖同步,我也發(fā)現(xiàn)挺多人意識到了這一點,并且在向大眾普及這個前端需要解決的核心問題

前端框架如何解決數(shù)據(jù)向視圖的復(fù)雜映射

我們說目前前端的核心問題是數(shù)據(jù)和視圖的同步,這里我姑且采用了一個個人覺得更適合的名詞,數(shù)據(jù)到視圖的映射,那么框架們是以怎么樣的思路思考這個問題的呢,我們這里開展一個功能實現(xiàn)的討論,首先是JQuery實現(xiàn),我們需要更新輸入框值

直接命令式
// 當前用戶名的值
let curUsername = 'cj'
// 找到類名為username的元素
let username = $('.username')
// 設(shè)置username為cj
username.val(curUsername)

按照以下步驟,即可完成我們的小需求

定義修改的值找到需要修改的元素修改元素的值為我們給定的值

問題

這里找到元素、設(shè)置元素的值,明顯是很命令式的寫法,如果我們需要多次操作,一個簡單的方法就是多次重復(fù)這段代碼

使用函數(shù)維護
function updateUsername(username) {
let usernameInput = $('.username')
usernameInput.val(username)
}

let curUsername = 'cj'
updateUsername(curUsername)

從上述代碼可以抽象出,我們只需要關(guān)心改變的值和改變的元素,其他細節(jié)是我們不需要知道的,中間選取元素、修改元素在過程中可以認為是完全抽離成一個新的抽象,下面就是基于這一點的思考

更深的思考

既然我們關(guān)注的點在于目標元素、數(shù)據(jù),這兩者可以在編譯時確定,只要我們更新這個數(shù)據(jù),系統(tǒng)就更新對應(yīng)引用這個數(shù)據(jù)的元素,從而將我們從指定元素、修改元素的重復(fù)勞動中脫離出來,這是一個基本的思路,當然Vue采用的是上述的思路,而React采用的是暴力diff的方式


目前實現(xiàn)Vue綁定數(shù)據(jù)和節(jié)點在一起,在數(shù)據(jù)更新時,更新對應(yīng)的元素React比較直接,直接對整個組件diff,找到前后不同的地方,內(nèi)部根本不需要知道數(shù)據(jù)和節(jié)點的對應(yīng)關(guān)系A(chǔ)ngular,接觸很少,目前好像是臟檢查和proxy結(jié)合關(guān)于Virtual DOM解決的問題

目前來說,Virtual DOM 和配套的diff算法,逐漸出現(xiàn)在大家面前,這里我們?yōu)槭裁匆脒@兩套技術(shù)?,大家其實看的也多了,解決DOM更新緩慢,跨平臺等,那么它引入的初心是什么,這還得看React為什么要引入它


為什么需要Virtual DOM

Virtual DOM是由React推出時引入的技術(shù),個人理解是,React系統(tǒng)不知道數(shù)據(jù)對應(yīng)的節(jié)點是哪些,所以按照常規(guī)方式來說,肯定是要更新全部節(jié)點,React需要一種在操作節(jié)點之前用于性能優(yōu)化的一套方案,這就是React引入Virtual DOM技術(shù)的初心

Vue為什么引入Virtual DOM

目前很多Vue響應(yīng)式基本實現(xiàn)會像以下一樣:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id='app'>
<h3>姓名</h3>
<p>{{name}}</p>
<h3>年齡</h3>
<p>{{age}}</p>
</div>
</body>
</html>
<script>
document.addEventListener('DOMContentLoaded', function(){
let opt = {el:'#app', data:{name:'檢索中...', age:30}}
let vm = new Vue(opt)
setTimeout(() => {
opt.data.name = '王永峰'
}, 2000);
}, false)
class Vue{
constructor(opt){
this.opt = opt
this.observe(opt.data)
let root = document.querySelector(opt.el)
this.compile(root)
}
// 為響應(yīng)式對象 data 里的每一個 key 綁定一個觀察者對象
observe(data){
Object.keys(data).forEach(key => {
let obv = new Observer()
data["_"+key] = data[key]
// 通過 getter setter 暴露 for 循環(huán)中作用域下的 obv,閉包產(chǎn)生
Object.defineProperty(data, key, {
get(){
Observer.target && obv.addSubNode(Observer.target);
return data['_'+key]
},
set(newVal){
obv.update(newVal)
data['_'+key] = newVal
}
})
})
}
// 初始化頁面,遍歷 DOM,收集每一個key變化時,隨之調(diào)整的位置,以觀察者方法存放起來
compile(node){
[].forEach.call(node.childNodes, child =>{
if(!child.firstElementChild && /\{\{(.*)\}\}/.test(child.innerHTML)){
let key = RegExp.$1.trim()
child.innerHTML = child.innerHTML.replace(new RegExp('\\{\\{\\s*'+ key +'\\s*\\}\\}', 'gm'),this.opt.data[key])
Observer.target = child
this.opt.data[key]
Observer.target = null
}
else if (child.firstElementChild)
this.compile(child)
})
}
}
// 常規(guī)觀察者類
class Observer{
constructor(){
this.subNode = []
}
addSubNode(node){
this.subNode.push(node)
}
update(newVal){
this.subNode.forEach(node=>{
node.innerHTML = newVal
})
}
}
</script>

上述代碼是Vue1的核心實現(xiàn)簡化,每個數(shù)據(jù)知道引用自己的精確節(jié)點,Vue的實現(xiàn)是在每個節(jié)點編譯,引用數(shù)據(jù)時都為其生成一個Watcher,顯而易見,為每一個引用數(shù)據(jù)的節(jié)點都要生成一個Watcher,是有比較大的內(nèi)存壓力,如何解決,很簡單,將粒度提升到組件級別,將低粒度的diff交給Virtual DOM

前端框架認知反思

框架解決的核心是選擇節(jié)點,操作節(jié)點這一過程的抽象,將其隱藏在框架實現(xiàn)之內(nèi),我們只需要關(guān)注數(shù)據(jù)和節(jié)點的對于關(guān)系即可,其余技術(shù)是在這個大背景下的優(yōu)化。

數(shù)據(jù)驅(qū)動方案

數(shù)據(jù)驅(qū)動方案決定了其性能以及后續(xù)性能與優(yōu)化方向,數(shù)據(jù)驅(qū)動是前端的一大潮流,已經(jīng)成為了框架必備特性了,因為從前面的討論得知,操作節(jié)點、修改節(jié)點已經(jīng)可以很好地進行抽象,優(yōu)化。這里簡單討論一下三個框架的數(shù)據(jù)驅(qū)動方案

Vue數(shù)據(jù)驅(qū)動設(shè)計

Vue2的數(shù)據(jù)驅(qū)動還是數(shù)據(jù)劫持和Virtual DOM方案結(jié)合,即保持了較為精準的更新能力又保持了內(nèi)存使用的低水平,Vue這種方式有著天然的性能優(yōu)勢,所以大家在對組件的認知上不僅僅要知道組件復(fù)用才被抽取,其實,組件可以進行良好的代碼組件,維持適當大小的組件規(guī)模,還可以利用Vue2的數(shù)據(jù)驅(qū)動方案進行一個天然的性能優(yōu)化,關(guān)于這一點具體的情況,后面我會研究分離組件和整體的性能差異

模板優(yōu)化

Vue使用模板時,還可以獲得靜態(tài)優(yōu)化的優(yōu)勢,在Vue3更加優(yōu)化了模板編譯

React數(shù)據(jù)驅(qū)動設(shè)計

React更新采用了Virtual DOM,解決了數(shù)據(jù)更新時,完全替換的問題,實現(xiàn)了局部更新的可能,但是對于數(shù)據(jù)更新這一層薄弱,或者說,完全不知道數(shù)據(jù)變了,需要我們主動setState,這就產(chǎn)生了后續(xù)需要在生命周期交由開發(fā)者避免不必要的渲染優(yōu)化,這里還有一個重要的點,就是時間分片,React推出了Fiber,用于優(yōu)化視圖更新時的性能問題,這里多說一句,Vue3本來也實現(xiàn)了時間分片,考慮到收益不大,又移除了,這應(yīng)該是本身Vue的數(shù)據(jù)驅(qū)動方案的優(yōu)勢造成時間分片的收益較低

模板優(yōu)化

由于采用了JSX,沒法提供足夠的信息在編譯時進行優(yōu)化,但是可以嘗試在JSX 編譯成 React.createElement 的整個過程進行優(yōu)化,目前 FaceBook 推出了Prepack 用于這個過程的優(yōu)化

Angular數(shù)據(jù)驅(qū)動設(shè)計

angular9目前采用了臟檢測和proxy結(jié)合的方式,基本沒使用,不予評價

模板優(yōu)化

Angular支持模板,隨著V9版本發(fā)布,ivy渲染引擎推出,用于優(yōu)化,也算是一個彌補

數(shù)據(jù)驅(qū)動設(shè)計反思

實現(xiàn)數(shù)據(jù)驅(qū)動的方式有很多,Vue和Angular走得是類MVVM的形式,React實質(zhì)上不可以稱為MVVM框架,就如它所說的,它就是一個視圖層框架,數(shù)據(jù)驅(qū)動的不同方式各有優(yōu)劣,個人能力水平有限,也說不出誰好誰壞,但是可以看出的是,每個數(shù)據(jù)驅(qū)動的方式都有存在一點缺陷,框架本身也針對這些缺陷在優(yōu)化

組件化設(shè)計

組件化除了數(shù)據(jù)驅(qū)動另外一大前端趨勢,框架如何設(shè)計組件也是一個關(guān)注點

Vue

定義

Vue.component("my-component", {
props:['props1'],
template: `
<div @click="clickHandler">
<slot><slot>
</div>
`,
methods: {
clickHandler() {
this.$emit('click')
}
}
});

使用

<my-component @click="clickHandler" :props1="props1" data-x="dataX">
<template #default>slot</template>
</my-component>
數(shù)據(jù)入口

Vue在組件上劃分了props和attrs,組件內(nèi)部提供了props選項來捕獲特點的attr轉(zhuǎn)換為props,其余會成為attrs直接附加到組件根節(jié)點上,實質(zhì)上,這是一種默認大于配置的想法,默認無關(guān)的屬性應(yīng)該附加到根節(jié)點,但是總會有少數(shù)情況,所以后續(xù)Vue提供了inheritAttrs來控制attr作用元素

組件事件

Vue在組件之前的事件采用了發(fā)布訂閱模式EventEmitter來實現(xiàn),這個模式比起直接傳遞回調(diào)函數(shù),有以下好處

在認知上,區(qū)分了觸發(fā)者和響應(yīng)者組件內(nèi)容替換

Vue提供了slot機制,用于提供擴展組件內(nèi)部節(jié)點,值得一提的是,scopedSlot機制

React

定義


function Square(props) {
return (
<button onClick={props.onClick}>
{props.props1}
</button>
<div>props.slot<div>
);
}

使用

<Square value={} onClick={() => this.handlerClick(i)  slot={}}/>
數(shù)據(jù)入口

React沒有區(qū)分Props和attrs,只是將數(shù)據(jù)解析好,完全交給開發(fā)者去控制

組件事件

React采用了將父組件直接傳入子組件的方式,個人認為像Vue那樣的EventEmitter對于開發(fā)者更加友好

組件內(nèi)容替換

React沒有為slot提供特殊語法,可以直接將slot以普通屬性的方式傳遞進來,剩下的交由組件內(nèi)部處理

Angular

定義

@Component({
// 省略
})
export class ProductAlertsComponent implements OnInit {
// 定義數(shù)據(jù)入口
@Input() product;

// 定義外部事件
@Output() notify = new EventEmitter();
constructor() { }

}

<div>
<button @click="notify.emit()"></button>
<ng-content></ng-content>
</div>

使用

<component
(notify)="onNotify()"
[product]="product">
<div>slot</div>
</component>
數(shù)據(jù)入口

Angular也只是提供了一個數(shù)據(jù)入口

組件事件

Angular類似Vue一樣,使用了發(fā)布訂閱模式來管理組件之間的事件

組件內(nèi)容替換

Angular提供了類似slot的機制來擴展組件節(jié)點能力

組件化設(shè)計反思

毫無疑問,組件化一定是未來的持續(xù)保持的前端框架特性,如何設(shè)計一個良好的組件,這是值得思考的,三個框架也有自己的思考,,這里不予評價

框架特性

這一點我想只是從我的認知來講,框架除去數(shù)據(jù)驅(qū)動和組件化設(shè)計之外,它對開發(fā)者帶來哪些特性,能力有限,這里分析不是很深入

Vue

Vue 是適應(yīng)開發(fā)者,讓開發(fā)者怎么爽怎么來,Vue很多特性都是基于開發(fā)者角度去開發(fā)的,比如attr和props,Angular和React就不會這樣處理,完全交給開發(fā)者去處理細節(jié),所以就導(dǎo)致,Vue好像看起來沒啥框架上的特點,實質(zhì)上,Vue將一些對開發(fā)者認知不友好的處理,內(nèi)置到了框架之內(nèi)

React

React 設(shè)計是改變開發(fā)者,提供強大而復(fù)雜的機制,當然這么做,就會社區(qū)非常繁榮,后續(xù)也可以吸收一些良好的方式,目前我也在學(xué)習(xí)React,不得不說,React更像是學(xué)院派,社區(qū)能夠誕生很多不錯的Idea

推崇函數(shù)式編程Angular

Angular給我最深的印象是Service和DI的機制,它也為開發(fā)者考慮了很多,很多庫直接用官方的就可以了,完全不需要考慮用哪個,Angular的腳手架用起來還是挺舒服的

Service將與視圖渲染無關(guān)的邏輯提取到單獨代碼中DI解決了對象管理混亂的問題更加貼近java那套OOP總結(jié)

從前端框架解決的問題出發(fā),我們反思了數(shù)據(jù)驅(qū)動、組件化等框架必備特性,脫去這兩點,剩余的框架特性,推崇的編程范式,也是值得我們品味的,比如Angular視圖渲染邏輯和數(shù)據(jù)分離,在React、Vue我們也可以借鑒,三大框架未來在保持數(shù)據(jù)驅(qū)動和組件化特性下,框架特性這一塊,很可能還是要統(tǒng)一走一套,比如Vue3的hook和React的hook,這一點是對開發(fā)者友好的,學(xué)習(xí)、認知成本沒那么高,有人會在這種文章上說,誰抄誰這種話,我認為試試不妥的,希望大家能夠以一個更高層的視覺看到目前前端的發(fā)展。

最后送福利了,自己是從事了五年的前端工程師,整理了一份最全面前端學(xué)習(xí)資料,只要私信:“前端"等3秒后即可獲取地址,

里面概括應(yīng)用網(wǎng)站開發(fā),css,html,JavaScript,jQuery,Ajax,node,angular等。等多個知識點高級進階干貨的相關(guān)視頻資料,等你來拿

推薦內(nèi)容