1. 先用vue3写一个vue2常见的Dialog组件的伪代码:
<template>
  <Dialog :state="state">
    <div>我是弹窗内容</div>
    <button @click="submit">提交</button>
  </Dialog>
</template>
<script setup>
import Dialog from '@/component/Dialog'
import { ref } from 'vue'
const state = ref(false)
function open(id) {
  state.value = true
  if(id) {
    // ...
  }
}
  const emit = defineEmits(['update'])
function submit() {
  state.value = false
  emit('update')
}
defineExpose({
  open
})
</script>
  1. 父组件在运用的时分:
<template>
  <button @click="openDialog">打开弹窗</button>
  <MyDialog :ref="dialog" @update="getData">
</template>
<script setup>
import MyDialog from './MyDialog.vue'
import { ref } from 'vue'
const dialog = ref()
function openDialog() {
  dialog.value.open()
}
</script>

父组件经过调用子组件露出的open方法去操控状态,而且还能经过参数就行初数据交互,子组件经过emit露出方法给父组件交互.

痛点

MyDialog组件一般是对组件库的Model组件进行的二次封窗,假设我想修正或呼应Model装备和事件,我要在一级父组件下去调用MyDialog下的定义的方法和特点,然后再传给三级组件.

这样当事务和UI变的越来越复杂的时分,MyDialog组件也许会有多个props,emits,exposes.

假如咱们让想父组件直接和三级组件通讯,略过MyDialog易手的繁琐,怎么办呢.

vue3全能的hook

咱们把MyDialogDialog组件都用jsx use的形式去写.

// Dialog.jsx
import { reactive, toRefs } from 'vue'
export function useDialog(/*init参数*/) {
  const config = reactive({
    state: false,
    title: '',
    loadingL false
  })
  const Dialog = defineComponent({
    setup(_props, { emit, slots }) {
      return () => <NModel v-model:show={config.state}>
        {slots.default()}
      </NModel>
    }
  })
  return {
    ...toRefs(config),
    Dialog
  }
}
// MyDialog.jsx
import { useDialog } from '@/component/Dialog'
export function useMyDialog(...props) {
  const { Dialog, ...config } = useDialog(...props)
  const MyDialog = defineComponent({
    setup(_props, { emit, slots }) {
      return () => <Dialog>
        // ...
      </Dialog>
  })
  return {
     ...config,
     MyDialog
  }
}

当咱们父组件去调用弹窗组件的时分,经过useMyDialog传入的参数,就能操控最底层的封装组件,经过回来的refs获取最原始的呼应值.

总结

这样的一个demo也许并不有用,例如二级组件是需求经常手写的,用jsxtemplate麻烦一些.

但是函数式开发的思路还是要把握的,经过参数和回来值替代vue2的propemit我认为是大势所趋.vue3的prox代理形式也许比react更适合useHook.