欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3+ElementPlus 表單組件的封裝實例

 更新時間:2022年06月02日 10:05:46   作者:小小前端程序猿  
這篇文章主要介紹了Vue3+ElementPlus 表單組件的封裝實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

在系統(tǒng)中,表單作為用戶與后端交互的重要傳遞組件使用頻率極高,故對其進行封裝是必然的,也是一個編寫規(guī)范代碼的前端程序員必須做的一件事。

在Vue3中封裝組件時,能感受到與Vue2有著很大的不同,故作此記錄。

form文件夾

在這里插入圖片描述

  • FormItem.tsx文件是Typescript中的新特性之一,詳細可查閱TS中文文檔
  • index.vue是主體文件
  • type.ts表單的規(guī)約

FormItem.tsx

import filter from '@/utils/filters'
import {
  ElCheckbox,
  ElCheckboxGroup,
  ElDatePicker,
  ElInput,
  ElInputNumber,
  ElOption,
  ElRadio,
  ElRadioGroup,
  ElSelect,
  ElTimePicker
} from 'element-plus'
import { defineComponent } from 'vue'
// 普通顯示
const Span = (form: Record<string, any>, data: Record<string, any>) => (
  <span>{data.valueProp ? form[data.valueProp] : (data.filter ? filter(form[data.prop], data.filter) : form[data.prop] || '無')}</span>
)
// 輸入框
const Input = (form: Record<string, any>, data: Record<string, any>) => (
  <ElInput
    v-model={form[data.prop]}
    type={data.type}
    size='small'
    show-password={data.type == 'password'}
    clearable
    placeholder={'請輸入' + data.label}
    autosize = {{
      minRows: 3,
      maxRows: 4,
    }}
    {...data.props}
  >
  </ElInput>
)
// 數(shù)字輸入框
const InputNumber = (form: Record<string, any>, data: Record<string, any>) => (
  <ElInputNumber
    size='small'
    v-model={form[data.prop]}
    controls-position="right"
    {...data.props}
  />
)
const setLabelValue = (_item: any, { optionsKey }: any = {}) => {
  return {
    label: optionsKey ? _item[optionsKey.label] : _item.label,
    value: optionsKey ? _item[optionsKey.value] : _item.value,
  }
}
// 選擇框
const Select = (form: Record<string, any>, data: Record<string, any>) => (
  <ElSelect
    size='small'
    v-model={form[data.prop]}
    filterable
    clearable 
    placeholder={'請選擇' + data.label}
    {...data.props}
  >
    {data.options.map((item: any) => {
      return <ElOption {...setLabelValue(item, data)} />
    })}
  </ElSelect>
)
// 單選/區(qū)間日期
const Date = (form: Record<string, any>, data: Record<string, any>) => (
  <ElDatePicker
    size='small'
    v-model={form[data.prop]}
    type={data.type}
    value-format={data.valueFormat}
    format = {data.format}
    range-separator="至"
    start-placeholder={data.startPlaceholder}
    end-placeholder={data.endPlaceholder}
    placeholder={'請選擇' + data.label}
    {...data.props}
  />
)
// 單選/區(qū)間時間
const Time = (form: Record<string, any>, data: Record<string, any>) => (
  <ElTimePicker
    size='small'
    v-model={[form[data.prop]]}
    value-format={data.valueFormat}
    format = {data.format}
    range-separator="至"
    disabled = {form.editable}
    start-placeholder={data.start}
    is-range={data.isRange}
    end-placeholder={data.end}
    {...data.props}
  />
)
// 單選
const Radio = (form: Record<string, any>, data: Record<string, any>) => (
  <ElRadioGroup v-model={form[data.prop]}>
    {data.radios.map(
      (item: { label: string | number | boolean; value: any }) => {
        return (
          <ElRadio label={setLabelValue(item, data.prop).label}>
            {setLabelValue(item, data.prop).value}
          </ElRadio>
        )
      },
    )}
  </ElRadioGroup>
)
// 多選
const Checkbox = (form: Record<string, any>, data: Record<string, any>) => (
  <ElCheckboxGroup size='small' v-model={form[data.prop]}>
    {data.checkboxs.map(
      (item: { label: string | number | boolean; value: any }) => {
        return (
          <ElCheckbox label={setLabelValue(item, data.prop).label}>
            {setLabelValue(item, data.prop).value}
          </ElCheckbox>
        )
      },
    )}
  </ElCheckboxGroup>
)
const setFormItem = (
  form: Record<string, any> | undefined,
  data: Record<string, any>,
  editable: Boolean,
) => {
  if (!form) return null
  if (!editable) return Span(form, data)
  switch (data.type) {
    case 'input':
      return Input(form, data)
    case 'textarea':
      return Input(form, data)
    case 'password':
      return Input(form, data)
    case 'inputNumber':
      return InputNumber(form, data)
    case 'select':
      return Select(form, data)
    case 'date':
    case 'daterange':
      return Date(form, data)
    case 'time':
      return Time(form, data)
    case 'radio':
      return Radio(form, data)
    case 'checkbox':
      return Checkbox(form, data)
    default:
      return null
  }
}
export default () =>
  defineComponent({
    props: {
      data: Object,
      formData: Object,
      editable: Boolean,
    },
    setup(props) {
      return () =>
        props.data
          ? setFormItem(props.formData, props.data, props.editable)
          : null
    },
  })

