npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vue-zoey-form

v1.0.0

Published

A Form component for Vue2

Readme

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) [email protected]
// 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