index.tsx 2.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
import { defineComponent, provide, ref } from 'vue'
import {
  useCustomEvent,
  EmitEvent,
  CustomEventTrigger,
} from '../../helpers/useNVueEvent'
import { uniFormKey, UniFormCtx, UniFormFieldCtx } from '../../components/form'

const NATIVE_COMPONENTS = ['u-input', 'u-textarea']

export default defineComponent({
  name: 'Form',
  emits: ['submit', 'reset'],
  setup({}, { slots, emit }) {
    const rootRef = ref<HTMLElement | null>(null)
    const trigger = useCustomEvent<EmitEvent<typeof emit>>(rootRef, emit)

d-u-a's avatar
d-u-a 已提交
18 19
    const vnodes = slots.default && slots.default()
    provideForm(trigger, vnodes)
20 21

    return () => {
d-u-a's avatar
d-u-a 已提交
22
      return <view ref={rootRef}>{vnodes}</view>
23 24 25 26 27 28 29 30 31 32 33
    }
  },
})

function provideForm(trigger: CustomEventTrigger, children: any) {
  const modulePlus = weex.requireModule('plus')
  const fields: UniFormFieldCtx[] = []
  const getOrClearNativeValue = (nodes: any, outResult: any): void => {
    nodes.forEach(function (node: any) {
      if (
        NATIVE_COMPONENTS.indexOf(node.type) >= 0 &&
d-u-a's avatar
d-u-a 已提交
34 35
        node.el.attr &&
        node.el.attr.name
36 37
      ) {
        if (outResult) {
d-u-a's avatar
d-u-a 已提交
38
          outResult[node.el.attr.name] = modulePlus.getValue(node.el.nodeId)
39
        } else {
d-u-a's avatar
d-u-a 已提交
40
          node.el.setValue('')
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
        }
      }
      if (
        Array.isArray(node.children) &&
        node.children &&
        node.children.length
      ) {
        getOrClearNativeValue(node.children, outResult)
      }
    })
  }

  provide<UniFormCtx>(uniFormKey, {
    addField(field: UniFormFieldCtx) {
      fields.push(field)
    },
    removeField(field: UniFormFieldCtx) {
      fields.splice(fields.indexOf(field), 1)
    },
    submit(evt: Event) {
      // 获取原生组件值
      let outFormData: any = {}
      getOrClearNativeValue(children, outFormData)

      let formData = fields.reduce((res, field) => {
        if (field.submit) {
          const [name, value] = field.submit()
          name && (res[name] = value)
        }
        return res
      }, Object.create(null))

      Object.assign(outFormData, formData)

      trigger('submit', {
        value: outFormData,
      })
    },
    reset(evt: Event) {
      // 清空原生组件值
      getOrClearNativeValue(children, null)

      fields.forEach((field) => field.reset && field.reset())
      trigger('reset', evt)
    },
  })
  return fields
}