- 先用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>
- 父组件在运用的时分:
<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
咱们把MyDialog
和Dialog
组件都用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
也许并不有用,例如二级组件是需求经常手写的,用jsx
比template
麻烦一些.
但是函数式开发的思路还是要把握的,经过参数和回来值替代vue2的prop
和emit
我认为是大势所趋.vue3的prox代理形式也许比react更适合useHook
.