溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Vue和React的插槽怎么使用

發(fā)布時間:2022-02-24 15:56:27 來源:億速云 閱讀:209 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下Vue和React的插槽怎么使用的相關(guān)知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

插槽,在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)

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

   
     <div class="card">
       <div class="card__title">
         <span>{{ title }}</span>
       </div>
       <div class="card__body">

         
       </div>
     </div>

   

   
   export default {
     props: {
       title: {
         type: String,
         default: ''
       }
     }
   }

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

在外部使用定義的card組件

   
     <div>

       
         <div>我將被放在card組件的默認插槽里面</div>

       
     </div>

   

   
   import MyCard from '../components/card'
   export default {
     components: {
       MyCard
     }
   }

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

React實現(xiàn)

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

使用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>

         
           <div>我將被放在card組件的body區(qū)域內(nèi)容</div>

         
       </div>
     );
   }

在外部使用Card組件

具名插槽

繼續(xù)以上面的Card組件為例,假如我們現(xiàn)在需求發(fā)生了變化,組件的title也可以使用插槽,這時候?qū)τ?code>Vue就可以使用具名插槽了,而React也是有辦法實現(xiàn)的哦。

Vue實現(xiàn)

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

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

  <div class="card">
    <div class="card__title">

      
      <span v-if="title">{{ title }}</span>

      
    </div>
    <div class="card__body">

      

      
    </div>
  </div>




export default {
  props: {
    title: {
      type: String,
      default: ''
    }
  }
}

card組件修改完之后,我們再去調(diào)整一下使用card組件的地方

  <div>

    

      

      
        <span>這里是標題</span>

      
      <div>我將被放在card組件的默認插槽里面</div>

    
  </div>




import MyCard from '../components/card'
export default {
  components: {
    MyCard
  }
}
React實現(xiàn)

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

對原有的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>
  );
}

這時候就可以在外部自定義title

import React from 'react'
import Card from './components/Card'


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

      
    </div>
  );
}
作用域插槽

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

Vue實現(xiàn)

實現(xiàn)用戶信息卡片組件,里面使用了作用域插槽

  
    <div class="content">

      

      

        
        <span>姓名: {{ userInfo.name }}</span>
        <span>性別: {{ userInfo.sex }}</span>
        <span>年齡: {{ userInfo.age }}</span>

      
    </div>

  




import CustomCard from '../card'
export default {
  components: {
    CustomCard
  },
  data() {
    return {
      userInfo: {
        name: '張三',
        sex: '男',
        age: 25
      }
    }
  }
}

在外部使用人員信息組件

  <div>

    

      
        <div class="custom-user">
          <ul>
            <li>姓名: {{ userInfo.name }}</li>
            <li>年齡: {{ userInfo.age }}</li>
          </ul>
        </div>

      

    
  </div>




import UserCard from '../components/user-card'
export default {
  components: {
    UserCard
  }
}
React實現(xiàn)

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

實現(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({
       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 
       {content}

     
   }

在外部使用人員信息卡片組件

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

   
   export default function () {

   
     return (
       <div>
          {
             return (
               <ul>
                 <li>姓名: {userInfo.name}</li>
               </ul>
             );
           }}
         >
       </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)容

  <div id="app">

    
  </div>






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

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

  <div :class="`child-${theme.theme}`">
  </div>




export default {
  inject: ['theme']
}

這樣就可以實現(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共享到所有的子組件?,F(xiàn)在我們在所有的組件的共同父組件比如App.js上面添加MyContext.Providertheme共享出去

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


export default function() {

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

  
  return (

    

        

     
    )
  }

然后這時候就可以直接在所有的子組件里面使用定義的主題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ù)綁定的能力,比如下面的代碼

   <input v-model="name"/>




  export default {
    data() {
      return {
        name:'子君'
      }
    }
  }

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

  <div class="custom-input">
     <input :value="value" @input="$_handleChange"/>
  </div>




  export default {
    props:{
      value:{
        type: String,
        default: ''
      }
    },
    methods:{
      $_handleChange(e) {
        this.$emit('input', e.target.value)
      }
    }
  }
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,并沒有指令,那么我們應該怎么做呢?下面我們就將Vue中最常用的一些指令轉(zhuǎn)換為JSX里面的語法(注意: 在Vue中也可以使用JSX)

v-showv-if

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

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

   
     <div>
       <span v-show="showName">姓名:{{ name }}</span>
       <span v-if="showDept">{{ dept }}</span>
     </div>

   

   
   export default {
     data() {
       return {
         name: '子君',
         dept: '銀河帝國',
         showName: false,
         showDept: true
       }
     }
   }

v-show,v-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的時候需要給元素指定key,key的值一般是數(shù)據(jù)的id或者其他唯一且固定的值。不僅在Vue中,在React中也是存在key的,兩者的key存在的意義基本一致,都是為了優(yōu)化虛擬DOM diff算法而存在的。

Vue中使用v-for

   
     <div>
       <ul>
         <li v-for="item in list" :key="item.id">
           {{ item.name }}
         </li>
       </ul>
     </div>

   

   
   export default {
     data() {
       return {
         list: [
           {
             id: 1,
             name: '子君'
           },
           {
             id: '2',
             name: '張三'
           },
           {
             id: '3',
             name: '李四'
           }
         ]
       }
     }
   }

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)可替代的方式。

Vue中使用v-bindv-on

   
     <div>

       
       <input :value="value" @input="handleInput" />
     </div>

   

   
   export default {
     data() {
       return {
         value: '子君'
       }
     },
     methods: {
       handleInput(e) {
         this.value = e.target.value
       }
     }
   }

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) => void) | undefined;
   }

   
   export default function(props: CustomInputProps) {

     
     function handleChange(e: React.ChangeEvent) {
       // 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>

         
       </div>
     )
   }

以上就是“Vue和React的插槽怎么使用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI