你應該要知道的React和Vue的區別

mindnote

前情提要

我學習和使用Vue大概有一年時間了,可是最近纔開始學習的React,在沒使用過React以前就常常看到許多博主都在將二者進行對比,在實踐完之後,我想站在我本身的角度看看。css

那就開始了

官方文檔

Vue官方文檔
React官方文檔【中文版】vue

  • 我的感受Vue的文檔劃分的更加好一點,會把許多概念都講的比較清晰(雖然第一次看的時候啥都沒看懂)同時把一些相關的生態系統也概括到了一塊兒,例如vue-cli、vue-router、vuex等,比較方便
  • React的文檔感受比較注重實操,對基礎的講解較少,在教程部分就會教你如何實現一個井字棋的(這一點是比較友好的)

組件

這兩個框架都是推薦把頁面組件化的,可是二者之間對於組件也有各自的不一樣

生命週期

Vue

  • 主要分爲8個階段:
    beforeCreate
    created (在這個階段就能夠首次拿到data中定義的數據)
    beforeMount
    mounted(在這個階段Dom樹渲染完畢可訪問Dom結構)
    beforeUpdate
    updated
    beforeDestroy
    destroyed

vue生命週期

React

  • 主要分爲3個階段:
    Mounting初始化 -> Updating運行中 -> Unmounting銷燬

React生命週期

  • 生命週期中的方法react

    • 【react 16.0以後已移除】 componentWillMount():在render()以前執行,因此在這個階段的setState()不會從新渲染;一般用constructor()代替
    • render():在componentWillMount()以後執行
    • componentDidMount():在render()以後執行,因此在這個階段的setState()會從新渲染;這裏能夠對DOM進行操做
    • 【react 16.0以後已移除】 componentWillReceiveProps(nextProps):當已掛載組件收到新的props時執行,但有可能props傳入時沒有發生改變但仍然從新渲染了,若是想要避免這種狀況能夠在傳入新的props時比較一下新舊props之間是否發生變化;這裏須要注意一下,若是隻是調用了setState()的話是不會觸發這個方法的,只有props發生改變或者沒有發生改變時纔會觸發這個方法
    • shouldComponentUpdate(nextProps,nextState):在接收到新的props或者state時肯定是否發生從新渲染,默認值爲true;在首次渲染時不會觸發這個方法
    • 【react 16.0以後已移除】 componentWillUpdate(nextProps,nextState):在shouldComponentUpdate()以後,render()以前觸發;在組件初始化時不會被觸發
    • componentDidUpdate(prevProps,prevState):在componentWillUpdate(nextProps,nextState)以後調用;在組件初始化時不會被觸發,此時能夠對DOM進行操做

組件形式

Vue Template

  • Vue組件的編寫結構分爲三部分,分別是 template(HTML) script(JS) style(CSS)
  • 將三者獨立開來,更好的注重每一部分的開發
  • CSS:Vue默認是在單文件組件中在<script scoped></script>標籤裏寫CSS樣式,咱們能夠經過在<script scoped></script>標籤中寫上scoped,這樣這部分樣式就只用來控制該組件的樣式,而不會影響到其餘組件。
  • JS:模版部分使用數據:須要將變量放在雙大括號內{{}}vue-router

    <template>
      <!-- HTML Code -->
      <div>{{name}}</div> 
    </template>
    
    <script>
      export default{
        name: 'NewComponent',
        data() {
          return {
            name: 'xx'
          }
        }
      }
    </script>
    
    <style scoped>
      /* CSS Code */
    </style>

React JSX

- React支持Class組件和Function組件
  • React組件使用render渲染函數,能夠用JavaScript來構建視圖頁面,常包含了大量的邏輯
  • CSS:React是經過使用className字段來設置樣式,通常都是引入外部的css,且通常都會使用less預編譯
  • JS:將變量放在{}vuex

    // class組件
    class Template extends React.Component{
       render() {
          return (
            <div className="shopping-list">
              <h1>Shopping List for {this.props.name}</h1>
            </div>
          );
       }
    }
    // function組件
    function NewComponent() {
      const [name, setName] = useState('');
      return (<div>{name}</div>);
    }

數據管理

Vue對象屬性

  • 數據由data屬性在對象中進行管理,能夠直接改變vue-cli

    export default {
       name: 'app',
       data() {
          return {
            orders: {}
          }
       }
    }

React狀態管理

