index.jsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /**
  2. * @description 用于触发多表单验证
  3. * @author xmf
  4. */
  5. import { ref, markRaw } from 'vue'
  6. export default {
  7. name: 'CipFormValidate',
  8. setup (props, { slots, expose }) {
  9. const defaultSlot = ref([])
  10. const isComponent = vnode => !!vnode.component
  11. const isFormComponent = (vnode) => {
  12. if (!isComponent(vnode)) return false
  13. const componentName = (vnode.type?.name ?? '').toLocaleLowerCase()
  14. return componentName.indexOf('form') > -1
  15. }
  16. const getComponent = vnode => vnode?.component
  17. const getMethodByComponent = (component = {}, method) => component.ctx?.[method] ?? component.exposed?.[method]
  18. const clearValidate = (vnodeList = []) => {
  19. // eslint-disable-next-line no-unused-expressions
  20. const handler = (component) => {
  21. const clearValidate = getMethodByComponent(component, 'clearValidate')
  22. // eslint-disable-next-line no-unused-expressions
  23. clearValidate?.()
  24. }
  25. return findFormAndHandler(vnodeList, handler).then(() => {})
  26. }
  27. const findFormAndHandler = async (vnodeList = [], handler = () => {}, depth = 1) => {
  28. for (let i = 0; i < vnodeList.length; i++) {
  29. const vnode = vnodeList[i]
  30. if (isFormComponent(vnode)) {
  31. const component = getComponent(vnode)
  32. await handler(component)
  33. } else {
  34. if (depth > props.maxDepth) return false
  35. // 使用defineAsyncComponent 是 subTree 及为下个组件
  36. const childVnodeList = isComponent(vnode)
  37. ? (vnode.component.subTree?.children ?? [vnode.component.subTree])
  38. : vnode.children
  39. // 如果是文字节点则跳过不处理
  40. if (typeof childVnodeList === 'string') {
  41. continue
  42. }
  43. if (childVnodeList?.length > 0) {
  44. await findFormAndHandler(childVnodeList, handler, ++depth) // 此处++必须在前
  45. }
  46. }
  47. }
  48. }
  49. const validForms = async (vnodeList = []) => {
  50. const validList = []
  51. const handler = async (component) => {
  52. try {
  53. const validate = getMethodByComponent(component, 'validate')
  54. await validate?.()
  55. validList.push(true)
  56. } catch (e) {
  57. validList.push(e)
  58. }
  59. }
  60. try {
  61. await findFormAndHandler(vnodeList, handler)
  62. } catch (e) {
  63. console.log('findFormAndHandler', e)
  64. }
  65. return validList
  66. }
  67. const validate = async () => {
  68. const validList = await validForms(defaultSlot.value)
  69. if (!validList.some(valid => valid !== true)) {
  70. return true
  71. } else {
  72. // 此处不需要报错
  73. throw new Error('未通过表单验证')
  74. }
  75. }
  76. const clear = () => {
  77. return clearValidate(defaultSlot.value)
  78. }
  79. expose({
  80. validate,
  81. clear
  82. })
  83. return () => {
  84. const slot = slots.default?.()
  85. if (slot) {
  86. defaultSlot.value = markRaw(slot)
  87. }
  88. return slot
  89. }
  90. }
  91. }