<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 14499字,需瀏覽 29分鐘

           ·

          2021-06-21 23:49

          雙節(jié)旅游人如山,不如家中代碼閑。 學(xué)以致用加班少,王者榮耀家中玩。

          小編日常工作中使用的是Vue,對于React只是做過簡單的了解,并沒有做過深入學(xué)習(xí)。趁著這個雙節(jié)假期,小編決定好好學(xué)一學(xué)React,今天這篇文章就是小編在學(xué)習(xí)React之后,將ReactVue的用法做的一個對比,通過這個對比,方便使用Vue的小伙伴可以快速將Vue中的寫法轉(zhuǎn)換為React的寫法。

          插槽,在React中沒找到??

          在使用Vue的時候,插槽是一個特別常用的功能,通過定義插槽,可以在調(diào)用組件的時候?qū)⑼獠康膬?nèi)容傳入到組件內(nèi)部,顯示到指定的位置。在Vue中,插槽分為默認插槽,具名插槽和作用域插槽。其實不僅僅Vue,在React中其實也有類似插槽的功能,只是名字不叫做插槽,下面我將通過舉例來說明。

          默認插槽

          現(xiàn)在項目需要開發(fā)一個卡片組件,如下圖所示,卡片可以指定標題,然后卡片內(nèi)容可以用戶自定義,這時候?qū)τ诳ㄆ瑑?nèi)容來說,就可以使用插槽來實現(xiàn),下面我們就分別使用VueReact來實現(xiàn)這個功能

          Vue實現(xiàn)

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

            <template>
            <div class="card">
            <div class="card__title">
            <span>{{ title }}</span>
            </div>
            <div class="card__body">
            <slot></slot>
            </div>
            </div>
            </template>
            <script>
            export default {
            props: {
            title: {
            type: String,
            default: ''
            }
            }
            }
            </script>

            可以看到上面我們使用了<slot></slot>,這個就是組件的默認插槽,在使用組件的時候,傳入的內(nèi)容將會被放到<slot></slot>所在位置

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

            <template>
            <div>
            <my-card>
            <div>我將被放在card組件的默認插槽里面</div>
            </my-card>
            </div>
            </template>
            <script>
            import MyCard from '../components/card'
            export default {
            components: {
            MyCard
            }
            }
            </script>

            如上代碼,就可以使用組件的默認插槽將外部的內(nèi)容應(yīng)用到組件里面指定的位置了。

          React實現(xiàn)

          雖然在React里面沒有插槽的概念,但是React里面也可以通過props.children拿到組件標簽內(nèi)部的子元素的,就像上面代碼<my-card>標簽內(nèi)的子元素,通過這個我們也可以實現(xiàn)類似Vue默認插槽的功能,一起看看代碼。

          1. 使用React定義Card組件

            import React from 'react'

            export interface CardProps {
            title: string,
            children: React.ReactNode
            }

            export default function(props: CardProps) {

            return (
            <div className="card">
            <div className="card__title">
            <span>{props.title}</span>
            </div>
            <div className="card__body">
            {/**每個組件都可以獲取到 props.children。它包含組件的開始標簽和結(jié)束標簽之間的內(nèi)容 */}
            {props.children}
            </div>
            </div>
            );
            }
            import React from 'react'
            import Card from './components/Card'

            export default function () {

            return (
            <div>
            <Card title="標題">
            <div>我將被放在card組件的body區(qū)域內(nèi)容</div>
            </Card>
            </div>
            );
            }
            1. 在外部使用Card組件

          具名插槽

          繼續(xù)以上面的Card組件為例,假如我們現(xiàn)在需求發(fā)生了變化,組件的title也可以使用插槽,這時候?qū)τ?code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Vue就可以使用具名插槽了,而React也是有辦法實現(xiàn)的哦。

          Vue實現(xiàn)

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

          1. 我們就上面的需求對card組件進行修改
          <template>
          <div class="card">
          <div class="card__title">
          <!--如果傳入了title,則使用title屬性,否則是否具名插槽-->
          <span v-if="title">{{ title }}</span>
          <slot v-else name="title"></slot>
          </div>
          <div class="card__body">
          <!--對于內(nèi)容區(qū)域依然使用默認插槽-->
          <slot></slot>
          </div>
          </div>
          </template>
          <script>
          export default {
          props: {
          title: {
          type: String,
          default: ''
          }
          }
          }
          </script>

          1. card組件修改完之后,我們再去調(diào)整一下使用card組件的地方
          <template>
          <div>
          <my-card>
          <!--通過v-slot:title 使用具名插槽-->
          <template v-slot:title>
          <span>這里是標題</span>
          </template>
          <div>我將被放在card組件的默認插槽里面</div>
          </my-card>
          </div>
          </template>
          <script>
          import MyCard from '../components/card'
          export default {
          components: {
          MyCard
          }
          }
          </script>

          React實現(xiàn)

          React連插槽都沒有, 更別提具名插槽了,但是沒有不代表不能模擬出來。對于Reactprops,我們不僅僅可以傳入普通的屬性,還可以傳入一個函數(shù),這時候我們就可以在傳入的這個函數(shù)里面返回JSX,從而就實現(xiàn)了具名插槽的功能。

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

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

          export default function(props: CardProps) {

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

          return (
          <div className="card">
          <div className="card__title">{titleEl}</div>
          <div className="card__body">
          {/**每個組件都可以獲取到 props.children。它包含組件的開始標簽和結(jié)束標簽之間的內(nèi)容 */}
          {props.children}
          </div>
          </div>
          );
          }
          1. 這時候就可以在外部自定義title
          import React from 'react'
          import Card from './components/Card'

          export default function () {
          return (
          <div>
          <Card renderTitle={
          () => {
          return <span>我是自定義的標題</span>
          }
          }>
          <div>我將被放在card組件的body區(qū)域內(nèi)容</div>
          </Card>
          </div>
          );
          }

          作用域插槽

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

          Vue實現(xiàn)
          1. 實現(xiàn)用戶信息卡片組件,里面使用了作用域插槽
          <template>
          <custom-card title="人員信息卡片">
          <div class="content">
          <!--這里使用了作用域插槽,將userInfo傳出去了-->
          <slot name="userInfo" :userInfo="userInfo">
          <!--如果沒有使用插槽,則顯示默認內(nèi)容-->
          <span>姓名: {{ userInfo.name }}</span>
          <span>性別: {{ userInfo.sex }}</span>
          <span>年齡: {{ userInfo.age }}</span>
          </slot>
          </div>
          </custom-card>
          </template>
          <script>
          import CustomCard from '../card'
          export default {
          components: {
          CustomCard
          },
          data() {
          return {
          userInfo: {
          name: '張三',
          sex: '男',
          age: 25
          }
          }
          }
          }
          </script>

          1. 在外部使用人員信息組件
          <template>
          <div>
          <user-card>
          <template v-slot:userInfo="{ userInfo }">
          <div class="custom-user">
          <ul>
          <li>姓名: {{ userInfo.name }}</li>
          <li>年齡: {{ userInfo.age }}</li>
          </ul>
          </div>
          </template>
          </user-card>
          </div>
          </template>
          <script>
          import UserCard from '../components/user-card'
          export default {
          components: {
          UserCard
          }
          }
          </script>

          React實現(xiàn)

          在具名插槽那一小節(jié)我們通過給組件傳入了一個函數(shù),然后在函數(shù)中返回JSX的方式來模擬了具名插槽,那么對于作用域插槽,我們依然可以使用函數(shù)的這種方式,而作用域插槽傳遞的參數(shù)我們可以使用給函數(shù)傳參的方式來替代

          1. 實現(xiàn)人員信息卡片組件

            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<UserInfo>({
            name: "張三",
            age: 25,
            sex: "男",
            });

            const content = props.renderUserInfo ? (
            props.renderUserInfo(userInfo)
            ) : (
            <div>
            <span>姓名: {userInfo.name}</span>
            <span>年齡: {userInfo.age}</span>
            <span>性別: {userInfo.sex}</span>
            </div>
            );

            return <Card title="人員信息">
            {content}
            </Card>
            }
          2. 在外部使用人員信息卡片組件

            import React from 'react'
            import UserCard, { UserInfo } from "./components/UserCard";

            export default function () {

            return (
            <div>
            <UserCard
            renderUserInfo={(userInfo: UserInfo) => {
            return (
            <ul>
            <li>姓名: {userInfo.name}</li>
            </ul>
            );
            }}
            ></UserCard>
            </div>
            );
            }

          Context, React中的provide/inject

          通常我們在項目開發(fā)中,對于多組件之間的狀態(tài)管理,在Vue中會使用到Vuex,在React中會使用到redux或者Mobx,但對于小項目來說,使用這些狀態(tài)管理庫就顯得比較大材小用了,那么在不使用這些庫的情況下,如何去完成數(shù)據(jù)管理呢?比如面試最常問的祖孫組件通信。在Vue中我們可以使用provide/inject,在React中我們可以使用Context

          假設(shè)有這樣一個場景,系統(tǒng)現(xiàn)在需要提供一個換膚功能,用戶可以切換皮膚,現(xiàn)在我們分別使用VueReact來實現(xiàn)這個功能。

          Vue中的provide/inject

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

          首先,修改App.vue內(nèi)容為以下內(nèi)容

          <template>
          <div id="app">
          <router-view />
          </div>
          </template>

          <script>
          export default {
          data() {
          return {
          themeInfo: {
          theme: 'dark'
          }
          }
          },
          provide() {
          return {
          theme: this.themeInfo
          }
          }
          }
          </script>

          然后在任意層級的子組件中像下面這樣使用

          <template>
          <div :class="`child-${theme.theme}`">
          </div>
          </template>
          <script>
          export default {
          inject: ['theme']
          }
          </script>

          這樣就可以實現(xiàn)theme在所有子組件中進行共享了

          React中的Context

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

          在項目src目錄下新建context目錄,添加MyContext.js文件,然后添加以下內(nèi)容

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

          MyContext提供了一個Provider,通過Provider可以將theme共享到所有的子組件。現(xiàn)在我們在所有的組件的共同父組件比如App.js上面添加MyContext.Providertheme共享出去

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

          export default function() {

          const [theme, setTheme] = useState('dark')

          return (
          <MyContext.Provider
          value={{
          theme
          }}
          >
          <Children></Children>
          </MyContext.Provider>
          )
          }

          然后這時候就可以直接在所有的子組件里面使用定義的主題theme

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

          export default function() {
          const {theme} = useContext(MyContext)
          return <div className={`child-${theme}`}>
          }

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

          我們知道ReactVue都是單向數(shù)據(jù)流的,即數(shù)據(jù)的流向都是由外層向內(nèi)層組件進行傳遞和更新的,比如下面這段React代碼就是標準的單向數(shù)據(jù)流.

          import React, { useState } from "react";

          export default function(){
          const [name] = useState('子君')
          return <input value={name}></input>
          }

          vue中使用v-model

          如上代碼,我們在通過通過value屬性將外部的值傳遞給了input組件,這個就是一個簡單的單向數(shù)據(jù)流。但是在使用Vue的時候,還有兩個比較特殊的語法糖v-model.sync,這兩個語法糖可以讓Vue組件擁有雙向數(shù)據(jù)綁定的能力,比如下面的代碼

          <template>
          <input v-model="name"/>
          </template>
          <script>
          export default {
          data() {
          return {
          name:'子君'
          }
          }
          }
          </script>

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

          <template>
          <div class="custom-input">
          <input :value="value" @input="$_handleChange"/>
          </div>
          </template>
          <script>
          export default {
          props:{
          value:{
          type: String,
          default: ''
          }
          },
          methods:{
          $_handleChange(e) {
          this.$emit('input', e.target.value)
          }
          }
          }
          </script>

          react尋找v-model替代方案

          同理,React雖然沒有v-model語法糖,但是也可以通過傳入屬性然后監(jiān)聽事件來實現(xiàn)數(shù)據(jù)的雙向綁定。

          import React, { useState } from 'react'

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

          const handleChange = (e) => {
          setName(e.target.value)
          }
          return <div>
          <input value={name} onChange={handleChange}></input>
          </div>
          }

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

          import React, { useState } from 'react'

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

          const handleChange = (e:any, method: Function) => {
          method(e.target.value)
          }
          return <div>
          <input value={name} onChange={(e) => handleChange(e, setName)}></input>
          <input value={sex} onChange={(e) => handleChange(e, setSex)}></input>
          </div>
          }

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

          Vue中我們一般繪制頁面都會使用到templatetemplate里面提供了大量的指令幫助我們完成業(yè)務(wù)開發(fā),但是在React中使用的是JSX,并沒有指令,那么我們應(yīng)該怎么做呢?下面我們就將Vue中最常用的一些指令轉(zhuǎn)換為JSX里面的語法(注意: 在Vue中也可以使用JSX)

          v-showv-if

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

          1. 看一下Vue中的v-showv-if的用法

            <template>
            <div>
            <span v-show="showName">姓名:{{ name }}</span>
            <span v-if="showDept">{{ dept }}</span>
            </div>
            </template>
            <script>
            export default {
            data() {
            return {
            name: '子君',
            dept: '銀河帝國',
            showName: false,
            showDept: true
            }
            }
            }
            </script>

          2. v-showv-if轉(zhuǎn)換為JSX中的語法

            Vue中指令是為了在template方便動態(tài)操作數(shù)據(jù)而存在的,但是到了React中我們寫的是JSX,可以直接使用JS,所以指令是不需要存在的,那么上面的v-show,v-if如何在JSX中替代呢

            import React, { useState } from 'react'

            export default function() {
            const [showName] = useState(false)

            const [showDept] = useState(true)

            const [userInfo] = useState({
            name:'子君',
            dept: '銀河帝國'
            })

            return (
            <div>
            {/**模擬 v-show */}
            <span style={{display: showName ? 'block' : 'none'}}>{userInfo.name}</span>
            {/**模擬 v-show */}
            {showDept ? <span>{userInfo.dept}</span>: undefined}
            </div>
            )
            }

          v-for

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

          1. Vue中使用v-for

            <template>
            <div>
            <ul>
            <li v-for="item in list" :key="item.id">
            {{ item.name }}
            </li>
            </ul>
            </div>
            </template>
            <script>
            export default {
            data() {
            return {
            list: [
            {
            id: 1,
            name: '子君'
            },
            {
            id: '2',
            name: '張三'
            },
            {
            id: '3',
            name: '李四'
            }
            ]
            }
            }
            }
            </script>

          2. React中使用v-for的替代語法

            react中雖然沒有v-for,但是JSX中可以直接使用JS,所以我們可以直接遍歷數(shù)組

            import React from 'react'

            export default function() {
            const data = [
            {
            id: 1,
            name: "子君",
            },
            {
            id: "2",
            name: "張三",
            },
            {
            id: "3",
            name: "李四",
            },
            ];

            return (
            <div>
            <ul>
            {
            data.map(item => {
            return <li key={item.id}>{item.name}</li>
            })
            }
            </ul>
            </div>
            )
            }

          v-bindv-on

          v-bindVue中是動態(tài)綁定屬性的,v-on是用于監(jiān)聽事件的,因為React也有屬性和事件的概念,所以我們在React也能發(fā)現(xiàn)可替代的方式。

          1. Vue中使用v-bindv-on

            <template>
            <div>
            <!--:value是v-bind:value的簡寫, @input是v-on:input的簡寫-->
            <input :value="value" @input="handleInput" />
            </div>
            </template>
            <script>
            export default {
            data() {
            return {
            value: '子君'
            }
            },
            methods: {
            handleInput(e) {
            this.value = e.target.value
            }
            }
            }
            </script>

          2. React中尋找替代方案

            Vue中,作者將事件和屬性進行了分離,但是在React中,其實事件也是屬性,所以在本小節(jié)我們不僅看一下如何使用屬性和事件,再了解一下如何在React中自定義事件

            開發(fā)一個CustomInput組件

            import React from 'react'

            export interface CustomInputProps {
            value: string;
            //可以看出 onChange是一個普通的函數(shù),也被定義到了組件的props里面了
            onChange: ((value: string,event: React.ChangeEvent<HTMLInputElement>) => void) | undefined;
            }

            export default function(props: CustomInputProps) {

            function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
            // props.onChange是一個屬性,也是自定義的一個事件
            props.onChange && props.onChange(e.target.value, e)
            }

            return (
            <input value={props.value} onChange={handleChange}></input>
            )
            }

            使用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 (
            <div>
            <CustomInput value={value} onChange={handleChange}></CustomInput>
            </div>
            )
            }

            總結(jié)

            剛開始從Vue轉(zhuǎn)到React的時候,其實是有點不適應(yīng)的,但是當慢慢的習(xí)慣之后,就會發(fā)現(xiàn)VueReact是存在很多共性的,可以參考的去學(xué)習(xí)。當然無論Vue還是React,上手比較快,但是想深入學(xué)習(xí)還是需要下功夫的,后續(xù)小編將會對VueReact的用法在做更深入的介紹,敬請期待。

          瀏覽 41
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产成人在线免费观看 | 日日日日人人人夜夜2022 | 高跟鞋少妇一级A片 | 无吗a在线播放 | 中文字幕22页 |