1. 程式人生 > >Vue.js與React的全面對比

Vue.js與React的全面對比

跟蹤 維護 frame directive down 容器 生效 寫法 bsp

Vue與React的對比

Vue.js與React.js從某些反面來說很相似,通過兩個框架的學習,有時候對一些用法會有一點思考,為加深學習的思索,特翻閱了兩個文檔,從以下各方面進行了對比,加深了對這兩個框架的認知。

1.數據綁定

1.1 Vue中有關數據綁定的部分

  • vue是雙向綁定, Vue.js 最核心的功能有兩個,一是響應式的數據綁定系統,二是組件系統。所謂雙向綁定,指的是vue實例中的data與其渲染的DOM元素的內容保持一致,無論誰被改變,另一方會相應的更新為相同的數據。這是通過設置屬性訪問器實現的。
  • 在vue中,與數據綁定有關的有 插值表達式、指令系統、*Class和Style、事件處理器和表單空間、ajax請求和計算屬性
1.1.1插值表達式

插值和指令又稱為模板語法
- 數據綁定最常見的形式就是使用“Mustache”語法 (雙大括號) 的文本插值
- Mustache 語法不能作用在 HTML 特性上,遇到這種情況應該使用 v-bind 指令

1.1.2 指令
  • vue中的指令很方便,指令 (Directives) 是帶有 v- 前綴的特殊屬性。指令屬性的值預期是單個 JavaScript 表達式 (v-for 是例外情況,稍後我們再討論)。指令的職責是,當表達式的值改變時,將其產生的連帶影響,響應式地作用於 DOM。

  • vue中的12個指令: v-bind,v-once,v-model,v-text,v-html,v-on,v-if,v-else,v-show,v-for,v-pre,v-clock

1.1.3 class與style綁定
  • 數據綁定的一個常見需求是操作元素的 class 列表和它的內聯樣式。因為它們都是屬性 ,我們可以用v-bind 處理它們:只需要計算出表達式最終的字符串。不過,字符串拼接麻煩又易錯。因此,在 v-bind 用於 class 和 style 時,Vue.js 專門增強了它。表達式的結果類型除了字符串之外,還可以是對象或數組。
  • 對象語法
    • 我們可以傳給 v-bind:class 一個對象,以動態地切換 class
  • 數組語法
    • 我們可以把一個數組傳給 v-bind:class,以應用一個 class 列表:
<div v-bind:class="[activeClass, errorClass]"></div>
  • 1
1.1.4 條件渲染和列表渲染
  • v-if條件渲染一組數
  • 我們用 v-for 指令根據一組數組的選項列表進行渲染。v-for 指令需要使用 item in items 形式的特殊語法,items 是源數據數組並且 item 是數組元素叠代的別名。
1.1.5 事件處理器
  • 通過v-on給元素註冊事件
  • 使用 v-on 有幾個好處:
    • 掃一眼 HTML 模板便能輕松定位在 JavaScript 代碼裏對應的方法。
    • 因為你無須在 JavaScript 裏手動綁定事件,你的 ViewModel 代碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易於測試。
    • 當一個 ViewModel 被銷毀時,所有的事件處理器都會自動被刪除。你無須擔心如何自己清理它們。
1.1.6 表單控件
  • v-model在表單控件元素上創建雙向數據綁定
  • 它會根據控件類型自動選取正確的方法來更新元素。
1.1.7 計算屬性
  • 在Vue中引入了計算屬性來處理模板中放入太多的邏輯會讓模板過重且難以維護的問題,這樣不但解決了上面的問題,而且也同時讓模板和業務邏輯更好的分離。
  • 簡單來說,假如data裏面有屬性a=1,然後你需要一個變量跟著a變化,例如b=a+1,那麽就需要用到計算屬性,Vue實例的computed屬性中,設置b為其屬性,其表現為一個函數,返回值是b的值。
1.1.8 ajax數據請求
  • vue2.0中數據請求推薦使用axios
註: 關於vue的數據雙向綁定和單向數據流
  • Vue 的依賴追蹤是【原理上不支持雙向綁定,v-model 只是通過監聽 DOM 事件實現的語法糖】

  • vue的依賴追蹤是通過 Object.defineProperty 把data對象的屬性全部轉為 getter/setter來實現的;當改變數據的某個屬性值時,會觸發set函數,獲取該屬性值的時候會觸發get函數,通過這個特性來實現改變數據時改變視圖;也就是說只有當數據改變時才會觸發視圖的改變,反過來在操作視圖時,只能通過DOM事件來改變數據,再由此來改變視圖,以此來實現雙向綁定

  • 雙向綁定是在同一個組件內,將數據和視圖綁定起來,和父子組件之間的通信並無什麽關聯;
  • 組件之間的通信采用單向數據流是為了組件間更好的解耦,在開發中可能有多個子組件依賴於父組件的某個數據,假如子組件可以修改父組件數據的話,一個子組件變化會引發所有依賴這個數據的子組件發生變化,所以vue不推薦子組件修改父組件的數據,直接修改props會拋出警告

