web前端開發框架之Vue和React差異


在開發中使用了vue之后,會感受到vue比jquery高效不少,一個指令可以省略不少代碼,但當學習和使用了react之后感覺更有趣的也出現了,就是喜歡上了比較vue和react的異同。今天就簡單談談兩者的部分差異。

首先,除了react使用虛擬DOM一大亮點外,我們先從直觀的地方比較下兩者的差異:在使用cli(React 的 create-react-app 和 Vue 的 vue-cli)創建應用時,應用的外觀展示如下:

兩個應用程序代碼結構及存放位置存在的差別:

它們的結構也幾乎完全相同,唯一的區別是 React 有三個 CSS 文件,而 Vue 則沒有。這是因為 React 組件需要一個附帶的文件來保存樣式,而 Vue 采用包含的方式,將樣式聲明在組件文件中。

從理論上講,你可以使用老式的 style.css 文件來保存整個頁面的樣式,這完全取決於你自己。不管怎樣,還是展示一下.vue 文件中的 CSS 代碼長什么樣:

然后讓我們在看看兩者在數據的傳遞,增刪改方面的差異。

數據如何傳給子組件?

React:

在 React 中,當創建子組件時,我們將 props 傳給它。

<ToDoItem key={key} item={todo} />

我們將 todo props 傳給了 ToDoItem 組件。從現在開始,我們可以在子組件中通過 this.props 引用它們。因此,要訪問 item.todo,我們只需調用 this.props.todo。

Vue:

在 Vue 中,當創建子組件時,我們將 props 傳給它。

<ToDoItem v-for="item in this.list"
          :todo="item.todo"
          :key="list.indexOf(item)"
          :id="list.indexOf(item)"
>
</ToDoItem>

 然后,我們將它們加入到子組件的 props 數組,如:props:[‘id’,'todo']。然后可以在子組件中通過名字來引用它們,入'id'和'todo'。

數據如何發送回父組件?

React:

我們在調用子組件時將函數作為 prop 傳給子組件,然后通過任意方式調用子組件的函數,這將觸發位於父組件中的函數。我們可以在“如何刪除待辦事項”一節中看到整個過程的示例。

Vue:

在我們的子組件中,我們只需寫一個函數,讓它向父函數發回一個值。在父組件中,我們寫了一個函數來監聽這個值,然后觸發函數調用。我們可以在“如何刪除待辦事項”一節中看到整個過程的示例。

怎樣傳遞事件監聽器?

React:

簡單事件(如點擊事件)的事件監聽器很簡單。以下是我們為添加新待辦事項的按鈕創建 click 事件的示例:

<div className=”ToDo-Add” onClick={this.createNewToDoItem}>+</div>

非常簡單,看起來很像是使用純 JS 處理內聯的 onClick 事件。而在 Vue 中,需要花費更長的時間來設置事件監聽器。input 標簽需要處理 onKeyPress 事件,如下所示:

<input type=”text” onKeyPress={this.handleKeyPress}/>

只要用戶按下了'enter'鍵,這個函數就會觸發 createNewToDoItem 函數,如下所示:

handleKeyPress = (e) => {
if (e.key === ‘Enter’) {
this.createNewToDoItem();
}
};

Vue:

在 Vue 中,要實現這個功能非常簡單。我們只需要使用 @符號和事件監聽器的類型。例如,要添加 click 事件偵聽器,我們可以這樣寫:

<div class=”ToDo-Add” @click=”createNewToDoItem()”>+</div>

注意:@click 實際上是寫 v-on:click 指令的簡寫。在 Vue 中,我們可以將很多東西鏈接到事件監聽器上,例如.once 可以防止事件監聽器被多次觸發。在編寫用於處理按鍵特定事件偵聽器時,還可以使用一些快捷方式。我發現,在 React 中為添加待辦事項按鈕創建一個事件監聽器需要花費更長的時間。而在 Vue 中,我們可以簡單地寫成:

<input type=”text” v-on:keyup.enter=”createNewToDoItem”/>

怎樣新增待辦事項?

React:

createNewToDoItem = () => {
    this.setState( ({ list, todo }) => ({
      list: [
          ...list,
        {
          todo
        }
      ],
      todo: ''
    })
  );
};

Vue:

createNewToDoItem() {
    this.list.push(
        {
            'todo': this.todo
        }
    );
    this.todo = '';
}

React 是怎么做到的?

在 React 中,input 有一個叫作 value 的屬性。我們通過幾個與創建雙向綁定相關的函數來自動更新 value。React 通過為 input 附加 onChange 函數來處理雙向綁定。

<input type="text" 
       value={this.state.todo} 
       onChange={this.handleInput}/>

只要 input 的值發生變化,就會執行 handleInput 函數。這個函數會將狀態對象中 todo 字段的值改為 input 中的值。這個函數看起來像這樣:

