适合Vue用戶的React教程,你(nǐ)值得擁有(二) - 新聞資(zī)訊 - 雲南小程序開發|雲南軟件開發|雲南網站(zhàn)建設-西山區知普網絡科技工作室

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不管是網站(zhàn),軟件還是小程序,都要直接或間接能為您産生價值,我們在追求其視覺表現的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網站(zhàn)成為營銷工具,讓軟件能切實提升企業(yè)内部管理水平和(hé)效率。優秀的程序為後期升級提供便捷的支持!

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

發表時間:2021-1-5

發布人:葵宇科技

浏覽次數:76

今天這篇文(wén)章将會對Vue2,Vue3,React的一些用法進行對比,方便小夥伴們學習。

數據data,在react中(zhōng)叫state

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

Vue2.0中(zhōng)的用法

如(rú)下(xià)代碼是一個(gè)比較簡單的Vue2.0data用法

<template>
  <div>{{ name }}div>
template>
<script>
export default {
  data() {
    return {
      name: '子(zǐ)君',
      gzh: '前端有的玩'
    }
  }
}
script>
複制代碼

通(tōng)過上面的代碼我們可(kě)以看到data是一個(gè)函數,然後函數中(zhōng)返回了一個(gè)對象,那麼為什麼data是一個(gè)函數呢(ne)?比如(rú)我們有時候也會在App.vue文(wén)件中(zhōng)看到data不是函數的情況。

<template>  
    <div id="app">
    <router-view />
  div>
template>
<script>
export default {
  data:{
    name: '子(zǐ)君',
    sex: '男(nán)'
  }
}
script>
複制代碼

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

App.vue可(kě)以将data聲明為一個(gè)普通(tōng)對象是因為整個(gè)系統中(zhōng)App.vue隻會被使用到一次,所以不存在上述的問(wèn)題。

Vue3中(zhōng)的用法

Vue3中(zhōng),我們依然可(kě)以像Vue2那樣去使用data,當然Vue3提供了新的Composition API,在後續文(wén)章中(zhōng),如(rú)果沒有特殊說明,我們提到Vue3就默認指的是使用Composition API

Composition API提供了響應式API,分别是ref和(hé)reactive,通(tōng)過這兩個(gè)API可(kě)以生成響應式的數據

基礎用法
<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: "子(zǐ)君",
      gzh: "前端有的玩"
    });
    const count = ref(0);
    return {
      state,
      count
    };
  }
});
script>

複制代碼
響應數據修改

Vue2.0中(zhōng),我們修改data的方式一般會使用this.name = '張三'這種賦值的方式,但是對于Composition API中(zhōng)因為提供了兩種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: "子(zǐ)君",
      gzh: "前端有的玩"
    });
    
    const count = ref(0);
    
    function handleClick() {
      state.name = "張三";
      count.value++;
    }
    
    return {
      state,
      count,
      handleClick
    };
  }
});
script>

複制代碼

如(rú)上代碼所示:

  1. 對于reactive聲明的數據

    對于reactive,我們可(kě)以通(tōng)過state.name來獲取數據,然後通(tōng)過state.name='張三'來修改數據

  2. 對于ref聲明的數據

    對于ref聲明的數據,ref接受一個(gè)參數值并返回一個(gè)響應式且可(kě)改變的 ref 對象。ref 對象擁有一個(gè)指向内部值的單一屬性 .value。所以我們在代碼中(zhōng)獲取ref對象的數據需要使用count.value的方式,修改值的方式也需要通(tōng)過count.value++的方式。

    但是這裡有一個(gè)特殊的點就是在template,ref對象會自動(dòng)解套,意思就是對于

    統計:{{ count }}
    ,代碼裡面可(kě)以直接使用count,而不需要寫成count.valueVue自己就會将其解套為count.value

React中(zhōng)的用法

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

Vue3.0中(zhōng)提供了Composition API,其實這個(gè)和(hé)Reacthook用法是很相似的,接下(xià)來我們将上文(wén)中(zhōng)我們寫的Vue3.0代碼修改為React版本

import React, { useState } from 'react'

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

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

  return (
    <div onClick={handleClick}>
      <div>姓名:{name}div>
      <div>公衆号: {gzh}div>
    div>
  );
}
複制代碼

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

偵聽器(qì)watch,監督你(nǐ)沒毛病

