1.0.0 • Published 9 months ago

vue-zoey-form v1.0.0

Weekly downloads
-
License
MIT
Repository
-
Last release
9 months ago

VueZoeyForm 组件

VueZoeyForm 是一个用于生成表单的 Vue 组件。基于elementUI,它提供了各种不同类型的表单字段,包括文本输入框、多行文本框、密码框、下拉框、单选框、开关、多选框、日期选择器、时间选择器、图片上传、按钮等。你可以根据具体需求配置不同的字段和验证规则。

下载并且调用

npm install --save vue-zoey-form
// main.js
import VueZoeyForm from 'vue-zoey-form'
Vue.use(VueZoeyForm)

Props参数

  • config (required): 表单的配置对象,包含以下属性:
    • title (String): 表单标题(可选)。
    • cards/items (Array): 表单项数组,有/无 边框阴影独立每块内容,每个项包含以下属性:
      1. label(String): 字段描述,比如‘用户名’,‘密码’
      2. type (String): 字段类型,比如‘text’,‘password’
      3. key (String): 字段的键,提交给后端的字段,比如username,password
      4. value (Any): 字段的初始值。
      5. attrs (Object): 字段的额外属性(可选),主要是原本elementui的原始属性,用于传递给对应的表单组件。
      6. options (Array): 对于下拉框和单选框类型的字段,选项数组,每个选项包含 valuelabel 属性。
      7. colspan (number): 列,比如一行一列,一行2列

事件

  • submit: 当表单验证通过并提交时触发该事件,并传递表单数据对象作为参数。
  • reset: 重置表单数据

插槽

  • btn: 用于自定义按钮组件的插槽。可以接收一个含有参数 truleForm 的函数,其中 t 是按钮文本,ruleForm 是表单数据对象。如果未提供该插槽,则默认显示提交和重置按钮。

字段类型

VueZoeyForm 组件支持的字段类型及其对应的取值为:

  • text: 文本输入框
  • textarea: 多行文本框
  • password: 密码框
  • select: 下拉框
  • radio: 单选框
  • switchs: Switch 开关
  • checkbox: 多选框
  • datepicker: 日期选择器
  • timepicker: 时间选择器
  • timeselect: 时间点选择器
  • images: 图片上传
  • button: 按钮
  • custom: 自定义模版

使用示例

<template>
    <div>
        <VueZoeyForm ref="form" :config="formConfig" @submit="handleSubmit"> </VueZoeyForm>
    </div>
</template>
  
<script>
import formConfig from './page';
export default {
    methods: {
        handleSubmit(formData) {
            // 处理表单提交逻辑
            console.log('表单数据:', formData)
        },
        handlereset(){​
            this.$refs.form.reset()​
        }
    },
}
</script>

数据如下:

没有边框版本

// page.js
const TEXTAREA = 'textarea' // 多行文本
const PASSWORD = 'password' // 密码
const RADIO = 'radio' // 单选框
const DATE_PICKER = 'datepicker' // 日期选择器
// 性别
export const sexOptions = [{
    value: 'man',
    label: '男'
  },
  {
    value: 'woman',
    label: '女'
  }
]
// 婚否
export const marriageOptions = [{
    value: 'married',
    label: '已婚'
  },
  {
    value: 'unmarried',
    label: '未婚'
  }
]
// 优化 => data方法中,默认是会Object.defineProperty => 当触发属性的get/set => 页面的更新
export default {
  items: Object.freeze([
    [{
      label: '用户名',
      colspan: 24,
      key: 'account',
      type: TEXTAREA
    }],
    [{
      label: '密码',
      colspan: 24,
      key: 'password',
      type: PASSWORD
    }],
    [{
      label: '确认密码',
      colspan: 24,
      key: 'confirmPwd',
      type: PASSWORD
    }],
    [{
      label: '性别',
      colspan: 8,
      key: 'sex',
      type: RADIO,
      value: 'man',
      options: sexOptions

    }],
    [{
      label: '出生日期',
      key: 'dd',
      type: DATE_PICKER,
      colspan: 8,
      attrs: {
        type: 'date',
        'placeholder': '选择日期'
      }
    }, ],
    [{
      label: '性别',
      colspan: 8,
      key: 'sex',
      type: RADIO,
      value: 'unmarried',
      options: marriageOptions

    }]
  ]),
  rules: {
    account: [{
      "required": true,
      "message": "用户名必填",
      "trigger": "blur"
    }],
    password: [{
        "required": true,
        "message": "用户名必填",
        "trigger": "blur"
      },
      {
        "trigger": "blur",
        message: '密码必须要6-12位之间',
        min: 6,
        max: 12,
      }
    ],
    confirmPwd: [{
      "trigger": "blur",
      validator: function (rule, value, callback) {
        if (!value) {
          return callback(new Error('确认密码不能为空'));
        }
        if (value === this.formData.password) {
          return callback();
        } else {
          return callback(new Error('两次密码不一致..'))
        }
      }
    }],
  }
}

cards版本 有边框

// page.js
const TEXTAREA = 'textarea'// 多行文本
const PASSWORD = 'password' // 密码
const RADIO = 'radio'// 单选框
const SWITCH = 'switchs'// Switch 开关
const DATE_PICKER = 'datepicker'// 日期选择器
const TIME_PICKER = 'timepicker'// 时间选择器
// 性别
export const sexOptions = [
  { value: 'man', label: '男' },
  { value: 'woman', label: '女' }
]
// 婚否
export const marriageOptions = [
  { value: 'married', label: '已婚' },
  { value: 'unmarried', label: '未婚' }
]

// 优化 => data方法中,默认是会Object.defineProperty => 当触发属性的get/set => 页面的更新

export default Object.freeze({
  cards: [
    {
    //   name: '测试信息',
      children: [
        [
          { label: '出生日期', key: 'dd', type: DATE_PICKER,
            attrs: { type: 'date', 'placeholder': '选择日期' }
          },
          { label: '准确时间', key: 'birthtime', type: TIME_PICKER,
            attrs: { 'placeholder': '任意时间点', 'value-format': 'timestamp' }
          },
          { label: '时间段', key: 'birthtimes', type: TIME_PICKER,
            attrs: {
              'is-range': true, 'start-placeholder': '开始时间',
              'end-placeholder': '结束时间',
              'range-separator': '至', 'arrow-control': true, 'value-format': 'timestamp'
            }
          },
          {
            label: '日历',
            key: 'leadar',
            type: SWITCH,
            attrs: {
              'active-color': 'red',
              'active-text': '阳历', 'inactive-text': '农历'
            }
          },
          {
            label: '性别',
            key: 'sex',
            type: RADIO,
            value: 'man',
            options: sexOptions
          }
        ],
        [{ label: '身份证', key: 'identity_card', type: PASSWORD }],
        [
          {
            label: '婚姻状态',
            key: 'marriage',
            type: RADIO,
            options: marriageOptions
          },
          { label: '居住地址', key: 'address1', type: TEXTAREA }
        ]
      ].map(row => row.map(item => ({ colspan: 8, ...item })))
    },
  ],
  rules: {
    identity_card: [
      { required: true, message: '请输入身份证', trigger: 'change' }
    ],
  }
}
)

在以上示例中,我们定义了一个包含多个表单字段的表单配置对象 formConfig,其中使用了不同的字段类型和相应的属性。在 <vue-zoey-form> 组件中,我们绑定了 config 属性为 formConfig,并监听了 submit 事件,在事件处理函数中可获取到表单数据对象。当然也可以使用自定义按钮插槽 btn,将按钮的点击事件绑定到 submitForm 方法。

只需根据需要配置 config 属性,定义自己的表单字段和验证规则,并监听 submit 事件处理表单提交的逻辑。

每个类型展示

<template>
  <div>
    <VueZoeyForm :config="conf"  @submit="createLoan">
      <template #imagesTemplate="{  }">
        <el-upload
          class="avatar-uploader"
          list-type="picture-card"
          :show-file-list="false"
          action="https://jsonplaceholder.typicode.com/posts/"
        >
          <img v-if="imageUrl" :src="imageUrl" class="avatar">
          <i v-else class="el-icon-plus avatar-uploader-icon" />
        </el-upload>
      </template>
      <template #customTemplate="{  }">
        <el-input v-model="input" placeholder="请输入内容" style="width:100px" />
        <el-select v-model="value" placeholder="请选择">
          <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
        <el-button type="primary">主要按钮</el-button>
      </template>
      <template #btn="{ t,ruleForm }">
        <el-button @click="createLoan(ruleForm)">提交{{ t }}</el-button>
      </template>
    </VueZoeyForm>
  </div>
