適合Vue用戶的React教程,你值得擁有(二)

2021-02-16 前端有的玩

上周小編我寫了 適合Vue用戶的React教程,你值得擁有,得到了小夥伴們的一致好評,今天這篇文章是這一系列的第二篇文章。今年的9月18日是九一八事變89周年,同時在這一天,Vue3.0正式版發布了。相信很多小夥伴已經看過了Vue3.0相關的很多文章了。今天這篇文章將會對Vue2,Vue3,React的一些用法進行對比,方便小夥伴們學習。

數據data,在react中叫state

熟悉vue的小夥伴一定對Vue中的data不會感到陌生的,反正天天寫Bug的時候都要用,但是對於data來說,在Vue2.0,Vue3.0,React中用法是不同的,我們下面依次舉例說明

Vue2.0中的用法

如下代碼是一個比較簡單的Vue2.0的data用法

<template>
<div>{{ name }}</div>
</template>
<script>
export default {
data() {
return {
name: '子君',
gzh: '前端有的玩'
}
}
}
</script>

通過上面的代碼我們可以看到data是一個函數,然後函數中返回了一個對象,那麼為什麼data是一個函數呢?比如我們有時候也會在App.vue文件中看到data不是函數的情況。

<template>  
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
data:{
name: '子君',
sex: '男'
}
}
</script>

那麼為什麼我們在普通組件裡面還要將data聲明為函數呢?Vue官網是這樣解釋的:當一個組件被定義,data 必須聲明為返回一個初始數據對象的函數,因為組件可能被用來創建多個實例。如果 data 仍然是一個純粹的對象,則所有的實例將共享引用同一個數據對象!通過提供 data 函數,每次創建一個新實例後,我們能夠調用 data 函數,從而返回初始數據的一個全新副本數據對象。

而App.vue可以將data聲明為一個普通對象是因為整個系統中App.vue只會被使用到一次,所以不存在上述的問題。

Vue3中的用法

在Vue3中,我們依然可以像Vue2那樣去使用data,當然Vue3提供了新的Composition API,在後續文章中,如果沒有特殊說明,我們提到Vue3就默認指的是使用Composition API。

在Composition API提供了響應式API,分別是ref和reactive,通過這兩個API可以生成響應式的數據

基礎用法
<template>
<div class="home">
<div>姓名:{{ state.name }}</div>
<div>公眾號:{{ state.gzh }}</div>
<div>統計:{{ count }}</div>
</div>
</template>

<script lang="ts">
import { defineComponent, reactive, ref } from "vue";

export default defineComponent({
name: "Home",
setup() {
const state = reactive({
name: "子君",
gzh: "前端有的玩"
});
const count = ref(0);
return {
state,
count
};
}
});
</script>

響應數據修改

在Vue2.0中,我們修改data的方式一般會使用this.name = '張三'這種賦值的方式,但是對於Composition API中因為提供了兩種api,所以用法稍有區別

<template>
<div class="home" @click="handleClick">
<div>姓名:{{ state.name }}</div>
<div>公眾號:{{ state.gzh }}</div>
<div>統計:{{ count }}</div>
</div>
</template>

<script lang="ts">
import { defineComponent, reactive, ref } from "vue";

export default defineComponent({
setup() {
const state = reactive({
name: "子君",
gzh: "前端有的玩"
});

const count = ref(0);

function handleClick() {
state.name = "張三";
count.value++;
}

return {
state,
count,
handleClick
};
}
});
</script>

如上代碼所示:

對於reactive聲明的數據

對於reactive,我們可以通過state.name來獲取數據,然後通過state.name='張三'來修改數據

對於ref聲明的數據

對於ref聲明的數據,ref接受一個參數值並返回一個響應式且可改變的 ref 對象。ref 對象擁有一個指向內部值的單一屬性 .value。所以我們在代碼中獲取ref對象的數據需要使用count.value的方式,修改值的方式也需要通過count.value++的方式。

但是這裡有一個特殊的點就是在template,ref對象會自動解套,意思就是對於<div>統計:{{ count }}</div>,代碼裡面可以直接使用count,而不需要寫成count.value,Vue自己就會將其解套為count.value。

React中的用法

React16.8新增了Hook特性,現在許多團隊已經大規模使用了,所以本文的內容更多的是以Hook為主。

在Vue3.0中提供了Composition API,其實這個和React的hook用法是很相似的,接下來我們將上文中我們寫的Vue3.0代碼修改為React版本

import React, { useState } from 'react'

export default function() {
// useState傳入要初始化的狀態數據,然後會返回一個數組
// 數組第一項為聲明的數據,而第二個參數是一個方法,用於調用
// 修改數據
const [name, setName] = useState('子君')
const [gzh] = useState('前端有的玩')

function handleClick() {
// 在react修改數據需要調用useState返回的方法
setName('張三')
}

return (
<div onClick={handleClick}>
<div>姓名:{name}</div>
<div>公眾號: {gzh}</div>
</div>
);
}

在這段代碼中我們使用到了useState聲明了一個state變量,useState返回的值是一個數組,然後我們通過數組解構獲取到了兩個變量, const [name, setName] = useState('子君'), 其中name對應聲明的state變量,而setName是一個函數,調用setName可以修改變量的值,比如setName('張三'),這時候name的值就會變成了張三

偵聽器watch,監督你沒毛病

小編在平常開發中是比較常用watch的,使用watch可以去監聽數據的變化,然後在變化之後做一系列的操作。比如有一個列表頁,我們希望用戶在輸入搜索關鍵字的時候,可以自動觸發搜索。此時除了監聽輸入框的input事件之外,還可以通過vue的watch來監聽關鍵字的變化

Vue2.0中的寫法

在vue2.0中,watch常用的寫法包含了兩種,下面我們分別使用不同的寫法來進行上述功能的實現

常規實現

<template>
<div>
<div>
<span>搜索</span>
<input v-model="searchValue" />
</div>
<!--列表,代碼省略-->
</div>
</template>
<script>
export default {
data() {
return {
searchValue: ''
}
},
watch: {
// 在值發生變化之後,重新加載數據
searchValue(newValue, oldValue) {
// 判斷搜索
if (newValue !== oldValue) {
// 在這裡處理搜索邏輯
}
}
}
}
</script>

使用$watch實現

<template>
<div>
<div>
<span>搜索</span>
<input v-model="searchValue" />
</div>
<!--列表,代碼省略-->
</div>
</template>
<script>
export default {
data() {
return {
searchValue: ''
}
},
created() {
// $watch會返回一個unwatch函數,如果需求上需要在某些場景取消watch,可以執行`unwatch`
const unwatch = this.$watch('searchValue', (newValue, oldValue) => {
// 判斷搜索
if (newValue !== oldValue) {
// 在這裡處理搜索邏輯
}
})
}
}
</script>

在調用$watch的時候,會有一個返回值unwatch,然後如果需要取消watch監聽,我們可以通過調用unwatch來進行,比如有一個表單,表單上面的保存按鈕平常是置灰的,但是假如用戶對表單進行了修改,就需要將表單的置灰狀態修改為啟用狀態。但是如果表單已經啟用了,就沒必要繼續watch了,這時候就需要使用unwatch

Vue3.0中的寫法

在Vue3.0中除了Vue2.0中的寫法外,還在Composition API提供了watch與watchEffect兩個API,用於監聽數據的變化,下面我們將上面搜索分別使用watch與watchEffect來實現

<template>
<div>
<span>搜索</span>
<input v-model="state.searchValue" />
</div>
</template>

<script lang="ts">
import { defineComponent, reactive, watch } from "vue";

export default defineComponent({
setup() {
const state = reactive({
searchValue: ""
});
// 通過watch來監聽searchValue的變化
const unwatch = watch(
() => state.searchValue,
(value, oldValue) => {
if (value !== oldValue) {
// 在這裡處理搜索邏輯
}
}
);
return {
state
};
}
});
</script>

watch API與Vue2.0中的this.$watch用法基本是一致的,包括使用的參數等,同時watch API返回了unwatch函數用於取消watch

同時watch還可以偵聽多個屬性的變化,就像下面這樣

watch([a,b,c], ([a,b,c],[oldA,oldB,oldC]) => {

})

watchEffect實現

watchEffect參數是一個函數,在代碼執行時,會立即執行watchEffect傳入的函數,然後響應式追蹤其依賴,並在其中某些依賴發生變化時重新運行該函數。我們將上述搜索代碼使用watchEffect來實現

export default defineComponent({
setup() {
const state = reactive({
searchValue: ""
});
// 加載數據
function loadData(searchValue){

}
// 通過watchEffect來監聽searchValue的變化
const unwatch = watchEffect(() => {
// 當代碼執行到watchEffect時,會立即調用此函數,同時會收集到存在
//`state.searchValue`的依賴,然後當`state.searchValue`發生
//變化時會在此調用watchEffect,已實現數據監聽
loadData(state.searchValue)
});
return {
state
};
}
})

