предисловие
в этот
卷神
Эпоха, которая вышла массово, просто искуснаVue
Толстоголовую рыбу много раз били.Во время интервью его спросили: «Вы не знаете, как реагировать?» Я потерял дар речи и не знал, что сказать.
В этой статье делается попытка
Vue
Некоторые общие черты вReact
реализовать его снова, если вы оказалисьVue
ПеременаReact
,илиReact
ПеременаVue
, с нетерпением жду помощи для вас.
Если вы знакомы
React
а такжеVue
Одноклассники становятся на колени и просят лёгкого спрея (ручное выживание)
每个功能,都有对应的Vue和React版本实现,也有对应的截图或者录屏
1. v-if
Давайте начнем с наиболее распространенного отображения и скрытия.Отображение и скрытие элемента в Vue обычно обрабатывается с помощью
v-if
илиv-show
инструкции, ноv-if
Является «истинным» условным рендерингом, прослушиватели событий и подкомпоненты внутри условного блока соответствующим образом уничтожаются и перестраиваются во время перехода. а такжеv-show
Это просто, просто управление стилем css.
v-if исходный код нажмите здесь
Vue
<template>
<div class="v-if">
<button @click="onToggleShow">切换</button>
<div v-if="isShow">前端胖头鱼 显示出来啦</div>
</div>
</template>
<script>
export default {
name: 'vif',
data () {
return {
isShow: true
}
},
methods: {
onToggleShow () {
this.isShow = !this.isShow
}
}
}
</script>
React
исходный код vif нажмите здесь
import React, { useState } from "react"
export default function Vif (){
const [ isShow, setIsShow ] = useState(true)
const onToggleShow = () => {
setIsShow(!isShow)
}
return (
<div className="v-if">
<button onClick={ onToggleShow }>切换</button>
{/* 也可以用三目运算符 */}
{/* { isShow ? <div>前端胖头鱼 显示出来啦</div> : null } */}
{
isShow && <div>前端胖头鱼 显示出来啦</div>
}
</div>
)
}
предварительный просмотр
2. v-show
Так же, на этот раз мы проходим
v-show
Для достижения функции отображения и скрытия при наблюдении за изменениями стиля DOM.
Уведомление:Почему здесь не отображается?block
Это связано с тем, что некоторые элементы сами по себе не являются элементами блочного уровня, если их принудительно установить вblock
Можно вызвать неправильный стиль.
Vue
Исходный код V-шоу Нажмите здесь
<template>
<div class="v-show">
<button @click="onToggleShow">切换</button>
<div v-show="isShow">前端胖头鱼 显示出来啦</div>
</div>
</template>
<script>
export default {
name: 'vshow',
data () {
return {
isShow: true
}
},
methods: {
onToggleShow () {
this.isShow = !this.isShow
}
}
}
</script>
React
исходный код vShow нажмите здесь
import React, { useState } from "react"
export default function VShow (){
const [ isShow, setIsShow ] = useState(true)
const onToggleShow = () => {
setIsShow(!isShow)
}
return (
<div className="v-show">
<button onClick={ onToggleShow }>切换</button>
{
<div style={{ display: isShow ? '' : 'none' }}>前端胖头鱼 显示出来啦</div>
}
</div>
)
}
предварительный просмотр
3. v-for
В общем, рендеринг списка в
Vue
используется вv-for
директива, необходимо использовать директиву v-foritem in items
специальный синтаксис формы, гдеitems
массив исходных данных, аitem
является псевдонимом элемента массива, по которому выполняется итерация. Конечно, каждому элементу нужно задать уникальныйkey
Vue
v-для исходного кода нажмите здесь
<template>
<div class="v-for">
<div
class="v-for-item"
v-for="item in list"
:key="item.id"
>
{{ item.name }}
</div>
</div>
</template>
<script>
export default {
name: 'vfor',
data () {
return {
list: [
{
id: 1,
name: '前端',
},
{
id: 2,
name: '后端',
},
{
id: 3,
name: 'android',
},
{
id: 4,
name: 'ios',
},
]
}
}
}
</script>
React
существует
React
нетv-for
инструкция, мы можем использоватьmap
Метод обхода выполняет аналогичные функции
vДля получения исходного кода нажмите здесь
import React, { useState } from "react"
export default function VFor (){
const [ list, setList ] = useState([
{
id: 1,
name: '前端',
},
{
id: 2,
name: '后端',
},
{
id: 3,
name: 'android',
},
{
id: 4,
name: 'ios',
},
])
return (
<div className="v-for">
{
list.map((item) => {
return <div className="v-for-item" key={ item.id }>{ item.name }</div>
})
}
</div>
)
}
предварительный просмотр
4. computed
Вычисляемые свойства удобны, когда переменная должна быть оценена в зависимости от других переменных, и
Vue
Вычисляемые свойства кэшируются на основе их зависимых зависимостей, а значение зависимости не изменилось и не будет пересчитываться для достижения эффекта кэширования.
Давайте рассмотрим простой пример сложения:num3
Зависит отnum1
а такжеnum2
Добавьте результат, пока кнопка нажата один разnum1
добавить 10,num3
будет продолжать добавлять 10
Vue
вычисленный исходный код нажмите здесь
<template>
<div class="computed">
<button @click="onAdd">+10</button>
<div>计算结果:{{ num3 }}</div>
</div>
</template>
<script>
export default {
name: 'computed',
data () {
return {
num1: 10,
num2: 10,
}
},
computed: {
num3 () {
return this.num1 + this.num2
}
},
methods: {
onAdd () {
this.num1 += 10
}
}
}
</script>
React
React
Здесь нет вычисляемых свойств, но мы можем передатьuseMemo
этот хук для реализации, иVue
Разница в том, что мы должны вычислитьРучное обслуживание зависимостей
вычисленный исходный код нажмите здесь
import React, { useMemo, useState } from "react"
export default function Computed (){
const [ num1, setNum1 ] = useState(10)
const [ num2, setNum2 ] = useState(10)
const num3 = useMemo((a, b) => {
return num1 + num2
}, [ num1, num2 ])
const onAdd = () => {
setNum1(num1 + 10)
}
return (
<div className="computed">
<button onClick={ onAdd }>+10</button>
<div>计算结果:{ num3 }</div>
</div>
)
}
предварительный просмотр
5. watch
Иногда нам нужно отслеживать изменения данных, а затем выполнять асинхронное поведение или дорогостоящие операции, которые можно использовать в Vue.
watch
реализовать
Давайте смоделируем такой сценарий и передадимwatch
Для достижения: выберитеboy
илиgirl
, выбрав его, отправьте запрос и отобразите результат запроса. (Здесь процесс асинхронного запроса моделируется через setTimeout)
Vue
посмотреть исходный код нажмите здесь
<template>
<div class="watch">
<div class="selects">
<button
v-for="(item, i) in selects"
:key="i"
@click="onSelect(item)"
>
{{ item }}
</button>
</div>
<div class="result">
{{ result }}
</div>
</div>
</template>
<script>
export default {
name: 'watch',
data () {
return {
fetching: false,
selects: [
'boy',
'girl'
],
selectValue: ''
}
},
computed: {
result () {
return this.fetching ? '请求中' : `请求结果: 选中${this.selectValue || '~'}`
}
},
watch: {
selectValue () {
this.fetch()
}
},
methods: {
onSelect (value) {
this.selectValue = value
},
fetch () {
if (!this.fetching) {
this.fetching = true
setTimeout(() => {
this.fetching = false
}, 1000)
}
}
}
}
</script>
React
React
Чтобы реализовать действие по мониторингу некоторых изменений данных и выполнению ответа, вы можете использоватьuseEffect
посмотреть исходный код нажмите здесь
import React, { useState, useMemo, useEffect } from "react"
import './watch.css'
export default function Watch() {
const [fetching, setFetching] = useState(false)
const [selects, setSelects] = useState([
'boy',
'girl'
])
const [selectValue, setSelectValue] = useState('')
const result = useMemo(() => {
return fetching ? '请求中' : `请求结果: 选中${selectValue || '~'}`
}, [ fetching ])
const onSelect = (value) => {
setSelectValue(value)
}
const fetch = () => {
if (!fetching) {
setFetching(true)
setTimeout(() => {
setFetching(false)
}, 1000)
}
}
useEffect(() => {
fetch()
}, [ selectValue ])
return (
<div className="watch">
<div className="selects">
{
selects.map((item, i) => {
return <button key={ i } onClick={ () => onSelect(item) }>{ item }</button>
})
}
</div>
<div className="result">
{ result }
</div>
</div>
)
}
предварительный просмотр
6. style
Иногда динамическое добавление стилей к элементам неизбежно.
style
,Vue
а такжеReact
Все они предоставляют нам удобный способ использования.
В основном то же самое в использовании:
Тот же пункт:
Имена свойств CSS могут быть названы в CamelCase или разделены тире (кебаб-регистр, не забудьте заключить их в кавычки)
разница:
- Vue может связывать несколько объектов стиля с помощью синтаксиса массива, React в основном имеет форму одного объекта (это также может быть сделано Vue)
- React автоматически добавит «px» (Vue не обрабатывает это автоматически) добавляется к свойству, встроенный стиль которого является числом, другие единицы измерения необходимо указывать вручную.
- Стили React не автозаполняют префиксы. Для поддержки старых браузеров необходимо вручную добавить соответствующие атрибуты стиля. В Vue, когда v-bind:style использует свойство CSS, для которого требуется префикс движка браузера, например, преобразование, Vue.js автоматически обнаружит и добавит соответствующий префикс.
Vue
исходный код стиля нажмите здесь
<template>
<div class="style" :style="[ style, style2 ]"></div>
</template>
<script>
export default {
name: 'style',
data () {
return {
style: {
width: '100%',
height: '500px',
},
style2: {
backgroundImage: 'linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%)',
borderRadius: '10px',
}
}
}
}
</script>
React
исходный код стиля нажмите здесь
import React from "react"
export default function Style (){
const style = {
width: '100%',
height: '500px',
}
const style2 = {
backgroundImage: 'linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%)',
borderRadius: '10px',
}
return (
<div className="style" style={ { ...style, ...style2 } } ></div>
)
}
предварительный просмотр
7. class
Как динамически добавлять классы к элементам? Во Vue я предпочитаю использовать синтаксис массивов (и, конечно, способ записи объектов), а в React можно использовать и некоторые сторонние пакеты, напримерclassnamesЭто упрощает добавление классов.
Давайте посмотрим, как добиться эффекта выбора кнопки без использования какой-либо библиотеки.
Vue
исходный код класса нажмите здесь
<template>
<button :class="buttonClasses" @click="onClickActive">{{ buttonText }}</button>
</template>
<script>
export default {
name: 'class',
data () {
return {
isActive: false,
}
},
computed: {
buttonText () {
return this.isActive ? '已选中' : '未选中'
},
buttonClasses () {
// 通过数组形式维护class动态列表
return [ 'button', this.isActive ? 'active' : '' ]
}
},
methods: {
onClickActive () {
this.isActive = !this.isActive
}
}
}
</script>
<style scoped>
.button{
display: block;
width: 100px;
height: 30px;
line-height: 30px;
border-radius: 6px;
margin: 0 auto;
padding: 0;
border: none;
text-align: center;
background-color: #efefef;
}
.active{
background-image: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);
color: #fff
}
</style>
React
исходный код класса нажмите здесь
import React, { useMemo, useState } from "react"
import './class.css' // 此处样式与上面是一样的
export default function Class (){
const [ isActive, setIsActive ] = useState(false)
const buttonText = useMemo(() => {
return isActive ? '已选中' : '未选中'
}, [ isActive ])
const buttonClass = useMemo(() => {
// 和Vue中不太一样的是我们需要手动join一下,变成'button active'形式
return [ 'button', isActive ? 'active' : '' ].join(' ')
}, [ isActive ])
const onClickActive = () => {
setIsActive(!isActive)
}
return (
<div className={ buttonClass } onClick={onClickActive}>{ buttonText }</div>
)
}
предварительный просмотр
8.provide/inject
И у Vue, и у React есть свои хорошие решения для управления глобальным состоянием, например, в Vue.
Vuex
, в реакцииredux
а такжеMobx
, конечно внедряя их в небольшие проектыИзлишествоТеперь есть ли другое решение?
Доступно в Vueprovide/inject
В React вы можете использоватьContext
假设全局有有一个用户信息userInfo的变量,需要在各个组件中都能便捷的访问到,在Vue和React中该如何实现呢?
Vue
Vue
заимствовано изprovide/inject
Состояние верхнего уровня может быть передано любому дочернему узлу, если мы объявим новый в app.vue.userInfo
данные
предоставить исходный код нажмите здесь
app.vue
<template>
<div id="app">
<div class="title">我是Vue栗子</div>
<router-view/>
</div>
</template>
<script>
export default {
name: 'app',
// 声明数据
provide () {
return {
userInfo: {
name: '前端胖头鱼'
}
}
}
}
</script>
provide.vue
<template>
<div class="provide-inject">{{ userInfo.name }}</div>
</template>
<script>
export default {
name: 'provideInject',
// 使用数据
inject: [ 'userInfo' ]
}
</script>
React
React
Для достижения аналогичной функции вContext, поделиться глобальным состоянием с любым дочерним узлом
предоставить исходный код нажмите здесь
context/index.js
import { createContext } from "react";
export const UserInfoContext = createContext({
userInfo: {
name: ''
}
})
app.js
import { UserInfoContext } from './context/index'
function App() {
return (
<BrowserRouter>
// 注意这里
<UserInfoContext.Provider
value={{ userInfo: { name: '前端胖头鱼' } }}
>
<div className="title">我是React栗子</div>
<Routes>
<Route path="/v-if" element={<Vif />} />
<Route path="/v-show" element={<VShow />} />
<Route path="/v-for" element={<VFor />} />
<Route path="/computed" element={<Computed />} />
<Route path="/watch" element={<Watch />} />
<Route path="/style" element={<Style />} />
<Route path="/class" element={<Class />} />
<Route path="/slot" element={<Slot />} />
<Route path="/nameSlot" element={<NameSlot />} />
<Route path="/scopeSlot" element={<ScopeSlot />} />
<Route path="/provide" element={<Provide />} />
</Routes>
</UserInfoContext.Provider>
</BrowserRouter>
);
}
provide.js
import React, { useContext } from "react"
import { UserInfoContext } from '../context/index'
export default function Provide() {
// 通过userContext,使用定义好的UserInfoContext
const { userInfo } = useContext(UserInfoContext)
return (
<div class="provide-inject">{ userInfo.name }</div>
)
}
предварительный просмотр
9. слот (слот по умолчанию)
слот
Vue
Это очень практичная функция в默认坑位
,具名坑位
,作用域坑位
, давайте рассмотрим практический примерReact
как добиться той же функциональности.
Предположим, мы хотим реализовать простуюdialog
Компонент, основная функция заключается в том, что заголовок может передавать строку, а контентная часть может быть полностью настроена, как это должно быть реализовано?
Vue
исходный код слота нажмите здесь
dialog
<template>
<div class="dialog" v-show="visible">
<div class="dialog-mask" @click="onHide"></div>
<div class="dialog-body">
<div class="dialog-title" v-if="title">{{ title }}</div>
<div class="dialog-main">
// 注意这里放了一个默认插槽坑位
<slot></slot>
</div>
<div class="dialog-footer">
<div class="button-cancel" @click="onHide">取消</div>
<div class="button-confirm" @click="onHide">确定</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "dialog",
props: {
title: {
type: String,
default: "",
},
visible: {
type: Boolean,
default: false,
},
},
methods: {
onHide () {
this.$emit('update:visible', false)
}
}
};
</script>
slot
<template>
<div class="slot">
<button @click="onToggleVisible">切换dialog</button>
<Dialog
:visible.sync="visible"
title="默认插槽"
>
// 这里会替换到<slot></slot>的位置处
<div class="slot-body">前端胖头鱼</div>
</Dialog>
</div>
</template>
<script>
import Dialog from './components/dialog.vue'
export default {
name: 'slot',
components: {
Dialog,
},
data () {
return {
visible: false
}
},
methods: {
onToggleVisible () {
this.visible = !this.visible
}
}
}
React
Что я должен сделать, чтобы добиться той же функции в React?
React
Но слота нет! не волнуйся, хотяReact
Нет понятия слотов вprops.children
Получить дочерние элементы внутри компонента, через которые можно реализовать функцию слота по умолчанию
исходный код слота нажмите здесь
Dialog
import React, { useState, useEffect } from "react"
import './dialog.css'
export default function Dialog(props) {
// 原谅我用visible -1这种傻叉的方式先实现了, 重点不是在这里
const { children, title = '', visible = -1 } = props
const [visibleInner, setVisibleInner] = useState(false)
const onHide = () => {
setVisibleInner(false)
}
useEffect(() => {
setVisibleInner(visible > 0)
}, [ visible ])
return (
<div className="dialog" style={ { display: visibleInner ? 'block' : 'none' }}>
<div className="dialog-mask" onClick={ onHide }></div>
<div className="dialog-body">
{ title ? <div className="dialog-title">{ title }</div> : null }
<div className="dialog-main">
{/* 注意这里,通过children实现默认插槽功能 */}
{children}
</div>
<div className="dialog-footer">
<div className="button-cancel" onClick={ onHide }>取消</div>
<div className="button-confirm" onClick={ onHide }>确定</div>
</div >
</div >
</div >
)
}
slot
import React, { useState, useEffect } from "react"
import Dialog from './components/dialog'
export default function Slot() {
const [visible, setVisible] = useState(-1)
const onToggleVisible = () => {
setVisible(Math.random())
}
return (
<div className="slot">
<button onClick={ onToggleVisible }>切换dialog</button>
<Dialog
visible={visible}
title="默认插槽"
>
{/* 注意这里,会被Dialog组件的children读取并且替换掉 */}
<div className="slot-body">前端胖头鱼</div>
</Dialog>
</div>
)
}
предварительный просмотр
10. слот имени
Когда внутри компонента есть несколько динамических элементов, которые необходимо заполнить извне, слота по умолчанию недостаточно, нам нужно предоставить слотвзять имя, так что снаружи можно "шаг за шагом" в назначенное место.
Давайте обогатимсяDialog
компоненты, предполагаяtitle
Может ли он также поддерживать динамическую доставку контента?
Vue
Через во Vue
<slot name="main"></slot>
Форма сначала объявляет слот, а затем проходитv-slot:main
В виде употребления будет засыпана одна редька и одна косточка.
исходный код nameSlot нажмите здесь
Преобразование диалога
<template>
<div class="dialog" v-show="visible">
<div class="dialog-mask" @click="onHide"></div>
<div class="dialog-body">
<div class="dialog-title" v-if="title">{{ title }}</div>
<!-- 注意这里,没有传title属性,时候通过插槽进行内容承接 -->
<slot name="title" v-else></slot>
<div class="dialog-main">
<!-- 声明main部分 -->
<slot name="main"></slot>
</div>
<div class="dialog-footer">
<div class="button-cancel" @click="onHide">取消</div>
<div class="button-confirm" @click="onHide">确定</div>
</div>
</div>
</div>
</template>
// ... 其他地方和上面试一样的
nameSlot
<template>
<div class="slot">
<button @click="onToggleVisible">切换dialog</button>
<Dialog
:visible.sync="visible"
>
<template v-slot:title>
<div class="dialog-title">具名插槽</div>
</template>
<template v-slot:main>
<div class="slot-body">前端胖头鱼</div>
</template>
</Dialog>
</div>
</template>
<script>
import Dialog from './components/dialog.vue'
export default {
name: 'nameSlot',
components: {
Dialog,
},
data () {
return {
visible: false
}
},
methods: {
onToggleVisible () {
this.visible = !this.visible
}
}
}
</script>
React
проходить впереди
props.children
Атрибуты могут считывать содержимое тега компонента иVue
Слоты по умолчанию делают то же самое, но как это делают именованные слоты?React
Одна из забавных вещей, я думаю, что вы можете передавать атрибуты и что угодно,字符串
,数字
,函数
,连DOM
также может передаваться. Следовательно, также очень просто реализовать именованный слот, и его можно передать напрямую как свойство.
исходный код nameSlot нажмите здесь
Преобразование диалога
import React, { useState, useEffect } from "react"
import './dialog.css'
export default function Dialog(props) {
// 原谅我用visible -1这种傻叉的方式先实现了, 重点不是在这里
const { title, main, visible = -1 } = props
const [visibleInner, setVisibleInner] = useState(false)
const onHide = () => {
setVisibleInner(false)
}
useEffect(() => {
setVisibleInner(visible > 0)
}, [ visible ])
return (
<div className="dialog" style={ { display: visibleInner ? 'block' : 'none' }}>
<div className="dialog-mask" onClick={ onHide }></div>
<div className="dialog-body">
{/* { title ? <div className="dialog-title">{ title }</div> : null } */}
{/* 注意这里,直接渲染title就可以了 */}
{ title }
<div className="dialog-main">
{/* 注意这里,通过children实现默认插槽功能 */}
{/* {children} */}
{/* 这一这里不是children了,是main */}
{ main }
</div>
<div className="dialog-footer">
<div className="button-cancel" onClick={ onHide }>取消</div>
<div className="button-confirm" onClick={ onHide }>确定</div>
</div >
</div >
</div >
)
}
nameSlot
import React, { useState } from "react"
import Dialog from './components/dialog'
import './slot.css'
export default function NameSlot() {
const [visible, setVisible] = useState(-1)
const onToggleVisible = () => {
setVisible(Math.random())
}
return (
<div className="slot">
<button onClick={ onToggleVisible }>切换dialog</button>
<Dialog
visible={visible}
// 注意这里,直接传递的DOM
title={ <div className="dialog-title">默认插槽</div> }
// 注意这里,直接传递的DOM
main={ <div className="slot-body">前端胖头鱼</div> }
>
</Dialog>
</div>
)
}
предварительный просмотр
Именованные слоты можно увидеть,
React
Более лаконично использовать атрибуты напрямую
11. слот для прицела
имеют
默认插槽
,具名插槽
Наконец, конечно же, слот для прицела незаменим! Иногда бывает полезно, чтобы содержимое слота имело доступ к данным, которые существуют только в дочерних компонентах, в чем суть слотов с ограниченной областью действия.
Предполагать:Dialog
Внутри компонента естьuserInfo: { name: '前端胖头鱼' }
объект данных, хотите использоватьDialog
Доступ к внешнему слоту компонента тоже есть, что делать?
Vue
Исходный код scopeSlot нажмите здесь
Dialog
<template>
<div class="dialog" v-show="visible">
<div class="dialog-mask" @click="onHide"></div>
<div class="dialog-body">
<div class="dialog-title" v-if="title">{{ title }}</div>
<!-- 注意这里,通过绑定userInfo外部可以进行使用 -->
<slot name="title" :userInfo="userInfo" v-else></slot>
<div class="dialog-main">
<!-- 注意这里,通过绑定userInfo外部可以进行使用 -->
<slot name="main" :userInfo="userInfo"></slot>
</div>
<div class="dialog-footer">
<div class="button-cancel" @click="onHide">取消</div>
<div class="button-confirm" @click="onHide">确定</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "dialog",
// ...
data () {
return {
userInfo: {
name: '前端胖头鱼'
}
}
},
// ...
};
</script>
scopeSlot
<template>
<div class="slot">
<button @click="onToggleVisible">切换dialog</button>
<Dialog
:visible.sync="visible"
>
<template v-slot:title>
<div class="dialog-title">作用域插槽</div>
</template>
<!-- 注意这里 -->
<template v-slot:main="{ userInfo }">
<!-- 注意这里userInfo是Dialog组件内部的数据 -->
<div class="slot-body">你好{{ userInfo.name }}</div>
</template>
</Dialog>
</div>
</template>
React
В том же предложении можно передать все в React.Подобно реализации именованных слотов, мы передаем DOM напрямую.Точно так же мы можем передавать функции для передачи
Dialog
внутри компонентаuserInfo
Данные передаются во внешнее использование параметрами функции
Исходный код scopeSlot нажмите здесь
Преобразование диалога
import React, { useState, useEffect } from "react"
import './dialog.css'
export default function Dialog(props) {
// 原谅我用visible -1这种傻叉的方式先实现了, 重点不是在这里
const { title, main, visible = -1 } = props
const [visibleInner, setVisibleInner] = useState(false)
const [ userInfo ] = useState({
name: '前端胖头鱼'
})
const onHide = () => {
setVisibleInner(false)
}
useEffect(() => {
setVisibleInner(visible > 0)
}, [ visible ])
return (
<div className="dialog" style={ { display: visibleInner ? 'block' : 'none' }}>
<div className="dialog-mask" onClick={ onHide }></div>
<div className="dialog-body">
{/* 作用域插槽,当函数使用,并且把数据传递进去 */}
{ title(userInfo) }
<div className="dialog-main">
{/* 作用域插槽,当函数使用,并且把数据传递进去 */}
{ main(userInfo) }
</div>
<div className="dialog-footer">
<div className="button-cancel" onClick={ onHide }>取消</div>
<div className="button-confirm" onClick={ onHide }>确定</div>
</div >
</div >
</div >
)
}
scopeSlot
import React, { useState } from "react"
import Dialog from './components/dialog'
import './slot.css'
export default function ScopeSlot() {
const [visible, setVisible] = useState(-1)
const onToggleVisible = () => {
setVisible(Math.random())
}
return (
<div className="slot">
<button onClick={ onToggleVisible }>切换dialog</button>
<Dialog
visible={visible}
// 通过函数来实现插槽
title={ () => <div className="dialog-title">作用域插槽</div> }
// 接收userInfo数据
main={ (userInfo) => <div className="slot-body">你好{ userInfo.name }</div> }
>
</Dialog>
</div>
)
}