1.2 react沒有數據雙向綁定

  • react是單向數據流
  • react中通過將state(Model層)與View層數據進行雙向綁定達數據的實時更新變化,具體來說就是在View層直接寫JS代碼Model層中的數據拿過來渲染,一旦像表單操作、觸發事件、ajax請求等觸發數據變化,則進行雙同步
1.2.1事件處理
  • React 元素的事件處理和 DOM元素的很相似。但是有一點語法上的不同:

    • React事件綁定屬性的命名采用駝峰式寫法,而不是小寫。
    • 如果采用 JSX 的語法你需要傳入一個函數作為事件處理函數,而不是一個字符串(DOM元素的寫法)
    • 在 React 中另一個不同是你不能使用返回 false 的方式阻止默認行為。你必須明確的使用 preventDefault。
    • 當你使用 ES6 class 語法來定義一個組件的時候,事件處理器會成為類的一個方法。一般需要顯式的綁定this,例如

      this.handleClick = this.handleClick.bind(this);

    • 你必須謹慎對待 JSX 回調函數中的 this,類的方法默認是不會綁定 this 的。如果你忘記綁定 this.handleClick 並把它傳入 onClick, 當你調用這個函數的時候 this 的值會是 undefined。
1.2.2 條件渲染
  • React 中的條件渲染和 JavaScript 中的一致,使用 JavaScript 操作符 if 或條件運算符來創建表示當前狀態的元素,然後讓 React 根據它們來更新 UI。
  • 你可以通過用花括號包裹代碼在 JSX 中嵌入任何表達式 ,也包括 JavaScript 的邏輯與 &&,它可以方便地條件渲染一個元素。之所以能這樣做,是因為在 JavaScript 中,true && expression 總是返回 expression,而 false && expression 總是返回 false。因此,如果條件是 true,&& 右側的元素就會被渲染,如果是 false,React 會忽略並跳過它。
  • 條件渲染的另一種方法是使用 JavaScript 的條件運算符 condition ? true : false。
1.2.3 列表渲染
  • 你可以通過使用{}在JSX內構建一個元素集合,使用Javascript中的map()方法循遍歷數組
  • Keys可以在DOM中的某些元素被增加或刪除的時候幫助React識別哪些元素發生了變化。因此你應當給數組中的每一個元素賦予一個確定的標識。一個元素的key最好是這個元素在列表中擁有的一個獨一無二的字符串。通常,我們使用來自數據的id作為元素的key。
1.2.4 表單操作
  • HTML表單元素與React中的其他DOM元素有所不同,因為表單元素生來就保留一些內部狀態。
  • 當用戶提交表單時,HTML的默認行為會使這個表單會跳轉到一個新頁面。在React中亦是如此。但大多數情況下,我們都會構造一個處理提交表單並可訪問用戶輸入表單數據的函數。實現這一點的標準方法是使用一種稱為“受控組件”的技術。其值由React控制的輸入表單元素稱為“受控組件”。this.setState({value: event.target.value});
  • 當你有處理多個受控的input元素時,你可以通過給每個元素添加一個name屬性,來讓處理函數根據 event.target.name的值來選擇做什麽。
1.2.5 狀態提升
  • 在React中,狀態分享是通過將state數據提升至離需要這些數據的組件最近的父組件來完成的。這就是所謂的狀態提升。this.props.xxx
  • 在React應用中,對應任何可變數據理應只有一個單一“數據源”。通常,狀態都是首先添加在需要渲染數據的組件中。此時,如果另一個組件也需要這些數據,你可以將數據提升至離它們最近的父組件中。你應該在應用中保持 自上而下的數據流,而不是嘗試在不同組件中同步狀態。

2.組件化以及組件數據流

2.1 react中的組件及數據流

  • React是單向數據流,數據主要從父節點傳遞到子節點(通過props)。如果頂層(父級)的某個props改變了,React會重渲染所有的子節點。
  • react中實現組件有兩種實現方式,一種是createClass方法,另一種是通過ES2015的思想類繼承React.Component來實現
  • 在React應用中,按鈕、表單、對話框、整個屏幕的內容等,這些通常都被表示為組件。
  • React推崇的是函數式編程和單向數據流:給定原始界面(或數據),施加一個變化,就能推導出另外一個狀態(界面或者數據的更新)
  • 組件可以將UI切分成一些的獨立的、可復用的部件,這樣你就只需專註於構建每一個單獨的部件。組件從概念上看就像是函數,它可以接收任意的輸入值(稱之為“props”),並返回一個需要在頁面上展示的React元素。
    1. Props的只讀性
  • 無論是使用函數或是類來聲明一個組件,它決不能修改它自己的props。
  • 所有的React組件必須像純函數那樣使用它們的props。

