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

159-8711-8523

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

知識

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

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

發表時間:2021-1-5

發布人:葵宇科技

浏覽次數:38

小編日常工作中(zhōng)使用的是Vue,對于React隻是做過簡單的了解,并沒有做過深入學習。趁着這個(gè)雙節假期,小編決定好好學一學React,今天這篇文(wén)章就是小編在學習React之後,将ReactVue的用法做的一個(gè)對比,通(tōng)過這個(gè)對比,方便使用Vue的小夥伴可(kě)以快速将Vue中(zhōng)的寫法轉換為React的寫法。

插槽,在React中(zhōng)沒找到??

在使用Vue的時候,插槽是一個(gè)特别常用的功能,通(tōng)過定義插槽,可(kě)以在調用組件的時候将外部的内容傳入到組件内部,顯示到指定的位置。在Vue中(zhōng),插槽分為默認插槽,具名插槽和(hé)作用域插槽。其實不僅僅Vue,在React中(zhōng)其實也有類似插槽的功能,隻是名字不叫做插槽,下(xià)面我将通(tōng)過舉例來說明。

默認插槽

現在項目需要開發一個(gè)卡片組件,如(rú)下(xià)圖所示,卡片可(kě)以指定标題,然後卡片内容可(kě)以用戶自定義,這時候對于卡片内容來說,就可(kě)以使用插槽來實現,下(xià)面我們就分别使用Vue和(hé)React來實現這個(gè)功能

Vue實現

  1. 首先實現一個(gè)card組件,如(rú)下(xià)代碼所示

    
    
    
    複制代碼

    可(kě)以看到上面我們使用了,這個(gè)就是組件的默認插槽,在使用組件的時候,傳入的内容将會被放到所在位置

  2. 在外部使用定義的card組件

    
    
    
    複制代碼

    如(rú)上代碼,就可(kě)以使用組件的默認插槽将外部的内容應用到組件裡面指定的位置了。

React實現

雖然在React裡面沒有插槽的概念,但是React裡面也可(kě)以通(tōng)過props.children拿到組件标簽内部的子(zǐ)元素的,就像上面代碼标簽内的子(zǐ)元素,通(tōng)過這個(gè)我們也可(kě)以實現類似Vue默認插槽的功能,一起看看代碼。

  1. 使用React定義Card組件

    import React from 'react'
    
    export interface CardProps {
      title: string,
      children: React.ReactNode
    }
    
    export default function(props: CardProps) {
    
      return (
        
    {props.title}
    {/**每個(gè)組件都可(kě)以獲取到 props.children。它包含組件的開始标簽和(hé)結束标簽之間的内容 */} {props.children}
    ); } 複制代碼
    1. 在外部使用Card組件
    import React from 'react'
    import Card from './components/Card'
    
    export default function () {
    
      return (
        
    我将被放在card組件的body區域内容
    ); } 複制代碼

具名插槽

繼續以上面的Card組件為例,假如(rú)我們現在需求發生了變化,組件的title也可(kě)以使用插槽,這時候對于Vue就可(kě)以使用具名插槽了,而React也是有辦法實現的哦。

Vue實現

Vue的具名插槽主要解決的是一個(gè)組件需要多個(gè)插槽的場景,其實現是為添加name屬性來實現了。

  1. 我們就上面的需求對card組件進行修改



複制代碼
  1. card組件修改完之後,我們再去調整一下(xià)使用card組件的地方



複制代碼
React實現

React連插槽都沒有, 更别提具名插槽了,但是沒有不代表不能模拟出來。對于Reactprops,我們不僅僅可(kě)以傳入普通(tōng)的屬性,還可(kě)以傳入一個(gè)函數,這時候我們就可(kě)以在傳入的這個(gè)函數裡面返回JSX,從而就實現了具名插槽的功能。

  1. 對原有的Card組件進行修改
import React from 'react'

export interface CardProps {
  title?: string,
  // 加入了一個(gè)renderTitle屬性,屬性類型是Function
  renderTitle?: Function,
  children: React.ReactNode
}

export default function(props: CardProps) {

  const {title, renderTitle} = props
  // 如(rú)果指定了renderTtile,則使用renderTitle,否則使用默認的title
  let titleEl = renderTitle ? renderTitle() : {title}

  return (
    
{titleEl}
{/**每個(gè)組件都可(kě)以獲取到 props.children。它包含組件的開始标簽和(hé)結束标簽之間的内容 */} {props.children}
); } 複制代碼
  1. 這時候就可(kě)以在外部自定義title
import React from 'react'
import Card from './components/Card'

export default function () {
  return (
    
{ return 我是自定義的标題 } }>
我将被放在card組件的body區域内容
); } 複制代碼

作用域插槽

有時讓插槽内容能夠訪問(wèn)子(zǐ)組件中(zhōng)才有的數據是很有用的,這個(gè)就是Vue提供作用域插槽的原因。我們繼續使用上面的Card組件為例,現在我基于上面的卡片組件開發了一個(gè)人員信息卡片組件,用戶直接使用人員信息卡片組件就可(kě)以将人員信息顯示到界面中(zhōng),但是在某些業(yè)務模塊需要自定義人員信息顯示方式,這時候我們就需要使用到作用域插槽了。

Vue實現
  1. 實現用戶信息卡片組件,裡面使用了作用域插槽



複制代碼
  1. 在外部使用人員信息組件



複制代碼
React實現

在具名插槽那一小節我們通(tōng)過給組件傳入了一個(gè)函數,然後在函數中(zhōng)返回JSX的方式來模拟了具名插槽,那麼對于作用域插槽,我們依然可(kě)以使用函數的這種方式,而作用域插槽傳遞的參數我們可(kě)以使用給函數傳參的方式來替代

  1. 實現人員信息卡片組件

    import React, { useState } from 'react'
    
    import Card from './Card'
    
    interface UserCardProps {
      renderUserInfo?: Function
    }
    
    export interface UserInfo {
      name: string;
      age: number;
      sex: string;
    }
    
    export default function(props: UserCardProps) {
      const [userInfo] = useState({
        name: "張三",
        age: 25,
        sex: "男(nán)",
      });
    
      const content = props.renderUserInfo ? (
        props.renderUserInfo(userInfo)
      ) : (
        
    姓名: {userInfo.name} 年齡: {userInfo.age} 性别: {userInfo.sex}
    ); return {content} } 複制代碼
  1. 在外部使用人員信息卡片組件

    import React from 'react'
    import UserCard, { UserInfo } from "./components/UserCard";
    
    export default function () {
    
      return (
        
    { return (
    • 姓名: {userInfo.name}
    ); }} >
    ); } 複制代碼

Context, React中(zhōng)的provide/inject

通(tōng)常我們在項目開發中(zhōng),對于多組件之間的狀态管理,在Vue中(zhōng)會使用到Vuex,在React中(zhōng)會使用到redux或者Mobx,但對于小項目來說,使用這些狀态管理庫就顯得比較大材小用了,那麼在不使用這些庫的情況下(xià),如(rú)何去完成數據管理呢(ne)?比如(rú)面試最常問(wèn)的祖孫組件通(tōng)信。在Vue中(zhōng)我們可(kě)以使用provide/inject,在React中(zhōng)我們可(kě)以使用Context

假設有這樣一個(gè)場景,系統現在需要提供一個(gè)換膚功能,用戶可(kě)以切換皮膚,現在我們分别使用Vue和(hé)React來實現這個(gè)功能。

Vue中(zhōng)的provide/inject

Vue中(zhōng)我們可(kě)以使用provide/inject來實現跨多級組件進行傳值,就以上面所說場景為例,我們使用provide/inject來實現以下(xià)

首先,修改App.vue内容為以下(xià)内容




複制代碼

然後在任意層級的子(zǐ)組件中(zhōng)像下(xià)面這樣使用




複制代碼

這樣就可(kě)以實現theme在所有子(zǐ)組件中(zhōng)進行共享了

React中(zhōng)的Context