handleInput = e => {
  this.setState({
    todo: e.target.value
  });
};

現在,只要用戶按下頁面上的 + 按鈕,createNewToDoItem 就會調用 this.setState,並傳入一個函數。這個函數有兩個參數,第一個是狀態對象的 list 數組,第二個是 todo(由 handleInput 函數更新)。然后函數會返回一個新對象,這個對象包含之前的整個 list,然后將 todo 添加到 list 的末尾。

最后,我們將 todo 設置為空字符串,它也會自動更新 input 中的值。

 Vue 是怎么做到的?

在 Vue 中,input 有一個叫作 v-model 的屬性。我們可以用它來實現雙向綁定。

<input type="text" v-model="todo"/>

v-model 將 input 綁定到數據對象 toDoItem 的一個 key 上。在加載頁面時,我們將 toDoItem 設置為空字符串,比如 todo:’’。如果 todo 不為空,例如 todo:’add some text here',那么 input 就會顯示這個字符串。我們在 input 中輸入的任何文本都會綁定到 todo。這實際上就是雙向綁定(input 可以更新數據對象,數據對象也可以更新 input)。

因此,回看之前的 createNewToDoItem() 代碼塊,我們將 todo 的內容放到 list 數組中,然后將 todo 更新為空字符串。

怎樣刪除待辦事項?

React:

deleteItem = indexToDelete => {
    this.setState(({ list }) => ({
      list: list.filter((toDo, index) => index !== indexToDelete)
    }));
};

React 是怎么做到的?

雖然 deleteItem 函數位於 ToDo.js 中,我仍然可以在 ToDoItem.js 中引用它,就是將 deleteItem() 函數作為的 prop 傳入:

<ToDoItem deleteItem={this.deleteItem.bind(this, key)}/>

這樣可以讓子組件訪問傳入的函數。我們還綁定了 this 和參數 key,傳入的函數需要通過 key 來判斷要刪除哪個 ToDoItem。在 ToDoItem 組件內部,我們執行以下操作:

<div className=”ToDoItem-Delete” onClick={this.props.deleteItem}>-</div>

我們使用 this.props.deleteItem 來引用父組件中的函數。

Vue:

this.$on(‘delete’, (event) => {
    this.list = this.list.filter(item => item.todo !== event)
})

Vue 是怎么做到的?

Vue 的方式稍微有點不同,我們基本上要做三件事。

首先,我們需要在元素上調用函數:

<div class=”ToDoItem-Delete” @click=”deleteItem(todo)”>-</div>

然后我們必須創建一個 emit 函數作為子組件內部的一個方法(在本例中為 ToDoItem.vue),如下所示:

deleteItem(todo) {
this.$parent.$emit(‘delete’, todo)
}

然后我們的父函數,也就是 this.$on(’delete’) 事件監聽器會在它被調用時觸發過濾器函數。

簡單地說,React 中的子組件可以通過 this.props 訪問父函數,而在 Vue 中,必須從子組件中向父組件發送事件,然后父組件需要監聽這些事件,並在它被調用時執行函數。

這里值得注意的是,在 Vue 示例中,我也可以直接將 $emit 部分的內容寫在 @click 監聽器中,如下所示:

<div class=”ToDoItem-Delete” @click=”this.$parent.$emit(‘delete’, todo)”>-</div>

這樣可以減少一些代碼,不過也取決於個人偏好。

怎樣改變數據?

我們說“改變數據”(mutate data),實際上就是指修改已經保存好的數據。比如,如果我們想將一個人的名字從 John 改成 Mark,我們就要“改變數據”。這就是 React 和 Vue 的關鍵區別之一。Vue 創建了一個數據對象,我們可以自由地更新數據對象,而 React 創建了一個狀態對象,要更新狀態對象,需要做更多瑣碎的工作。下面是 React 的狀態對象和 Vue 的數據對象之間的對比:

React 的狀態對象:

Vue 的數據對象:

從圖中可以看到,我們傳入的是相同的數據,它們只是標記的方式不一樣。但它們在如何改變這些數據方面卻有很大的區別。

假設我們有一個數據元素 name:'david'。

在 Vue 中,我們通過 this.name 來引用它。我們也可以通過 this.name='John'來更新它,這樣會把名字改成 John。

在 React 中,我們通過 this.state.name 來引用它。關鍵的區別在於,我們不能簡單地通過 this.state.name='John'來更新它,因為 React 對此做出了限制。在 React 中,我們需要使用 this.setState({name:'John'}) 的方式來更新數據。

示例參考指南:

Vue:https://github.com/sunil-sandhu/vue-todo

React:https://github.com/sunil-sandhu/react-todo

                                                                                                        


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM