Skip to content

基础表单

最基础的表单,创建表单组件,在组件内部抛出方法,表单本身只做显示,由外部控制它的提交。

在这里为表单输入默认值

username:
password:

用户名:
密码:
代码
vue
<script setup lang="ts">
import { ref, computed, useTemplateRef } from 'vue'
import MyForm from './my-form.vue'
import type { FormData } from './types'

const showForm = ref(false)
const btnText = computed(() => {
  return showForm.value ? '隐藏' : '显示'
})

const _data = ref({
  username: '测试用户',
  password: '123',
})
const getData = async () => {
  await new Promise(resolve => {
    setTimeout(() => {
      resolve(true)
    }, 1000)
  })
  return _data.value
}

const switchForm = async () => {
  if (!showForm.value) {
    await openForm()
  } else {
    closeForm()
  }
}
const openForm = async () => {
  if (!myFormRef.value) { return }
  const data = await getData()
  // 从外部获取数据并赋值给表单
  await myFormRef.value.setValues(data)
  showForm.value = true
}
const closeForm = () => {
  showForm.value = false
}

const myFormRef = useTemplateRef<InstanceType<typeof MyForm> | null>('myFormRef')
const onSubmit = async () => {
  if (!myFormRef.value) { return }
  const data = await myFormRef.value.submit<FormData>()
  alert(`表单数据:${JSON.stringify(data)}`)
}
</script>

<template>
  <div>
    <div style="border: 1px solid green">
      <p>在这里为表单输入默认值</p>
      <div>
        <span>username: </span>
        <input v-model="_data.username" />
      </div>
      <div>
        <span>password: </span>
        <input v-model="_data.password" />
      </div>
    </div>

    <br />

    <div style="border: 1px solid red;">
      <button @click="switchForm">{{ btnText }}表单</button>

      <div v-show="showForm">
        <my-form ref="myFormRef"/>
        <button @click="onSubmit">提交</button>
      </div>
    </div>
  </div>
</template>
vue
<script setup lang="ts">
import { ref, toRaw } from 'vue'
import type { FormData } from './types'
import { cloneDeep } from 'lodash-es'

const formData = ref<FormData>({
  username: '',
  password: ''
})

defineExpose({
  submit: async <T>(): Promise<T> => {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(formData.value as T)
      }, 1000)
    })
  },
  setValues: async (data: FormData) => {
    formData.value = cloneDeep(toRaw(data))
  }
})
</script>

<template>
  <div>
    <form>
      <div>
        <span>用户名:</span>
        <input v-model="formData.username" />
      </div>
      <div>
        <span>密码:</span>
        <input v-model="formData.password" />
      </div>
    </form>
  </div>
</template>