props與State的區別
- props是property的縮寫,可以理解為HTML標簽的attribute。不可以使用this.props直接修改props,因為props是只讀的,props是用於整個組件樹中傳遞數據和配置。在當前組件訪問props,使用this.props。
- props是一個組件的設置參數,可以在父控件中選擇性設置。父組件對子控件的props進行賦值,並且props的值不可改變。一個子控件自身不能改變自己的 props。
- state:當一個組件 mounts的時候,state如果設置有默認值的會被使用,並且state可能時刻的被改變。一個子控件自身可以管理自己的state,但是需要註意的是,無法管理其子控件的state。所以可以認為,state是子控件自身私有的。
- 每個組件都有屬於自己的state,state和props的區別在於前者(state)只存在於組件內部,只能從當前組件調用this.setState修改state值(不可以直接修改this.state!)。
- props是一個父組件傳遞給子組件的數據流,可以一直的被傳遞到子孫組件中。然而 state代表的是子組件自身的內部狀態。從語義上講,改變組件的狀態,可能會導致dom結構的改變或者重新渲染。而props是父組件傳遞的參數,所以可以被用於初始化渲染和改變組件自身的狀態,雖然大多數時候組件的狀態是又外部事件觸發改變的。我們需要知道的是,無論是state改變,還是父組件傳遞的 props改變,render方法都可能會被執行。
- 一般我們更新子組件都是通過改變state值,更新新子組件的props值從而達到更新。

2.1.1 組件之間的通信
  1. 父子組件數通信
    • 父與子之間通props屬性進行傳遞
    • 子與父之間,父組件定義事件,子組件觸發父組件中的事件時,通過實參的形式來改變父組件中的數據來通信

即:
- * 父組件更新組件狀態 —–props—–> 子組件更新
- * 子組件更新父組件狀態 —–需要父組件傳遞回調函數—–> 子組件調用觸發

  1. 非父子組件之間的通信,嵌套不深的非父子組件可以使共同父組件,觸發事件函數傳形參的方式來實現
    兄弟組件:

(1) 按照React單向數據流方式,我們需要借助父組件進行傳遞,通過父組件回調函數改變兄弟組件的props。
- 其實這種實現方式與子組件更新父組件狀態的方式是大同小異的。

(2) 當組件層次很深的時候,在這裏,React官方給我們提供了一種上下文方式,可以讓子組件直接訪問祖先的數據或函數,無需從祖先組件一層層地傳遞數據到子組件中。

2.1.2 組件的生命周期
construtor() //創建組件
componentWillMount() //組件掛載之前
componentDidMount() // 組件掛載之後
componentWillReceiveProps() // 父組件發生render的時候子組件調用該函數
shouldComponentUpdate() // 組件掛載之後每次調用setState後都會調用該函數判斷是否需要重新渲染組件,默認返回true
componentDidUpdate() // 更新
render() //渲染,react中的核心函數
componentWillUnmount() //組件被卸載的時候調用,一般在componentDidMount註冊的事件需要在這裏刪除
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

技術分享圖片

2.2 vue中的組件和數據流

2.2.1 組件化應用構建
  • 組件系統是 Vue 的另一個重要概念,因為它是一種抽象,允許我們使用小型、獨立和通常可復用的組件構建大型應用。
  • 在 Vue 裏,一個組件本質上是一個擁有預定義選項的一個 Vue 實例
  • 在一個大型應用中,有必要將整個應用程序劃分為組件,以使開發可管理。
  • 組件(component)是 Vue 最強大的功能之一。組件可以幫助你擴展基本的 HTML 元素,以封裝可重用代碼。在較高層面上,組件是 Vue 編譯器附加行為後的自定義元素。在某些情況下,組件也可以是原生 HTML 元素的形式,以特定的 is 特性擴展。
  • 組件中,data必須是一個函數
  • 組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以是原生 HTML 元素的形式,以 is 特性擴展。
2.2.2 響應式
  • 當一個 Vue 實例被創建時,它向 Vue 的響應式系統中加入了其 data 對象中能找到的所有的屬性。當這些屬性的值發生改變時,視圖將會產生“響應”,即匹配更新為新的值。
  • 當這些數據改變時,視圖會進行重渲染。值得註意的是只有當實例被創建時 data 中存在的屬性是響應式的。
2.2.3 組件的生命周期
  • 每個 Vue 實例在被創建之前都要經過一系列的初始化過程。例如需要設置數據監聽、編譯模板、掛載實例到 DOM、在數據變化時更新 DOM 等。同時在這個過程中也會運行一些叫做生命周期鉤子的函數,給予用戶機會在一些特定的場景下添加他們自己的代碼。
  • 比如 created 鉤子可以用來在一個實例被創建之後執行代碼,也有一些其它的鉤子,在實例生命周期的不同場景下調用,如 mounted、updated、destroyed。鉤子的 this 指向調用它的 Vue 實例。
  • 生命周期圖示:
    技術分享圖片
2.2.3 組件之間的通信
  • Vue默認的是單向數據流,這是Vue直接提出來說明的,父組件默認可以向子組件傳遞數據,但是子組件向父組件傳遞數據就需要額外設置了。
  • Vue 也支持雙向綁定,默認為單向綁定,數據從父組件單向傳給子組件。在大型應用中使用單向綁定讓數據流易於理解。
  • 父子組件之間的數據通信是通過Prop和自定義事件實現的,而非父子組件可以使用訂閱/發布模式實現(類似於Angualr中的非父子指令之間的通信),再復雜一點也是建議使用狀態管理(vuex)。
  • 在 Vue 中,父子組件之間的關系可以概述為:props 向下,events 向上。父組件通過 props 向下傳遞數據給子組件,子組件通過 events 發送消息給父組件。

1.父向子
- 每個組件實例都有自己的孤立隔離作用域。也就是說,不能(也不應該)直接在子組件模板中引用父組件數據。要想在子組件模板中引用父組件數據,可以使用 props 將數據向下傳遞到子組件。
- 每個 prop 屬性,都可以控制是否從父組件的自定義屬性中接收數據。子組件需要使用 props 選項顯式聲明 props,以便它可以從父組件接收到期望的數據。
- 動態Props,類似於將一個普通屬性綁定到一個表達式,我們還可以使用 v-bind 將 props 屬性動態地綁定到父組件中的數據。無論父組件何時更新數據,都可以將數據向下流入到子組件中

2.子向父
- 使用自定義事件
- 每個 Vue 實例都接入了一個事件接口(events interface),也就是說,這些 Vue 實例可以做到:
- 使用 on(eventName)?使on(eventName)監聽一個事件?使用emit(eventName) 觸發一個事件

3. 非父子組件通信
- 可以使用一個空的 Vue 實例作為一個事件總線中心(central event bus),用emitemit觸發事件,on監聽事件

2.2.4 單向數據流

單向數據流示意圖:
技術分享圖片

3.狀態管理

3.1 react中的狀態管理:Flux

  • Redux 是 React 生態環境中最流行的 Flux 實現。Redux 事實上無法感知視圖層,所以它能夠輕松的通過一些簡單綁定和 Vue 一起使用。
    1. 創建actions
      • 定義動作,事件觸發需要用dispatcher來調用
      • 行為,如增加操作、刪除操作、更新操作,就是一堆函數。
    2. 創建store
      • store中包含應用的狀態和邏輯,用來管理應用中不同的狀態和邏輯,相當於Model層
    3. 創建dispatcher
      • 在dispatcher中通過register來給每個action註對應的的store中的方法
    4. 在view層調用action中的方法
      • 就是各類component

技術分享圖片

3.2 vue中的狀態管理vuex

  • vuex借鑒了 Flux、Redux、和 The Elm Architecture。與其他模式不同的是,Vuex 是專門為 Vue.js 設計的狀態管理庫,以利用 Vue.js 的細粒度數據響應機制來進行高效的狀態更新。這使得它能夠更好地和 Vue 進行整合,同時提供簡潔的 API 和改善過的開發體驗。
  • 組件不允許直接修改屬於 store 實例的 state,而應執行 action 來分發 (dispatch) 事件通知 store 去改變,我們最終達成了 Flux 架構。這樣約定的好處是,我們能夠記錄所有 store 中發生的 state 改變,同時實現能做到記錄變更 (mutation)、保存狀態快照、歷史回滾/時光旅行的先進的調試工具。

  • 每一個 Vuex 應用的核心就是 store(倉庫)。“store”基本上就是一個容器,它包含著你的應用中大部分的狀態

  • Vuex 和單純的全局對象有以下兩點不同:

    1. Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麽相應的組件也會相應地得到高效更新。

    2. 你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地了解我們的應用。

    3. State

  • Vuex 使用單一狀態樹——是的,用一個對象就包含了全部的應用層級狀態。至此它便作為一個“唯一數據源 (SSOT)”而存在。這也意味著,每個應用將僅僅包含一個 store 實例。單一狀態樹讓我們能夠直接地定位任一特定的狀態片段,在調試的過程中也能輕易地取得整個當前應用狀態的快照。這也意味著,每個應用將僅僅包含一個 store 實例。
    1. Getters
  • 從state中獲取狀態值,有時候我們需要從 store 中的 state 中派生出一些狀態,例如對列表進行過濾並計數。

    1. Mutation
      • 更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似於事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個參數。
      • 你不能直接調用一個 mutation handler。這個選項更像是事件註冊:“當觸發一個類型為 increment 的 mutation 時,調用此函數。”要喚醒一個 mutation handler,你需要以相應的 type 調用 store.commit 方法
    2. Action

      • Action 類似於 mutation,不同在於:

      • Action 提交的是 mutation,而不是直接變更狀態。

      • Action 可以包含任意異步操作。
      • dispatch分發action
    3. Module

  • 由於使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常復雜時,store 對象就有可能變得相當臃腫。
  • Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割

技術分享圖片

4.路由

  • 兩者的路由很相似,都是利用了組件化思想

4.1 react中的路由

  • 在路由庫的問題上,React 選擇把問題交給社區維護,因此創建了一個更分散的生態系統。但相對的,React 的生態系統相比 Vue 更加繁榮。
  • react中,需要引入react-router庫,
    使用時,路由器Router就是React的一個組件。
  • Router組件本身只是一個容器,真正的路由要通過Route組件定義。
  • Route組件定義了URL路徑與組件的對應關系。你可以同時使用多個Route組件。
<Router history={hashHistory}>
  <Route path="/" component={App}/>
  <Route path="/repos" component={Repos}/>
  <Route path="/about" component={About}/>
</Router>
  • 1
  • 2
  • 3
  • 4
  • 5

