您好,登錄后才能下訂單哦!
今天小編給大家分享一下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),下面我們就分別使用Vue
和React
來實現(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)是為`添加
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
連插槽都沒有, 更別提具名插槽了,但是沒有不代表不能模擬出來。對于React
的props
,我們不僅僅可以傳入普通的屬性,還可以傳入一個函數(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)在我們分別使用Vue
和React
來實現(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.Provider
將theme
共享出去
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
,但也不影響使用我們知道React
和Vue
都是單向數(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
中我們一般繪制頁面都會使用到template
,template
里面提供了大量的指令幫助我們完成業(yè)務(wù)開發(fā),但是在React
中使用的是JSX
,并沒有指令,那么我們應該怎么做呢?下面我們就將Vue
中最常用的一些指令轉(zhuǎn)換為JSX
里面的語法(注意: 在Vue中也可以使用JSX
)
v-show
與v-if
在Vue
中我們隱藏顯示元素可以使用v-show
或者v-if
,當然這兩者的使用場景是有所不同的,v-show
是通過設(shè)置元素的display
樣式來顯示隱藏元素的,而v-if
隱藏元素是直接將元素從dom
中移除掉。
看一下Vue
中的v-show
與v-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-for
在Vue
中是用來遍歷數(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-bind
與v-on
v-bind
在Vue
中是動態(tài)綁定屬性的,v-on
是用于監(jiān)聽事件的,因為React
也有屬性和事件的概念,所以我們在React
也能發(fā)現(xiàn)可替代的方式。
在Vue
中使用v-bind
與v-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è)資訊頻道。
免責聲明:本站發(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)容。