Vue中(zhōng)我們使用provide/inject實現了組件跨層級傳值功能,在React中(zhōng)也提供了類似的功能即Context,下(xià)面我們使用Context來實現相同的功能。

在項目src目錄下(xià)新建context目錄,添加MyContext.js文(wén)件,然後添加以下(xià)内容

import {createContext} from 'react'
// 定義 MyContext,指定默認的主題為`light`
export const MyContext = createContext({
  theme: 'light'
})
複制代碼

MyContext提供了一個(gè)Provider,通(tōng)過Provider可(kě)以将theme共享到所有的子(zǐ)組件。現在我們在所有的組件的共同父組件比如(rú)App.js上面添加MyContext.Providertheme共享出去

import { MyContext } from '@/context/MyContext';

export default function() {
  
  const [theme, setTheme] = useState('dark')
  
  return (
    
        
     
    )
  }

複制代碼

然後這時候就可(kě)以直接在所有的子(zǐ)組件裡面使用定義的主題theme

import React, { useContext } from 'react'
import { MyContext } from '@/context/MyContext';

export default function() {
   const {theme}  = useContext(MyContext)
   return 
} 複制代碼

沒有了v-model,但也不影響使用

我們知道React和(hé)Vue都是單向數據流的,即數據的流向都是由外層向内層組件進行傳遞和(hé)更新的,比如(rú)下(xià)面這段React代碼就是标準的單向數據流.

import React, { useState } from "react";

export default function(){
  const [name] = useState('子(zǐ)君')
  return 
}
複制代碼

vue中(zhōng)使用v-model

如(rú)上代碼,我們在通(tōng)過通(tōng)過value屬性将外部的值傳遞給了input組件,這個(gè)就是一個(gè)簡單的單向數據流。但是在使用Vue的時候,還有兩個(gè)比較特殊的語法糖v-model和(hé).sync,這兩個(gè)語法糖可(kě)以讓Vue組件擁有雙向數據綁定的能力,比如(rú)下(xià)面的代碼



複制代碼

通(tōng)過v-model,當用戶修改input的值的時候,外部的name的值也将同步被修改。但這是Vue的語法糖啊,React是不支持的,所以React應該怎麼辦呢(ne)?這時候再想想自定義v-modelv-model實際上是通(tōng)過定義value屬性同時監聽input事件來實現的,比如(rú)這樣:



複制代碼

react尋找v-model替代方案

同理,React雖然沒有v-model語法糖,但是也可(kě)以通(tōng)過傳入屬性然後監聽事件來實現數據的雙向綁定。

import React, { useState } from 'react'

export default function() {
  const [name, setName] = useState('子(zǐ)君')

  const handleChange = (e) => {
    setName(e.target.value)
  }
  return 
} 複制代碼

小編剛開始使用react,感覺沒有v-model就顯得比較麻煩,不過麻煩歸麻煩,代碼改寫也要寫。就像上文(wén)代碼一樣,每一個(gè)表單元素都需要監聽onChange事件,越發顯得麻煩了,這時候就可(kě)以考慮将多個(gè)onChange事件合并成一個(gè),比如(rú)像下(xià)面代碼這樣

import React, { useState } from 'react'

export default function () {
  const [name, setName] = useState('子(zǐ)君')
  const [sex, setSex] = useState('男(nán)')

  const handleChange = (e:any, method: Function) => {
    method(e.target.value)
  }
  return 
handleChange(e, setName)}> handleChange(e, setSex)}>
} 複制代碼

沒有了指令,我感覺好迷茫

Vue中(zhōng)我們一般繪制頁面都會使用到templatetemplate裡面提供了大量的指令幫助我們完成業(yè)務開發,但是在React中(zhōng)使用的是JSX,并沒有指令,那麼我們應該怎麼做呢(ne)?下(xià)面我們就将Vue中(zhōng)最常用的一些指令轉換為JSX裡面的語法(注意: 在Vue中(zhōng)也可(kě)以使用JSX)

v-showv-if