- Link組件用於取代元素,生成一個鏈接,允許用戶點擊後跳轉到另一個路由。它基本上就是元素的React 版本,可以接收Router的狀態。

4.2 vue中的路由

  • Vue 的路由庫和狀態管理庫都是由官方維護支持且與核心庫同步更新的。
  • 使用 Vue.js ,我們已經可以通過組合組件來組成應用程序,當你要把 vue-router 添加進來,我們需要做的是,將組件(components)映射到路由(routes),然後告訴 vue-router 在哪裏渲染它們。

    1. HTML中:
<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 組件來導航. -->
    <!-- 通過傳入 `to` 屬性指定鏈接. -->
    <!-- <router-link> 默認會被渲染成一個 `<a>` 標簽 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的組件將渲染在這裏 -->
  <router-view></router-view>
</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

5. 渲染性能對比

  • 在操作界面時,要盡量減少對DOM的操作,Vue 和 React 都使用虛擬DOM來實現,並且兩者工作一樣好。
  • 盡量減少除DOM操作以外的其他操作。(vue和react的不同)

5.1 react視圖渲染

  • React 的渲染建立在 Virtual DOM 上——一種在內存中描述 DOM 樹狀態的數據結構。當狀態發生變化時,React 重新渲染 Virtual DOM,比較計算之後給真實 DOM 打補丁。

  • Virtual DOM 提供了函數式的方法描述視圖,它不使用數據觀察機制,每次更新都會重新渲染整個應用,因此從定義上保證了視圖與數據的同步。它也開辟了 JavaScript 同構應用的可能性。

  • 在超大量數據的首屏渲染速度上,React 有一定優勢,因為 Vue 的渲染機制啟動時候要做的工作比較多,而且 React 支持服務端渲染。

  • 元素是構成 React 應用的最小單位。元素用來描述你在屏幕上看到的內容,與瀏覽器的 DOM 元素不同,React 當中的元素事實上是普通的對象,React DOM 可以確保 瀏覽器 DOM 的數據內容與 React 元素保持一致。

  • 我們用React 開發應用時一般只會定義一個根節點。但如果你是在一個已有的項目當中引入 React 的話,你可能會需要在不同的部分單獨定義 React 根節點。我們將 元素傳入一個名為 ReactDOM.render() 的方法來將其渲染到頁面上,頁面上就會顯示該元素。

組件渲染
- 當React遇到的元素是用戶自定義的組件,它會將JSX屬性作為單個對象傳遞給該組件,這個對象稱之為“props”。

5.2 vue視圖渲染

  • Vue 通過建立一個虛擬 DOM 對真實 DOM 發生的變化保持追蹤。

  • vue渲染的過程如下:

    • new Vue,執行初始化
    • 掛載$mount方法,通過自定義Render方法、template、el等生成Render函數
    • 通過Watcher監聽數據的變化
    • 當數據發生變化時,Render函數執行生成VNode對象
    • 通過patch方法,對比新舊VNode對象,通過DOM Diff算法,添加、修改、刪除真正的DOM元素

6. 數據更新

6.1 react數據更新

  • React 元素都是immutable 不可變的。當元素被創建之後,你是無法改變其內容或屬性的。一個元素就好像是動畫裏的一幀,它代表應用界面在某一時間點的樣子。
  • 根據我們現階段了解的有關 React 知識,更新界面的唯一辦法是創建一個新的元素,然後將它傳入 ReactDOM.render() 方法

6.2 vue數據更新

7. 開發模式及規模

7.1 react

7.1.1 開發模式
  • React本身,是嚴格的view層,MVC模式
7.1.2 規模
  • Vue 提供了Vue-cli 腳手架,能讓你非常容易地構建項目,包含了 Webpack,Browserify,甚至 no build system。

7.2 vue

7.2.1 開發模式
  • Vue是MVVM模式的一種方式實現
  • 雖然沒有完全遵循 MVVM 模型,Vue 的設計無疑受到了它的啟發。因此在文檔中經常會使用 vm (ViewModel 的簡稱) 這個變量名表示 Vue 實例。
7.2.2 腳手架
  • React 提供了create-react-app,但是現在還存在一些局限性:
    • 它不允許在項目生成時進行任何配置,而 Vue 支持 Yeoman-like 定制。
    • 它只提供一個構建單頁面應用的單一模板,而 Vue 提供了各種用途的模板。
    • 它不能用用戶自建的模板構建項目,而自建模板對企業環境下預先建立協議是特別有用的。

8. HTML&&CSS

  • 在 React 中,一切都是 JavaScript。不僅僅是 HTML 可以用 JSX 來表達,現在的潮流也越來越多地將 CSS 也納入到 JavaScript 中來處理。這類方案有其優點,但也存在一些不是每個開發者都能接受的取舍。

- Vue 的整體思想是擁抱經典的 Web 技術,並在其上進行擴展。

8.1 react

8.1.1 JSX
  • 在 React 中,所有的組件的渲染功能都依靠 JSX。JSX 是使用 XML 語法編寫 JavaScript 的一種語法糖。
  • JSX, 一種 JavaScript 的語法擴展。 我們推薦在 React 中使用 JSX 來描述用戶界面。JSX 乍看起來可能比較像是模版語言,但事實上它完全是在 JavaScript 內部實現的。

  • JSX 用來聲明 React 當中的元素。

  • JSX本身也是一種表達式,在編譯之後呢,JSX 其實會被轉化為普通的 JavaScript 對象。這也就意味著,你其實可以在 if 或者 for 語句裏使用 JSX,將它賦值給變量,當作參數傳入,作為返回值都可以
  • JSX 說是手寫的渲染函數有下面這些優勢:
    • 你可以使用完整的編程語言 JavaScript 功能來構建你的視圖頁面。比如你可以使用臨時變量、JS 自帶的流程控制、以及直接引用當前 JS 作用域中的值等等。
    • 開發工具對 JSX 的支持相比於現有可用的其他 Vue 模板還是比較先進的 (比如,linting、類型檢查、編輯器的自動完成)。
8.1.2 組件作用域內的CSS
  • 除非你把組件分布在多個文件上 (例如 CSS Modules),CSS 作用域在 React 中是通過 CSS-in-JS 的方案實現的 (比如 styled-components、glamorous 和 emotion)。這引入了一個新的面向組件的樣式範例,它和普通的 CSS 撰寫過程是有區別的。另外,雖然在構建時將 CSS 提取到一個單獨的樣式表是支持的,但 bundle 裏通常還是需要一個運行時程序來讓這些樣式生效。當你能夠利用 JavaScript 靈活處理樣式的同時,也需要權衡 bundle 的尺寸和運行時的開銷。

8.2 vue

8.2.1 Templates模板語法
  • 事實上 Vue 也提供了渲染函數,甚至支持 JSX。然而,我們默認推薦的還是模板。任何合乎規範的 HTML 都是合法的 Vue 模板,這也帶來了一些特有的優勢:
    • 對於很多習慣了 HTML 的開發者來說,模板比起 JSX 讀寫起來更自然。這裏當然有主觀偏好的成分,但如果這種區別會導致開發效率的提升,那麽它就有客觀的價值存在。
    • 基於 HTML 的模板使得將已有的應用逐步遷移到 Vue 更為容易。
    • 這也使得設計師和新人開發者更容易理解和參與到項目中。
    • 你甚至可以使用其他模板預處理器,比如 Pug 來書寫 Vue 的模板。
  • Vue.js 使用了基於 HTML 的模板語法,允許開發者聲明式地將 DOM 綁定至底層 Vue 實例的數據。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循規範的瀏覽器和 HTML 解析器解析。
  • 在底層的實現上,Vue 將模板編譯成虛擬 DOM 渲染函數。結合響應系統,在應用狀態改變時,Vue 能夠智能地計算出重新渲染組件的最小代價並應用到 DOM 操作上。
8.2.2 單文件組件CSS
  • Vue 設置樣式的默認方法是單文件組件裏類似 style 的標簽。
    單文件組件讓你可以在同一個文件裏完全控制 CSS,將其作為組件代碼的一部分。
  • Vue 的單文件組件裏的樣式設置是非常靈活的。通過 vue-loader,你可以使用任意預處理器、後處理器,甚至深度集成 CSS Modules——全部都在

8.3 小結

  • 更抽象一點來看,我們可以把組件區分為兩類:一類是偏視圖表現的 (presentational),一類則是偏邏輯的 (logical)。我們推薦在前者中使用模板,在後者中使用 JSX 或渲染函數。這兩類組件的比例會根據應用類型的不同有所變化,但整體來說我們發現表現類的組件遠遠多於邏輯類組件。

9. 使用場景

9.1 選擇react

9.1.1 期待構建一個大型應用程序——選擇React
  • 同時用Vue和React實現的簡單應用程序,可能會讓一個開發者潛意識中更加傾向於Vue。這是因為基於模板的應用程序第一眼看上去更加好理解,而且能很快跑起來。但是這些好處引入的技術債會阻礙應用擴展到更大的規模。模板容易出現很難註意到的運行時錯誤,同時也很難去測試,重構和分解。
    相比之下,Javascript模板可以組織成具有很好的分解性和幹(DRY)代碼的組件,幹代碼的可重用性和可測試性更好。Vue也有組件系統和渲染函數,但是React的渲染系統可配置性更強,還有諸如淺(shallow)渲染的特性,和React的測試工具結合起來使用,使代碼的可測試性和可維護性更好。
    與此同時,React的immutable應用狀態可能寫起來不夠簡潔,但它在大型應用中意義非凡,因為透明度和可測試性在大型項目中變得至關重要。
9.1.2 期待同時適用於Web端和原生APP的框架——選擇React
  • React Native是一個使用Javascript構建移動端原生應用程序(iOS,Android)的庫。 它與React.js相同,只是不使用Web組件,而是使用原生組件。 如果你學過React.js,很快就能上手React Native,反之亦然。
    它的意義在於,開發者只需要一套知識和工具就能開發Web應用和移動端原生應用。如果你想同時做Web端開發和移動端開發,React為你準備了一份大禮。
    阿裏的Weex也是一個跨平臺UI項目,目前它以Vue為靈感,使用了許多相同的語法,同時計劃在未來完全集成Vue,然而集成的時間和細節還不清楚。因為Vue將HTML模板作為它設計的核心部分,並且現有特性不支持自定義渲染,因此很難看出目前的Vue.js的跨平臺能力能像React和React Native一樣強大。