index.vue

<template>
  <el-form ref="FormRef"
           :model="prop.data.data"
           :rules="editable ? prop.data.rules : {}"
           :inline="inline"
           :label-position="labelPosition"
           label-width="atuo">
    <el-row :gutter="prop.data.elRowGutter">
      <el-col v-for="item in prop.data.formItems"
              :span="item.span">
        <el-form-item :label="item.label ? item.label + ':' : ''"
                      :prop="item.prop"
                      :label-width="item.width">
          <FormItem :formData="prop.data.data"
                    :editable="editable"
                    :data="item">
          </FormItem>
        </el-form-item>
      </el-col>
      <el-col v-if="btnList && btnList.length"
              :span="24">
        <el-form-item>
          <template v-for="item in btnList">
            <Btn :props="item"
                 @click="onClick(item)"></Btn>
          </template>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>
<script lang="ts" setup>
import { computed } from '@vue/reactivity'
import type { FormInstance } from 'element-plus'
import { ref } from 'vue'
import formItem from './FormItem'
import type { commonForm } from './type'
interface Props {
? data: commonForm
}
const prop = defineProps<Props>()
const editable = computed(() => !!prop.data?.editable)
const inline = computed(() => !!prop.data.formProps?.inline)
const labelWidth = computed(() => prop.data.formProps?.labelWidth || '100px')
const labelPosition = computed(
? () => prop.data.formProps?.labelPosition || 'top',
)
const btnList = computed(() => {
? return prop.data.formProps?.btn
})
// tsx組件
const FormItem = formItem()
const FormRef = ref<FormInstance>()
// 表單按鈕
function onClick(data: { onClick?: () => void }) {
? if (!data.onClick) return
? data.onClick()
}
// 表單校驗
async function validate() {
? if (!FormRef.value) return
? const result = await FormRef.value.validate()
? return result
}
// 清除表單驗證
async function resetFields() {
? return await FormRef.value.resetFields()
}
defineExpose({
? validate,
? resetFields,
})
</script>
<style scoped>
.el-form-item {
? margin: 0 10px !important;
}
.el-form-item__label {
? position: absolute;
}
.el-form-item__content {
? width: 100%;
? padding-left: 80px;
}
.el-select,
.el-input_inner {
? width: 100%;
}
</style>

type.ts

type itemType =
  | 'input'
  | 'select'
  | 'switch'
  | 'radio'
  | 'date'
  | 'time'
  | 'checkbox'
  | 'daterange'
interface FormProps {
  inline?: Boolean
  labelWidth?: string | number
  labelPosition?: 'left' | 'top' | 'right'
  btn?: object[]
}
interface FormItems {
  type: itemType
  label?: string
  prop: string
  valueProp?: string
  width?: string | number
  span?: number
  filter?: string
}
export class commonForm {
  public data: any
  private rules?: object
  public elRowGutter?: number
  public editable?: boolean
  public formProps?: FormProps
  public formItems: FormItems[]
  public dataArray?:object[]
  constructor({
    data = {},
    rules = {},
    editable = true,
    formProps = {},
    formItems = [],
    elRowGutter = 0,
  }: any) {
    this.data = data
    this.rules = rules
    this.elRowGutter = elRowGutter
    this.editable = editable
    this.formItems = formItems
    this.formProps = formProps
  }
}

在頁面中引用

在這里插入圖片描述

  • changCarrier.vue是主題頁面,用來顯示表單
  • userForm.ts是對表單進行渲染的數(shù)據(jù)項

index.vue

<template>
  <el-dialog v-model="show"
             v-if="show"
             :title="`${title}人員`"
             :before-close="handleClose"
             width="60%">
      <Form ref="FormRef"
            :data="formData"></Form>
    <template #footer>
      <el-button @click="handleClose">關 閉</el-button>
      <el-button type="primary"
                 v-show="!isDetail"
                 @click="submit">提 交</el-button>
    </template>
  </el-dialog>
</template>
<script lang="ts" setup>
import { reactive, ref, defineEmits } from 'vue'
// import api from '@/api'
import { ElMessage } from 'element-plus'
import useForm from './hooks/useForm'	//表單的
import api from '@/api/index'
enum types {
  'default' = '',
  'add' = '新增',
  'unData' = '編輯',
  'detail' = '詳情',
}
const show = ref(false)	//控制表單開關
const title = ref(types.default)	//表單標題
const FormRef = ref()	//表單DOM
const emit = defineEmits(['refresh'])	//父組件傳過來的方法,作用:在表單提交后觸發(fā),刷新數(shù)據(jù)
defineExpose({	//向父組件暴露其屬性及方法,實例:父組件點擊添加,觸發(fā)formRef中的addData行為
  show,
  title,
  setData,
  addData,
  delData,
})
// 表單生成
let formData = useForm()
//新增
function addData() {
  handleOpen('add')
}
// 編輯設置數(shù)據(jù)
function setData(data: object) {	//父組件點擊編輯,將值通過方法傳過來
  formData.data = reactive({ ...data })	
  handleOpen('unData')
}
//刪除
async function delData(data: number) {
  const res: any = await api.gasSite.deleteQueueApply({
    idList: [data],
  })
  emit('refresh')
}
// 請求
async function request() {
  let res: any
  // formData是否存在id值, 存在id值表示編輯, 不存在則為添加
  if (!formData.data?.id) {
    //編輯提交
    res = await api.gasSite.addQueueApply(formData.data)
  } else if (formData.data?.id) {
    //新增提交
    res = await api.gasSite.updateStartWarehouse(formData.data)
  }
  if (res?.status.state === '00') {
    ElMessage.success('操作成功')
    title.value = types.default
    emit('refresh')	//刷新數(shù)據(jù)
    show.value = false
  } else if (res?.status.state !== '00') {
    ElMessage.error(res?.status.state)
  }
  show.value = false
}
//清除驗證信息
async function reset() {
  await FormRef.value.resetFields()
}
//新增表單打開事件
function handleOpen(type: any) {
  formData.formItems = useForm().formItems //表單item
  formData.editable = true //打開表單編輯
  title.value = types[type]
  show.value = true //表單的打開
}
//表單關閉事件
function handleClose() {
  show.value = false
  reset()	//重置該表單項,將其值重置為初始值,并移除校驗結果
}
// 提交
async function submit() {
  const result = await FormRef.value.validate()
  if (result) request()
}
</script>

useForm

import { commonForm } from '@/components/common/form/type'
import { reactive } from 'vue'
export default () => {
  const rules = {
    name: [
      { required: true, message: '人員名稱', trigger: 'blur' }
    ]
  }
  const form = reactive(
    new commonForm({
      data: [],
      editable: true,
      rules: rules,
      formItems: [
        {
          label: '人員名稱',
          type: 'select',
          prop: 'name',
        },
        {
          label: '日期范圍',
          type: 'daterange',
          prop: 'queueDate',
          format:'YYYY-MM-DD',
          valueFormat:'YYYY-MM-DD',
          startPlaceholder:'開始時間',
          endPlaceholder:'結束時間',
          span: 6,
        },
        {
          label: '時間段范圍',
          type: 'time',
          prop: 'timeSlot',
          format:'HH:mm',
          valueFormat:'HH:mm',
          start:'開始時間',
          end:'結束時間',
          isRange:true,
          span: 6,
        },
        {
          label: '允許排隊數(shù)量',
          type: 'input',
          prop: 'queueNum',
          span: 6,
        },
        {
          label: '生效類型',
          type: 'select',
          prop: 'isDelay',
          options: [
            {
              label: '當日生效',
              value: 0,
            },
            {
              label: '次日生效',
              value: 1,
            }
          ],
          span: 6,
        },
        {
          label: '生效時間',
          type: 'date',
          prop: 'effectiveTime',
          format:'YYYY-MM-DD',
          valueFormat:'YYYY-MM-DD',
          span: 6,
        },
      ],
    }),
  )
  return form
}

總結

一百個人有一百個編寫代碼的習慣,其上實現(xiàn)是基于模塊化的思想,可能看起來有點累,但是我相信能幫助到你。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • vue.js綁定class和style樣式(6)

    vue.js綁定class和style樣式(6)

    這篇文章我們將一起學習vue.js實現(xiàn)綁定class和style樣式,感興趣的小伙伴們可以參考一下
    2016-12-12
  • Vue中watch和methods兩種屬性的作用

    Vue中watch和methods兩種屬性的作用

    這篇文章主要介紹了Vue中watch和methods兩種屬性的作用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2023-02-02
  • vue實現(xiàn)吸頂、錨點和滾動高亮按鈕效果

    vue實現(xiàn)吸頂、錨點和滾動高亮按鈕效果

    這篇文章主要介紹了vue實現(xiàn)一個簡單的吸頂、錨點和滾動高亮按鈕效果,需要的朋友可以參考下
    2019-10-10
  • Ant Design Pro 之 ProTable使用操作

    Ant Design Pro 之 ProTable使用操作

    這篇文章主要介紹了Ant Design Pro 之 ProTable使用操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • 記一次vue去除#問題處理經(jīng)過小結

    記一次vue去除#問題處理經(jīng)過小結

    這篇文章主要介紹了vue去除#問題處理經(jīng)過,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • vue-cli構建的項目如何手動添加eslint配置

    vue-cli構建的項目如何手動添加eslint配置

    這篇文章主要介紹了vue-cli構建的項目如何手動添加eslint配置,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue表格組件Vxe-table使用技巧總結

    Vue表格組件Vxe-table使用技巧總結

    這篇文章主要給大家介紹了關于Vue表格組件Vxe-table使用技巧的相關資料,文中還介紹了VXEtable展示指定行所遇到得問題,對大家學習或者使用Vxe-table具有一定的參考學習價值,需要的朋友可以參考下
    2022-09-09
  • Vue實現(xiàn)日歷小插件

    Vue實現(xiàn)日歷小插件

    這篇文章主要為大家詳細介紹了Vue實現(xiàn)日歷小插件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • vue3中的this.$set寫法舉例

    vue3中的this.$set寫法舉例

    在Vue2中,由于數(shù)據(jù)響應式是利用object.definedProperty()實現(xiàn)的,無法深層監(jiān)聽數(shù)據(jù)變化,因此提供了$set方法來解決數(shù)據(jù)變化視圖未實時更新的問題,然而,在Vue3中,數(shù)據(jù)響應式使用ES6的proxy進行數(shù)據(jù)代理,因此廢棄了$set的概念
    2024-10-10
  • Vue設置瀏覽器小圖標(ICON)的詳細步驟

    Vue設置瀏覽器小圖標(ICON)的詳細步驟

    vue中網(wǎng)頁圖標默認使用的是vue自帶的一個icon的圖標,也是vue的logo,下面這篇文章主要給大家介紹了關于Vue設置瀏覽器小圖標(ICON)的詳細步驟,需要的朋友可以參考下
    2023-01-01

最新評論