React中的用法

在React中與watch比較相似的功能是Effect Hook,使用它可以讓你在函數組件中執行副作用操作,先來看一下代碼

import React, { useEffect, useState } from 'react'

export default function() {
// useState傳入要初始化的狀態數據,然後會返回一個數組
// 數組第一項為聲明的數據,而第二個參數是一個方法,用於調用
// 修改數據
const [searchValue, setSearchValue] = useState('')

function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
// 在react修改數據需要調用useState返回的方法
setSearchValue(e.target.value);
}

// useEffect接受兩個參數,第一個是回調函數,第二個是要監聽變化的屬性,是一個數組
useEffect(() => {
// 當代碼首次調用useEffect會進入這個回調函數,然後
// 當serchValue 發生變化時,會再次進入到這裡
console.log(111)
},[searchValue])
return (
<div>
<input value={searchValue} onChange={handleChange}></input>

</div>
);
}

如上代碼我們使用useEffect來監聽searchValue的變化,然後觸發新的邏輯,但是看到上面代碼,我們並沒有發現取消effect的方法,那麼如何取消呢?

useEffect第二個參數是一個數組,通過給數組傳入要監聽的變量來實現數據監聽,但是卻沒有辦法去取消這個監聽,所以我們需要曲線救國,就像下面代碼這樣

 const [isWatch] = useState(true)

useEffect(() => {
// 通過isWatch來判斷是否進行監聽邏輯變化
if(isWatch) {
// 監聽數據變化
console.log(searchValue)
}
},[isWatch, searchValue])

計算屬性,在React中我也找到的蹤跡

Vue中的計算屬性,相信大家都很熟悉,通常我們會使用計算屬性來對template中的複雜邏輯計算進行簡化,比如許多英文網站輸入用戶名的時候會輸入firstName和lastName,然後在界面上面又會將firstName和lastName連在一起顯示,這時候就可以使用到了計算屬性對顯示進行處理

Vue2.0中的寫法
<template>
<div>
<div>
<label>firstName</label>
<input v-model="firstName" />
<label>lastName</label>
<input v-model="lastName" />
</div>
<div>用戶名:{{ name }}</div>
</div>
</template>
<script>
export default {
data() {
return {
firstName: '',
lastName: ''
}
},
computed: {
name() {
return this.firstName + '·' + this.lastName
}
}
}
</script>

Vue3.0中的寫法

在Vue3.0的Composition API也提供了computed API,用於生成計算屬性,用法與Vue2.0用法基本是一致的

import { computed, defineComponent, reactive } from "vue";

export default defineComponent({
setup() {
const state = reactive({
firstName: "",
lastName: ""
});
const name = computed(() => state.firstName + "·" + state.lastName);
return {
state,
name
};
}
});

React中的寫法

在說到在React中模擬計算屬性之前,我們先要了解一些React Hook的規則。

當我們在React函數中使用useState之後,如果我們通過setState修改了state,那麼這時候react會做什麼呢?React會將這個函數式組件重新執行一遍,但是對於裡面的useState,useEffect等等不會重新初始化,而是使用已經記錄的狀態進行處理。那麼React是怎麼知道哪個state對應哪個useState呢?答案是React靠的是Hook調用的順序。所以我們不能在非頂層比如if裡面使用Hook。

同時呢?因為state的變化會引起整個函數重新執行,那麼假如我們在代碼裡面寫了這樣一段邏輯

const [firstName, setFirstName] = useState('')
const [lastName, setLastName ] = useState('')
const [other,setOther] = useState('')

// 使用 useMemo可以模仿Vue中的計算屬性
const name = firstName + "·" + lastName;

上面代碼裡面我們的name是通過firstName與lastName計算而來的,那麼當firstName或者lastName發生變化時,都會重新計算name,這個邏輯是正確的。但是實際上other如果發生了變化,也會導致name重新計算,這是我們不願意看到的。假如name的計算邏輯很複雜,那麼就會引起不必要的性能開支。所以React提供了useMemo,用於避免非相關屬性變化引起計算邏輯發生變化,而我們正好可以利用useMemo來模擬計算屬性,如下代碼

import React, {  useMemo, useState } from 'react'