</template>

<script>
import conf from './pagelist'

export default {
  name: 'PageZoey',
  data() {
    return {
      conf, input: '', imageUrl: '',
      options: [{
        value: '选项1',
        label: '黄金糕'
      }, {
        value: '选项2',
        label: '双皮奶'
      }, {
        value: '选项3',
        label: '蚵仔煎'
      }, {
        value: '选项4',
        label: '龙须面'
      }, {
        value: '选项5',
        label: '北京烤鸭'
      }],
      value: ''
    }
  },
  beforeDestroy() {
    console.log(this.$options.name, '被销毁了..')
  },
  methods: {
    async createLoan(user) {
      console.log(user)
      this.$notify.success('添加成功')
    },
   
  }
}
</script>

数据如下

// pagelist.js
const TEXT = 'text'// 文本
const TEXTAREA = 'textarea'// 多行文本
const PASSWORD = 'password' // 密码
const SELECT = 'select' // 下拉框
const RADIO = 'radio'// 单选框
const SWITCH = 'switchs'// Switch 开关
const CHECKBOX = 'checkbox'// 多选框
const DATE_PICKER = 'datepicker'// 日期选择器
const TIME_PICKER = 'timepicker'// 时间选择器
const TIME_SELECT = 'timeselect'// 时间点选择器
const CUSTOM = 'custom' // 自定义模版

const IMAGES = 'images'// 图片上传
const BUTTON = 'button' // 按钮
// 性别
export const sexOptions = [
  { value: 'man', label: '男' },
  { value: 'woman', label: '女' }
]
// 行业
export const companyOptions = [
  { value: 'education', label: '教育' },
  { value: 'finance', label: '金融' }
]
// 区域
export const cityOptions = [
  { value: 'sh', label: '上海' },
  { value: 'bj', label: '北京' },
  { value: 'gz', label: '广州' },
  { value: 'sz', label: '深圳' }
]

// 婚否
export const marriageOptions = [
  { value: 'married', label: '已婚' },
  { value: 'unmarried', label: '未婚' }
]
// 学历
export const educationOptions = [
  { value: 'college', label: '大学' },
  { value: 'highschool', label: '高中' },
  { value: 'chuz', label: '初中' },
  { value: 'xiaox', label: '小学' }
]

// 优化 => data方法中,默认是会Object.defineProperty => 当触发属性的get/set => 页面的更新

