关于前端:建议收藏11实战技巧让你轻松从Vue过渡到React

56次阅读

共计 15707 个字符,预计需要花费 40 分钟才能阅读完成。

前言

在这个 卷神 辈出的时代,只是纯熟 Vue 的胖头鱼,曾经被毒打过屡次了,面试中曾被质疑:“你竟然不会 React?”我无语凝噎,不知说啥是好。

新公司 VueReact我的项目都有不少,做了几个后,发现两者之间还是有很多共通之处,重点是先了解思维,而后把握对应的写法,上手起来也就快了很多。

这篇文章尝试将 Vue 中一些常见的性能在 React 中实现一遍,如果你恰巧是 VueReact,或者 ReactVue,期待对你有些帮忙。

如果你是一名相熟 ReactVue的同学跪求轻喷(手动求生)

每个性能,都有对应的 Vue 和 React 版本实现,也有对应的截图或者录屏

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-show 源代码点击这里

<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-for 指令须要应用 item in items 模式的非凡语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。当然了,每个元素都须要设置惟一的key

Vue

v-for 源代码点这里

<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 遍历的形式实现相似性能

vFor 源代码点这里

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 的计算属性是基于它们的响应式依赖进行缓存的,依赖值未发生变化,不会从新计算,达到缓存的作用。

咱们来看一个简略的加法例子:num3num1num2相加所得,同时按钮每点一次 num1 加 10,num3也会跟着一直加 10

Vue

computed 源代码点这里

<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 这个 hook 来实现,和 Vue computed 不太一样的中央在于,咱们必须 手动保护依赖

computed 源代码点这里

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

watch 源代码点这里

<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

watch 源代码点这里

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

有时候不免要给元素动静增加款式 styleVueReact都给咱们提供了不便的应用形式。

在应用上根本大同小异:

相同点:

CSS property 名能够用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名

不同点:

  1. Vue 能够通过数组语法绑定多个款式对象,React 次要是单个对象的模式(这点 Vue 也能够)
  2. React 会主动增加”px”(这点 Vue 不会主动解决) 后缀到内联款式为数字的属性,其余单位手动须要手动指定
  3. React 款式不会主动补齐前缀。如需反对旧版浏览器,需手动补充对应的款式属性。Vue 中当 v-bind:style 应用须要增加浏览器引擎前缀的 CSS property 时,如 transform,Vue.js 会主动侦测并增加相应的前缀。

Vue

style 源代码点这里

<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

style 源代码点这里

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

如何动静地给元素增加 class?Vue 中我本人比拟喜爱用数组的语法(当然还有对象的写法),React 中也能够应用一些第三方包如 classnames 起到更加便捷增加 class 的成果。

上面咱们看下不借助任何库,如何实现按钮选中的成果

Vue

class 源代码点这里

<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

class 源代码点这里

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,React 中的reduxMobx,当然小型我的项目中引入这些有点 大材小用 了, 有没有其余解决方案呢?

Vue 中能够应用 provide/inject

React 中则能够应用 Context

假如全局有有一个用户信息 userInfo 的变量,须要在各个组件中都能便捷的拜访到,在 Vue 和 React 中该如何实现呢?

Vue

Vue中借用 provide/inject 能够将顶层状态,传递至任意子节点,假如咱们再 app.vue 中申明了一个 userInfo 数据

provide 源代码点这里

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,将全局状态共享给任意子节点

provide 源代码点这里

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. slot(默认插槽)

插槽是 Vue 中十分实用的性能,我把他了解成”坑位“,期待着你从里面把他填上,而这个”坑位“能够分成 默认坑位 具名坑位 作用域坑位 ,咱们通过一个实战例子来看看React 中如何实现等同的性能。

假如咱们要实现一个简略的 dialog 组件, 基本功能是题目能够传字符串,内容局部能够齐全自定义,应该怎么实现呢?

Vue

slot 源代码点这里

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>

默认插槽组件

dialog

<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 获取到组件外部的子元素,通过这个就能够实现默认插槽的性能

slot 源代码点这里

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 >
  )
}

默认插槽组件

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. name slot(具名插槽)

当组件外部有多个动静内容须要内部来填充的时候,一个默认插槽曾经不够用了,咱们须要给插槽取个名字,这样内部才能够”循序渐进“到指定地位。

咱们来丰盛一下 Dialog 组件,假如 title 也能够反对动静传递内容呢?

Vue

Vue 中通过 <slot name="main"></slot> 模式先进行插槽的申明,再通过 v-slot:main 模式进行应用,一个萝卜一个坑也就填起来了

nameSlot 源代码点这里

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>
      <!-- 留神这里,没有传 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

React

后面通过 props.children 属性能够读取组件标签内的内容算是和 Vue 默认插槽实现了一样的性能,然而具名插槽如何实现呢?React好玩的其中一个点,我感觉是属性啥玩意都能够传、字符串 数字 函数 连 DOM也能够传。所以实现具名插槽也很简略,间接当属性传递就能够

nameSlot 源代码点这里

Dialog 革新

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. scope slot(作用域插槽)

有了 默认插槽 具名插槽 最初当然少不了作用域插槽啦!有时让插槽内容可能拜访子组件中才有的数据是很有用的,这也是作用域插槽的意义所在

假如: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 源代码点这里
Dialog 革新

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>
  )
}

预览

正文完
 0