9.1.3 期待最大的生態系統——選擇React
  • 毫無疑問,React是目前最受歡迎的前端框架。它在NPM上每個月的下載量超過了250萬次,相比之下,Vue是22.5萬次。人氣不僅僅是一個膚淺的數字,這意味著更多的文章,教程和更多Stack Overflow的解答,還意味有著更多的工具和插件可以在項目中使用,讓開發者不再孤立無援。
    這兩個框架都是開源的,但是React誕生於Facebook,有Facebook背書,它的開發者和Facebook都承諾會持續維護React。相比之下,Vue是獨立開發者尤雨溪的作品。尤雨溪目前在全職維護Vue,也有一些公司資助Vue,但是規模和Facebook和Google沒得比。不過請對Vue的團隊放心,它的小規模和獨立性並沒有成為劣勢,Vue有著固定的發布周期,甚至更令人稱道的是,Github上Vue只有54個open issue,3456個closed issue,作為對比,React有多達530個open issue,3447個closed issue。

9.2 選擇vue

9.2.1 期待模板搭建應用——選擇 Vue
  • Vue應用的默認選項是把markup放在HTML文件中。數據綁定表達式采用的是和Angular相似的mustache語法,而指令(特殊的HTML屬性)用來向模板添加功能。
    相比之下,React應用不使用模板,它要求開發者借助JSX在JavaScript中創建DOM。
  • 對於來自標準Web開發方式的新開發者,模板更容易理解。但是一些資深開發者也喜歡模板,因為模板可以更好的把布局和功能分割開來,還可以使用Pug之類的模板引擎。
    但是使用模板的代價是不得不學習所有的HTML擴展語法,而渲染函數只需要會標準的HTML和JavaScript。而且比起模板,渲染函數更加容易調試和測試。當然你不應該因為這方面的原因錯過Vue,因為在Vue2.0中提供了使用模板或者渲染函數的選項。
9.2.2 期待簡單和“能用就行”的東西——選擇 Vue
  • 一個簡單的Vue項目可以不需要轉譯直接運行在瀏覽器中,所以使用Vue可以像使用jQuery一樣簡單。當然這對於React來說在技術上也是可行的,但是典型的React代碼是重度依賴於JSX和諸如class之類的ES6特性的。
    Vue的簡單在程序設計的時候體現更深,讓我們來比較一下兩個框架是怎樣處理應用數據的(也就是state)。
  • React中是通過比較當前state和前一個state來決定何時在DOM中進行重渲染以及渲染的內容,因此需要不可變(immutable)的state。
    Vue中的數據是可變(mutated)的,所以同樣的操作看起來更加簡潔。
    讓我們來看看Vue中是如何進行狀態管理的。當向state添加一個新對象的時候,Vue將遍歷其中的所有屬性並且轉換為getter,setter方法,現在Vue的響應系統開始保持對state的跟蹤了,當state中的內容發生變化的時候就會自動重新渲染DOM。令人稱道的是,Vue中改變state的狀態的操作不僅更加簡潔,而且它的重新渲染系統也比React 的更快更有效率。
  • Vue的響應系統還有有些坑的,例如:它不能檢測屬性的添加和刪除和某些數組更改。這時候就要用到Vue API中的類似於React的set方法來解決。
9.2.3 期待應用盡可能的小和快——選擇Vue
  • 當應用程序的狀態改變時,React和Vue都將構建一個虛擬DOM並同步到真實DOM中。 兩者都有各自的方法優化這個過程。
    Vue核心開發者提供了一個benchmark測試,可以看出Vue的渲染系統比React的更快。測試方法是10000個項目的列表渲染100次,結果如下圖。從實用的觀點來看,這種benchmark只和邊緣情況有關,大部分應用程序中不會經常進行這種操作,所以這不應該被視為一個重要的比較點。但是,頁面大小是與所有項目有關的,這方面Vue再次領先,它目前的版本壓縮後只有25.6KB。React要實現同樣的功能,你需要React DOM(37.4KB)和React with Addon庫(11.4KB),共計44.8KB,幾乎是Vue的兩倍大。雙倍的體積並不能帶來雙倍的功能。

10. 服務器端渲染(SSR)

  • 客戶端渲染路線:1. 請求一個html -> 2. 服務端返回一個html -> 3. 瀏覽器下載html裏面的js/css文件 -> 4. 等待js文件下載完成 -> 5. 等待js加載並初始化完成 -> 6. js代碼終於可以運行,由js代碼向後端請求數據( ajax/fetch ) -> 7. 等待後端數據返回 -> 8. react-dom( 客戶端 )從無到完整地,把數據渲染為響應頁面

  • 服務端渲染路線:1. 請求一個html -> 2. 服務端請求數據( 內網請求快 ) -> 3. 服務器初始渲染(服務端性能好,較快) -> 4. 服務端返回已經有正確內容的頁面 -> 5. 客戶端請求js/css文件 -> 6. 等待js文件下載完成 -> 7. 等待js加載並初始化完成 -> 8. react-dom( 客戶端 )把剩下一部分渲染完成( 內容小,渲染快 )