export default Object.freeze({
  cards: [
    {
      name: '个人基本信息',
      children: [
        [
          { label: '姓名', key: 'name', type: TEXT },
          { label: '出生日期', key: 'birthday', type: DATE_PICKER,
            attrs: { type: 'date', 'placeholder': '选择日期' }
          },
          { label: '准确时间', key: 'birthtime', type: TIME_PICKER,
            attrs: { 'placeholder': '任意时间点', 'value-format': 'timestamp' }
          },
          { label: '时间段', key: 'birthtimes', type: TIME_PICKER,
            attrs: {
              'is-range': true, 'start-placeholder': '开始时间',
              'end-placeholder': '结束时间',
              'range-separator': '至', 'arrow-control': true, 'value-format': 'timestamp'
            }
          },
          {
            label: '日历',
            key: 'leadar',
            type: SWITCH,
            attrs: {
              'active-color': 'red',
              'active-text': '阳历', 'inactive-text': '农历'
            }
          },
          {
            label: '性别',
            key: 'sex',
            type: RADIO,
            value: 'man',
            options: sexOptions
          }
        ],
        [{ label: '身份证', key: 'identity_card', type: PASSWORD }],
        [
          {
            label: '婚姻状态',
            key: 'marriage',
            type: RADIO,
            options: marriageOptions
          },
          {
            label: '教育程度',
            type: SELECT,
            key: 'education',
            options: educationOptions
            // optionsList: [{ key: 'education', list: educationOptions }, { key: 'education1', list: marriageOptions }, { key: 'education2', list: educationOptions }]
          },
          { label: '就学时间', key: 'study', type: DATE_PICKER,
            attrs: {
              type: 'daterange',
              'range-separator': '至',
              'start-placeholder': '开始日期',
              'value-format': 'yyyy-MM-dd',
              'end-placeholder': '结束日期'
            }
          },
          { label: '居住地址', key: 'address1', type: TEXTAREA }
        ]
        // [
        //   { label: '户籍地址', key: 'address2', type: TEXT },
        //   { label: '居住电话', key: 'phone', type: TEXT },
        //   { label: '手机号', key: 'mobile_phone', type: TEXT }
        // ]
      ].map(row => row.map(item => ({ colspan: 8, ...item })))
    },
    {
      name: '职业信息',
      children: [
        [ // element原生属性
          { label: '选择信息', btn: '选择', key: '', type: BUTTON,
            action: function actions() {
              console.log(1111)
            },
            attrs: {
              'type': 'warning', 'round': true
            }
          },
          { label: '选择头像', key: 'icon', type: IMAGES },
          { label: '自定义模版', key: 'suc', type: CUSTOM, attr: { 'label-width': '100px' }},
          { label: '现职公司', key: 'company', type: TEXT },
          { label: '工作时间', key: 'worktime', type: TIME_SELECT,
            attrs: { 'placeholder': '任意时间点' }
          },
          {
            label: '所属区域',
            attrs: { placeholder: '请选择' },
            key: 'position', type: CHECKBOX,
            options: cityOptions
          },
          {
            label: '所属行业',
            attrs: { placeholder: '请选择' },
            key: 'trade', type: RADIO,
            options: companyOptions
          }
        ].map(item => ({ colspan: 12, ...item }))
      ]
    }
  ],
  rules: {
    name: [
      { required: true, message: '请输入姓名', trigger: 'blur' },
      {
        min: 2,
        max: 5,
        message: '长度在 2 到 5 个字符',
        trigger: 'blur'
      }
    ],
    identity_card: [
      { required: true, message: '请输入身份证', trigger: 'change' }
    ],
    birthday: [
      {
        required: true,
        message: '请选择日期',
        trigger: 'change'
      }
    ],
    study: [
      {
        required: true,
        message: '请选择时间段',
        trigger: 'change'
      }
    ],
    sex: [{ required: true, message: '请选择性别', trigger: 'change' }],
    marriage: [
      { required: true, message: '请选择婚姻状态', trigger: 'change' }
    ],
    education: [
      { required: true, message: '请选择教育程度', trigger: 'change' }
    ],
    trade: [
      { required: true, message: '请选择所属行业', trigger: 'change' }
    ],
    position: [
      { required: true, message: '请选择所属区域', trigger: 'change' }
    ]

  }
}
)

开发上传步骤

安装并配置发布相关的依赖项

npm install --save-dev rimraf

在package.json文件中添加构建和发布脚本

{
  "name": "vue-zoey-form",
  "version": "1.0.0",
  "main": " dist/vue-zoey-form.umd.min.js ",
  "keywords": ["vue", "zoey", "form"],
  "author": "zoey",
  "license": "MIT",
  "scripts": {
    "build": "rimraf dist && vue-cli-service build --target lib --name vue-zoey-form src/components/VueZoeyForm.vue",
    "prepublishOnly": "npm run build"
  }
}

步骤

  • 使用了rimraf工具来在构建之前删除dist文件夹。
  • 使用vue-cli-service将 VueZoeyForm.vue构建为一个名为vue-zoey-form.js的库文件
  • 运行以下命令将组件发布到npm
npm config get registry
npm config set registry https://registry.npmjs.org/ # 检查注册表并且更换为官网注册表

npm login # 按照提示输入用户名、密码和电子邮件地址以登录到npm账户

// npm login
// npm notice Log in on https://registry.npmjs.org/
// Username: zoeyz0000
// Password: 
// Email: (this IS public) 1291609705@qq.com
// npm notice Please check your email for a one-time password (OTP)
// Enter one-time password: 12417992
// Logged in as zoeyz0000 on https://registry.npmjs.org/.
  • 打包dist yarn build

  • 运行发布命令

npm publish # 将组件上传到npm仓库中
 # 不允许私有包。所以需要package.json  "private": false,
  • 删除
npm unpublish <package-name> [--force] // <package-name> 替换为您要删除的包的名称 --force 标志以强制删除
//  npm unpublish xxx --force
1.0.0

9 months ago

0.1.2

9 months ago

0.1.1

9 months ago

0.1.0

9 months ago