class組件state
  • 數據經過state保存狀態,須要經過setState來改變
  • setState更新的是組件的部分數據,react會自動將數據合併
  • setState原理:你真的理解setState嗎數組

    state = {
      version: Version.V3
    };
    
    handleVersionChange(version: Version) {
      this.setState({ version: Number(version)}
    );
function組件hooks
  • 數據須要經過setXXX來改變
  • useState 不會自動合併更新對象瀏覽器

    function Counter({initialCount}) {  
      const [count, setCount] = useState(initialCount);  
      return (    
          <>      
              <button onClick={() => setCount(initialCount)}>Reset</button>      
          </>  
      ); 
    }

數據流

單向數據流中的 單向:我理解的是父級數據的更新會向下流動到子組件中,可是反過來則不行,這樣能夠防止從子組件意外改變父級組件的狀態

數據流

Vue雙向數據綁定

vue仍然是單向數據流

表現形式

  • 使用v-model
  • 通常有兩種使用情景:app

    • 組件
    • input元素
  • v-model實質爲語法糖
<input v-model="message" />

// 等價於:
<input 
   v-bind:value="message" // 與data中聲明的數據進行綁定
   v-on:input="message=$event.target.value" // 監聽輸入框中值的變化
/>

// 實現原理
// 修改AST元素,給el添加一個prop,至關於動態綁定了value
addProp(el,'value',`(${value})`);
// 添加事件處理,至關於給input綁定了input事件
addHandler(el,event,code,null,true);

實現原理

  • vue使用的是發佈者訂閱者的模式+數據劫持的方式來實現的,在組件中咱們定義data時,vue會遍歷這個對象,經過Object.defineProperty()給每個值都添加gettersetter方法,而後每個組件都有一個watcher來監聽數據的變化,當數據發生變化的時候,即觸發setter時,就會發布消息給訂閱者,觸發相應的監聽回調

Vue2.0的缺陷

  • 不具有監聽數組的能力,須要從新定義數組的原型來達到響應式
  • 沒法檢測到對象屬性的添加和刪除
  • 只能劫持對象的屬性(假如須要對每一個對象的每一個屬性進行遍歷,若是屬性值也是對象那麼須要深度遍歷,顯然能劫持一個完整的對象是更好的選擇)
解決方法:Vue.set() || this.$set()
  • 若是在實例建立以後添加新的屬性到實例上,它不會觸發視圖更新,由於此時添加的屬性並無綁定上gettersetter,所以這個屬性是非響應式。若是咱們想要把這個屬性變成響應式的話,能夠經過Vue.set()或者this.$set()這兩種方式添加新的屬性
  • 除了添加新的屬性之外,改變數組的一些屬性也不會使得視圖更新,
  • 利用索引直接設置數組的某一項 arr[1] = 10
  • 直接修改數組的大小 arr.length = 10
  • 對於數組除了能夠經過Vue.set()this.$set()這兩種方式,還可使用數組的一些API來觸發更新,如splice() concat()等會修改原始數組的API

Vue3.0的改進

  • 使用ES6中的proxy框架

    • 能夠劫持到整個對象而非屬性,並返回一個新的對象
    • 能夠監聽到數組的變化

React單向數據流

特色

  • React採用單向數據流的形式,即它只接收數據,但不改變數據,只監聽數據的改變;當數據發生變化的時候,它會接收使用新的數據,從新進行渲染。
  • 我以爲單向數據流最大的好處的話,是當多個組件都要對同一個值進行操做的時候,因爲數據只有一份,所以可以保持它的一致性。

狀態管理器

什麼狀況下咱們要使用狀態管理器呢?
通常是當多個組件須要共同維護一些數據,使用傳值的方式會十分複雜,於是咱們能夠把這些須要共同維護的數據提取出來,放在store中共同維護,這樣就能夠保證數據的一致性

Vue

Vuex

  • 單一數據源:只有一個store
  • mutation(同步操做):修改state只能經過mutation的方式,須要經過store.commit()來提交mutation
  • action(異步操做):action裏面能夠包含多個mutation,最後也是要經過store.commit()來觸發mutation,action須要經過store.dispatch()來觸發
  • model:引入來模塊化,就是想要把store進行拆分,每一個 Module 有本身的 state、mutation、action、getter,能夠各自維護,最後再把每一個store組合起來,不違背Vuex的單一數據源

React

Redux

  • 單一數據源:只有一個store
  • state是隻讀的:須要經過reducer純函數返回一個新的state
  • 單向數據流
  • 使用的是不可變數據,每次更新都是使用新的state來替換舊的state

Mobx-React

  • 能夠有多個store
  • store中的state能夠直接修改
@observable // 咱們要在須要觀察的數據加上@observable
current: number = 1;
total: number = 0;

@action // 將修改被觀測變量的行爲放在action中
updateCurrent(current: number) {
    this.current = current;
}

// 對於異步操做,action沒法影響當前函數調用的異步操做,可使用runInAction來解決
async getList() {
  // some code
    runInAction(() => {
      this.total = res.total;
  });
}

路由

Vue-Router

vue是單頁面應用,頁面跳轉不會發送請求

hash模式

  • 簡單點說就是URL後帶有#標誌的就是hash路由

    // 像這樣
    http://localhost:8080/home#heading
表層原理
  • 使用hash來模擬一個完整的URL,因此當URL發生改變的時候,不會從新加載
  • hash出如今URL中,但並不會包含到http請求中,所以當hash值發生變化的時候,並不會引發頁面的請求
  • 當#後的值發生變化的時候,會向瀏覽器的歷史瀏覽增長一個記錄,當點擊後退按鈕時,會彈出,以此來實現頁面的跳轉
  • 經過onhashchange事件監聽hash值的變化

history模式

  • URL後不帶有#標誌的
// 像這樣
http://localhost:8080/home/center
表層原理
  • history模式主要使用的是HTML5中提供的APIhistory.pushState()history.replaceState()來實現
  • 須要注意的是,history模式不怕前進,不怕後退,就怕刷新
  • history模式下若是刷新頁面的話,可能會返回404,由於當刷新頁面的時候,會真實的向服務端發送請求,但若是此時該頁面沒有在服務端配置過的話就會返回404,所以須要服務端進行重定向,可使用Nginx,使用try_file和rewrite實現重定向

React-Router(待完善)

BrowserRouter

  • 與Vue-Router中的history模式相似

HashRouter

  • 與Vue-Router中的hash模式相似

腳手架(待補充)

Vue-Cli

Create-React-App

單元測試(待補充)

從Vue到React

  • 雖然我是先學習和使用Vue的,可是因爲之前學習過Java等一些面向對象的語言,因此從Vue到React的過渡並無不適應,反而以爲很熟悉;並且React使用JS來構建頁面,能夠在裏面寫邏輯,我以爲很是安逸呀。
  • 但其實不論是哪種框架,適合這個項目的框架那它就是好框架,不一樣的框架有不一樣的特殊點,若是這個特殊點和項目的要求想契合的話,那就是它了!
相關文章
相關標籤/搜索