Vue中(zhōng)我們隐藏顯示元素可(kě)以使用v-show或者v-if,當然這兩者的使用場景是有所不同的,v-show是通(tōng)過設置元素的display樣式來顯示隐藏元素的,而v-if隐藏元素是直接将元素從dom中(zhōng)移除掉。

  1. 看一下(xià)Vue中(zhōng)的v-showv-if的用法

    
    
    
    複制代碼
  2. v-showv-if轉換為JSX中(zhōng)的語法

    Vue中(zhōng)指令是為了在template方便動(dòng)态操作數據而存在的,但是到了React中(zhōng)我們寫的是JSX,可(kě)以直接使用JS,所以指令是不需要存在的,那麼上面的v-show,v-if如(rú)何在JSX中(zhōng)替代呢(ne)

    import React, { useState } from 'react'
    
    export default function() {
      const [showName] = useState(false)
    
      const [showDept] = useState(true)
    
      const [userInfo] = useState({
        name:'子(zǐ)君',
        dept: '銀河帝國'
      })
    
      return (
        
    {/**模拟 v-show */} {userInfo.name} {/**模拟 v-if */} {showDept ? {userInfo.dept}: undefined}
    ) } 複制代碼

v-for

v-forVue中(zhōng)是用來遍曆數據的,同時我們在使用v-for的時候需要給元素指定keykey的值一般是數據的id或者其他唯一且固定的值。不僅在Vue中(zhōng),在React中(zhōng)也是存在key的,兩者的key存在的意義基本一緻,都是為了優化虛拟DOM diff算法而存在的。

  1. Vue中(zhōng)使用v-for

    
    
    
    複制代碼
  1. React中(zhōng)使用v-for的替代語法

    react中(zhōng)雖然沒有v-for,但是JSX中(zhōng)可(kě)以直接使用JS,所以我們可(kě)以直接遍曆數組

    import React from 'react'
    
    export default function() {
      const data = http://www.wxapp-union.com/[
        {
          id: 1,
          name:"子(zǐ)君",
        },
        {
          id: "2",
          name: "張三",
        },
        {
          id: "3",
          name: "李四",
        },
      ];
    
      return (
        
      { data.map(item => { return
    • {item.name}
    • }) }
    ) } 複制代碼

v-bindv-on

v-bindVue中(zhōng)是動(dòng)态綁定屬性的,v-on是用于監聽事件的,因為React也有屬性和(hé)事件的概念,所以我們在React也能發現可(kě)替代的方式。

  1. Vue中(zhōng)使用v-bindv-on

    
    
    
    複制代碼
  2. React中(zhōng)尋找替代方案

    Vue中(zhōng),作者将事件和(hé)屬性進行了分離(lí),但是在React中(zhōng),其實事件也是屬性,所以在本小節我們不僅看一下(xià)如(rú)何使用屬性和(hé)事件,再了解一下(xià)如(rú)何在React中(zhōng)自定義事件

    • 開發一個(gè)CustomInput組件

      import React from 'react'
      
      export interface CustomInputProps {
        value: string;
        //可(kě)以看出 onChange是一個(gè)普通(tōng)的函數,也被定義到了組件的props裡面了
        onChange: ((value: string,event: React.ChangeEvent) => void) | undefined;
      }
      
      export default function(props: CustomInputProps) {
        
        function handleChange(e: React.ChangeEvent) {
          // props.onChange是一個(gè)屬性,也是自定義的一個(gè)事件
          props.onChange && props.onChange(e.target.value, e)
        }
      
        return (
          
        )
      }
      複制代碼
  • 使用CustomInput組件

    import React, { useState } from 'react'
    
    import CustomInput from './components/CustomInput'
    
    export default function() {
     const [value, setValue] =  useState('')
    
     function handleChange(value: string) {
       setValue(value)
     }
    
      return (
        
    ) } 複制代碼

    總結

    剛開始從Vue轉到React的時候,其實是有點不适應的,但是當慢慢的習慣之後,就會發現Vue和(hé)React是存在很多共性的,可(kě)以參考的去學習。當然無論Vue還是React,上手比較快,但是想深入學習還是需要下(xià)功夫的,後續小編将會對Vue和(hé)React的用法在做更深入的介紹,敬請期待。


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

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