export default function() {
const [firstName, setFirstName] = useState('')
const [lastName, setLastName ] = useState('')

// 使用 useMemo可以模仿Vue中的計算屬性,當firstName與`lastName`任何一個發生變化
//都會觸發`name`重新計算,但是對於其他屬性變化,並不會引起重新計算
const name = useMemo(() => firstName + '·' + lastName,[firstName,lastName])

const handleChange = (method: Function, e: React.ChangeEvent<HTMLInputElement> ) => {
method(e.target.value)
}

return (
<div>
<div>
<label>firstName</label>
<input
value={firstName}
onChange={(e) => handleChange(setFirstName, e)}
/>
<label>lastName</label>
<input
value={lastName}
onChange={(e) => handleChange(setLastName, e)}
/>
</div>
<div>用戶名:{name}</div>
</div>
);
}

但是呢,在Vue中計算屬性既可以get,也可以set,這一點我們是無法使用useMemo來模擬的,當然如果有小夥伴知道如何模擬,麻煩下方評論區告訴我,謝謝。

總結

前端技術發展日新月異,我表示已經學不動了,可是不學怎麼賺錢吃飯,所以還是要學。作為前端主流三大框架之二的Vue和React,在日常工作中還是很常用的,通過這種對比的學習,可以比較好的將兩者聯合在一起,方便記憶。本文首發於公眾號前端有的玩,學前端,面試找工作,就在前端有的玩