10.1 react

  • React的虛擬DOM是其可被用於服務端渲染的關鍵。首先每個ReactComponent 在虛擬DOM中完成渲染,然後React通過虛擬DOM來更新瀏覽器DOM中產生變化的那一部分,虛擬DOM作為內存中的DOM表現,為React在Node.js這類非瀏覽器環境下的吮吸給你提供了可能,React可以從虛擬DoM中生成一個字符串。而不是跟新真正的DOM,這使得我們可以在客戶端和服務端使用同一個React Component。

  • React 提供了兩個可用於服務端渲染組件的函數:React.renderToString 和React.render-ToStaticMarkup。 在設計用於服務端渲染的ReactComponent時需要有預見性,考慮以下方面。

    • 選取最優的渲染函數。
    • 如何支持組件的異步狀態。
    • 如何將應用的初始化狀態傳遞到客戶端。
    • 哪些生命周期函數可以用於服務端的渲染。
    • 如何為應用提供同構路由支持。
    • 單例、實例以及上下文的用法。

10.2 vue

1. 什麽是服務器端渲染(SSR)?

  • Vue.js 是構建客戶端應用程序的框架。默認情況下,可以在瀏覽器中輸出 Vue 組件,進行生成 DOM 和操作 DOM。然而,也可以將同一個組件渲染為服務器端的 HTML 字符串,將它們直接發送到瀏覽器,最後將靜態標記”混合”為客戶端上完全交互的應用程序。

  • 服務器渲染的 Vue.js 應用程序也可以被認為是”同構”或”通用”,因為應用程序的大部分代碼都可以在服務器和客戶端上運行。

2. 服務器端渲染優勢
- 更好的 SEO,由於搜索引擎爬蟲抓取工具可以直接查看完全渲染的頁面。
- 更快的內容到達時間(time-to-content),特別是對於緩慢的網絡情況或運行緩慢的設備。無需等待所有的 JavaScript 都完成下載並執行,才顯示服務器渲染的標記,所以你的用戶將會更快速地看到完整渲染的頁面。通常可以產生更好的用戶體驗,並且對於那些「內容到達時間(time-to-content)與轉化率直接相關」的應用程序而言,服務器端渲染(SSR)至關重要。

11. 附: react理念

1. 把UI圖劃分出組件層級
2. 用React創建一個靜態版本
  • 傳入數據模型,渲染 UI 但沒有任何交互。最好把這些過程解耦,因為創建一個靜態版本更多需要的是碼代碼,不太需要邏輯思考,而添加交互則更多需要的是邏輯思考,不是碼代碼。
  • 在創建靜態版本的時候不要使用 state。
  • 你可以自頂向下或者自底向上構建應用。也就是,你可以從層級最高的組件開始構建(即 FilterableProductTable開始)或層級最低的組件開始構建(ProductRow)。在較為簡單的例子中,通常自頂向下更容易,而在較大的項目中,自底向上會更容易並且在你構建的時候有利於編寫測試。
  • React 的單向數據流(也叫作單向綁定)保證了一切是模塊化並且是快速的。
3. 定義 UI 狀態的最小(但完整)表示
  • 想想實例應用中的數據,讓我們來看看每一條,找出哪一個是 state。每個數據只要考慮三個問題:

    • 它是通過 props 從父級傳來的嗎?如果是,他可能不是 state。
    • 它隨著時間推移不變嗎?如果是,它可能不是 state。
    • 你能夠根據組件中任何其他的 state 或 props 把它計算出來嗎?如果是,它不是 state。
4. 確定你的State應該位於哪裏
  • 對你應用的每一個 state:

    • 確定每一個需要這個 state 來渲染的組件。
    • 找到一個公共所有者組件(一個在層級上高於所有其他需要這個 state 的組件的組件)
    • 這個公共所有者組件或另一個層級更高的組件應該擁有這個 state。
    • 如果你沒有找到可以擁有這個 state 的組件,創建一個僅用來保存狀態的組件並把它加入比這個公共所有者組件層級更高的地方。
5. 添加反向數據流

小結

總結一下,我們發現,
- Vue的優勢包括:
- 模板和渲染函數的彈性選擇
- 簡單的語法及項目創建
- 更快的渲染速度和更小的體積
- React的優勢包括:
- 更適用於大型應用和更好的可測試性
- 同時適用於Web端和原生App
- 更大的生態圈帶來的更多支持和工具
- 而實際上,React和Vue都是非常優秀的框架,它們之間的相似之處多過不同之處,並且它們大部分最棒的功能是相通的:
- 利用虛擬DOM實現快速渲染
- 輕量級
- 響應式和組件化
- 服務器端渲染
- 易於集成路由工具,打包工具以及狀態管理工具
- 優秀的支持和社區

文章參考來源:

  • vue官方文檔關於框架的對比
  • react中文文檔
  • vue官方文檔
版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/CystalVon/article/details/78428036

Vue.js與React的全面對比