小編在平常開發中(zhōng)是比較常用watch的,使用watch可(kě)以去監聽數據的變化,然後在變化之後做一系列的操作。比如(rú)有一個(gè)列表頁,我們希望用戶在輸入搜索關(guān)鍵字的時候,可(kě)以自動(dòng)觸發搜索。此時除了監聽輸入框的input事件之外,還可(kě)以通(tōng)過vuewatch來監聽關(guān)鍵字的變化

Vue2.0中(zhōng)的寫法

vue2.0中(zhōng),watch常用的寫法包含了兩種,下(xià)面我們分别使用不同的寫法來進行上述功能的實現

  1. 常規實現

    <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>
    
    複制代碼
  2. 使用$watch實現

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

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

Vue3.0中(zhōng)的寫法

Vue3.0中(zhōng)除了Vue2.0中(zhōng)的寫法外,還在Composition API提供了watchwatchEffect兩個(gè)API,用于監聽數據的變化,下(xià)面我們将上面搜索分别使用watchwatchEffect來實現

  1. watch實現方式
<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: ""
    });
    // 通(tōng)過watch來監聽searchValue的變化
    const unwatch = watch(
      () => state.searchValue,
      (value, oldValue) => {
        if (value !== oldValue) {
          // 在這裡處理搜索邏輯
        }
      }
    );
    return {
      state
    };
  }
});
script>

複制代碼

watch APIVue2.0中(zhōng)的this.$watch用法基本是一緻的,包括使用的參數等,同時watch API返回了unwatch函數用于取消watch

同時watch還可(kě)以偵聽多個(gè)屬性的變化,就像下(xià)面這樣

watch([a,b,c], ([a,b,c],[oldA,oldB,oldC]) => {
  
})
複制代碼
  1. watchEffect實現

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

    export default defineComponent({
      setup() {
        const state = reactive({
          searchValue: ""
        });
        // 加載數據
        function loadData(searchValue){
          
        }
        // 通(tōng)過watchEffect來監聽searchValue的變化
        const unwatch = watchEffect(() => {
          // 當代碼執行到watchEffect時,會立即調用此函數,同時會收集到存在
          //`state.searchValue`的依賴,然後當`state.searchValue`發生
          //變化時會在此調用watchEffect,已實現數據監聽
          loadData(state.searchValue)
        });
        return {
          state
        };
      }
    })
    複制代碼

React中(zhōng)的用法

React中(zhōng)與watch比較相似的功能是Effect Hook,使用它可(kě)以讓你(nǐ)在函數組件中(zhōng)執行副作用操作,先來看一下(xià)代碼

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

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

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

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

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

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

 const [isWatch] = useState(true)

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

計算屬性,在React中(zhōng)我也找到的蹤迹

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

Vue2.0中(zhōng)的寫法

<template>
  <div>
    <div>
      <label>firstNamelabel>
      <input v-model="firstName" />
      <label>lastNamelabel>
      <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中(zhōng)的寫法

Vue3.0Composition 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中(zhōng)的寫法

在說到在React中(zhōng)模拟計算屬性之前,我們先要了解一些React Hook的規則。

  1. 隻能在最頂層使用Hook
  2. 隻能在React函數中(zhōng)調用Hook

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

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

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

// 使用 useMemo可(kě)以模仿Vue中(zhōng)的計算屬性
const name = firstName + "·" + lastName;
複制代碼

上面代碼裡面我們的name是通(tōng)過firstNamelastName計算而來的,那麼當firstName或者lastName發生變化時,都會重新計算name,這個(gè)邏輯是正确的。但是實際上other如(rú)果發生了變化,也會導緻name重新計算,這是我們不願意看到的。假如(rú)name的計算邏輯很複雜,那麼就會引起不必要的性能開支。所以React提供了useMemo,用于避免非相關(guān)屬性變化引起計算邏輯發生變化,而我們正好可(kě)以利用useMemo來模拟計算屬性,如(rú)下(xià)代碼

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

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

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

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

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

但是呢(ne),在Vue中(zhōng)計算屬性既可(kě)以get,也可(kě)以set,這一點我們是無法使用useMemo來模拟的,當然如(rú)果有小夥伴知道如(rú)何模拟,麻煩下(xià)方評論區告訴我,謝謝。

總結

作為前端主流三大框架之二的Vue和(hé)React,在日常工作中(zhōng)還是很常用的,通(tōng)過這種對比的學習,可(kě)以比較好的将兩者聯合在一起,方便記憶。


作者:前端進擊者
來源:掘金
著作權歸作者所有。商(shāng)業(yè)轉載請聯系作者獲得授權,非商(shāng)業(yè)轉載請注明出處。

相關(guān)案例查看更多