相關焦點

  • 前端技術:React&Vue對比
    React和vue的業務邏輯是差不多,vue在react上封裝了更簡潔的方法,使用起來更加的便捷,如:提供了便捷的指令(v-for,v-if,v-model),還提供了更多的屬性(computed,watch),我還是比較喜歡用react的,更接近js原生,更容易於理解它。
  • Vue.js 教程:構建一個特斯拉汽車餘電計算器
    作為本教程的起點,請克隆這個 Github 存儲庫:https://github.com/petereijgermans11/workshop-reactjs-vuejs然後轉至 vuejs-app 目錄。
  • 我居然把 Vue3 的原理用到了 React 上?
    前言vue-next是Vue3的源碼倉庫,Vue3採用lerna做package的劃分,而響應式能力@vue/reactivity被劃分到了單獨的一個package中。如果我們想把它集成到React中,可行嗎?來試一試吧。
  • 快速在你的vue/react應用中實現ssr(服務端渲染)
    摘要ssr(服務端渲染)技術實現方案接下來筆者將列舉幾個常用的基於vue/react的服務端渲染方案,如下:使用next.js/nuxt.js的服務端渲染方案>使用node+vue-server-renderer實現vue項目的服務端渲染使用node+React renderToStaticMarkup實現react項目的服務端渲染傳統網站通過模板引擎來實現ssr(比如ejs, jade, pug等)
  • 前端諸神大戰,Vue、React 依舊笑傲江湖
    來源:https://www.codeinwp.com/blog/angular-vs-vue-vs-react/而從 Google 趨勢的搜索結果來看,React 也依然是目前最受關注的框架,其次是 Vue,而 Angular 的關注度幾乎為零。來源:Google 趨勢就業方面的情況則略有不同。
  • 框架React vs Vue
    如果你不想用組件式開發,選React像不像JQ,React才不幹這種事情如果你想用模版開發,選Vue (JSX Vs 模版)Vue: 提供了模版的方式,將Html,CSS和Script分離,看起來比較的舒服
  • 三年React 開發經驗的我,遷移到 Vue 的心路歷程
    最初僅有 React,後來使用 Redux 和 React 的其他庫(react-router、react-redux、prop-types 等)配合使用。我喜歡 React 的簡單和方便,使用 React 的時光一直都很快樂。我喜歡這個時代,有太多的好工具幫助我們更快更好地開發應用。
  • 精通React/Vue系列之帶你實現一個功能強大的通知提醒框
    本文將會使用React來開發該組件,也會使用到Javascript中常用的一些設計模式,比如單例模式,但是不管你使用什麼框架來實現,原理都是通用的,如果感興趣的朋友可以用vue也實現以一下。如果對設計模式不是很了解,可以移步:15分鐘帶你了解前端工程師必知的javascript設計模式(附詳細思維導圖和源碼).
  • 學點vue.js的東西,什麼都得學點,面試時說不定對方會問什麼
    說vue呢也是關注視圖層的框架,它嫌react太繞了,redux太麻煩了,然後就說自己很簡單,說自己還有雙向綁定,好的很,不是小好
  • 手把手教你用JS/Vue/React實現幸運水果機(80後情懷之作)
    項目體驗地址免費視頻教程分別使用原生JS,Vue和React,手把手教你開發一個H5小遊戲,快速上手Vue和React框架的使用。快速入門vue框架的應用快速入門react框架的應用對比原生js,vue框架和react框架開發的優缺點。
  • Vue.js 很難學?看看這個由 DCloud 與 Vue 官方合作推出的免費入門...
    這對於微小項目可能沒什麼感覺,甚至還很方便,但對於中大型但項目,更適合工程化開發模式的 Vue/react ,只要學會了就真的不會再回去了。這套在線觀看的免費入門視頻教程就是給你們準備的。Vue.js 是目前國內很火的前端框架,前端工程師招聘幾乎都要求掌握。
  • 三個JavaScript框架重量級:Angular,React和Vue
    你可能知道這三個JavaScript框架重量級,但哪一個是正確的?嘗試查看使用每個框架構建的相同應用程式並進行自己的評估。在這篇文章中,我們提出了一個使用三種不同框架開發三次的開源參考應用程式:React,Vue和Angular。
  • JavaScript 框架對比及案例(React、Vue 及 Hyperapp) | Linux 中國
    編譯自 | https://hackernoon.com/javascript-framework-comparison-with-examples-react-vue-hyperapp-97f064fb468d  作者 | Angelos Chalaris 譯者 | Bestony (bestony) 🌟🌟🌟共計翻譯:21 篇 貢獻時間:969 天在我的上一篇文章中
  • React Hooks 與Vue3.0 Function based API的對比?
    'Online' : 'Offline') } </div> )}在上述例子中,你可能會對 useEffect Hook 產生以下疑問:1.useEffect 做了什麼?首先,接收了一個函數,而 React 會保存這個函數(稱為'effect'),並且在執行 DOM 更新後調用這個函數,即添加訂閱。2.
  • Vue、React和Angular:該選擇哪個框架?
    ,我們希望本文對你選擇正確的解決方案能有所幫助。 性能和框架大小 Angular Angular 使用真實 DOM,因此它最適合用於內容不時更新的單頁應用程式。這會使更新過程變得非常緩慢,並且在丟失流的情況下,將需要花費很長時間才能找出問題所在。值得慶幸的是,雙向數據綁定過程將模型中所做的所有更改都以一種安全高效的方式複製到視圖中。
  • Vue、React 和 Angular:該選擇哪個框架?
    性能和框架大小AngularAngular 使用真實 DOM,因此它最適合用於內容不時更新的單頁應用程式。這會使更新過程變得非常緩慢,並且在丟失流的情況下,將需要花費很長時間才能找出問題所在。值得慶幸的是,雙向數據綁定過程將模型中所做的所有更改都以一種安全高效的方式複製到視圖中。
  • 精通react/vue組件設計之實現一個Tag(標籤)和Empty(空狀態)組件
    /vue等MVVM框架的出現,幫我們減少了工作中大量的冗餘代碼, 一切皆組件的思想深得人心.所以, 為了讓工程師們有更多的時間去考慮業務和產品迭代,我們不得不掌握高質量組件設計的思路和方法.所以筆者將花時間去總結各種業務場景下的組件的設計思路和方法,並用原生框架的語法去實現各種常用組件的開發,希望等讓前端新手或者有一定工作經驗的朋友能有所收穫.
  • 前端框架VUE,理解這一點,快速成為大咖
    首先大家要知道,IT行業迅速發展,想成為一個全棧開發工程師,你就要精通後端到前端,進大公司可能要求你在某個技術點有深入研究或者精通。進創業型公司或者小公司,你要明白老闆是招來幹活的,而不是培養你的技術,最後你跳槽,那人家不損失大。
  • 《精通react/vue組件設計》之實現一個健壯的警告提示(Alert)組件
    正文在開始組件設計之前希望大家對css3和js有一定的基礎,並了解基本的react/vue語法.我們先看看實現後的組件效果:1. 組件設計思路按照之前筆者總結的組件設計原則,我們第一步是要確認需求.選手來說,如果沒用typescript,建議大家都用PropTypes, 它是react內置的類型檢測工具,我們可以直接在項目中導入. vue有自帶的屬性檢測方式,這裡就不一一介紹了.
  • 精通react/vue組件設計教你實現一個極具創意的加載(Loading)組件
    正文在開始組件設計之前希望大家對css3和js有一定的基礎,並了解基本的react/vue語法.我們先看看實現後的組件效果:因為動圖體積太大,就不給大家傳gif了,接下來我們具體分析一下該組件的特點.1. 組件設計思路按照之前筆者總結的組件設計原則,我們第一步是要確認需求.