日常开发中积累了不少可能对一些开发有帮助的简单易用的组件, 好记性不如烂笔头, 想对过去的一些零零乱乱的东西做一些总结, 反省自己的同时也便于思考一些更优的方法, 提升下开发思维.
代码传送门 (感觉有作用的的同学帮忙点下)
效果截图
先上效果图, 自定义规则, 违反规则马上显示提示.
Form
组件结构
参照 elementUI 的表单组件, 组件的结构是 Form> ... (FormItem> Form 组件)
- <j-form> // Form
- <j-form-item> // FormItem
- <j-input></j-input> // content
- </j-form-item>
- // ... 可以添加多个 Item
- </j-form>
核心代码
Form 组件
最上级是 Form 组件, 是进行全局验证的组件, 并且接收 prop(传递的数据模型和规则), 并将自身注入到子级中.
- <template>
- <div id="form">
- <slot></slot>
- </div>
- </template>
- <script>
- export default {
- name: 'j-form',
- // 将自身注入
- provide () {
- return {
- form: this
- }
- },
- props: {
- // 数据模型
- model: {
- type: Object,
- required: true
- },
- // 校验规则
- rules: {
- type: Object
- }
- },
- methods: {
- // 表单全局校验方法, 校验所有的 item 内容
- validate (callBack) {
- const tasks = this.$children.filter(item => item.prop).map(item => item.validate())
- // 所有任务都通过才算校验通过
- Promise.all(tasks).then(() => callBack(true)
- ).catch(() => callBack(false)
- )
- }
- }
- }
- </script>
FormItem 组件
用 item 组件包裹表达内容组件, 目的是为了进行单一校验, 并产生错误的提示信息. 这里使用的是 async-validator 第三方的校验库, 需要额外装载.
- <template>
- <div id="form-item">
- <label v-if="label" class="label">{{label}}</label>
- <slot></slot>
- <p v-if="errorMsg" class="error-msg">{{errorMsg}}</p>
- </div>
- </template>
- <script>
- import Schema from 'async-validator'
- export default {
- name: 'j-form-item',
- components: {},
- inject: ['form'],
- data () {
- return {
- errorMsg: ''
- }
- },
- props: {
- // 标题文本
- label: {
- type: String,
- default: '',
- required: true
- },
- // 数据字段名
- prop: {
- type: String
- }
- },
- mounted () {
- // 监听校验
- this.$on('validate', () => { this.validate() })
- },
- methods: {
- validate () {
- console.log('触发校验 ===')
- // async-validator 的校验方法
- const value = this.form.model[this.prop]
- const rules = this.form.rules[this.prop]
- const desc = { [this.prop]: rules }
- const schema = new Schema(desc)
- // return 的是校验结果的 Promise
- return schema.validate({ [this.prop]: value }, errors => {
- if (errors) {
- console.log('error', errors[0].message)
- this.errorMsg = errors[0].message
- } else {
- console.log('error', errors)
- this.errorMsg = ''
- }
- })
- }
- }
- }
- </script>
Input 组件
内容组件, 在这里进行内容的监听, 上到 FormItem 进行校验
- <template>
- <div id="input">
- <input :value="value" @input="onInput" v-bind="$attrs" />
- </div>
- </template>
- <script>
- export default {
- name: 'j-input',
- // 禁用继承的属性
- inheritAttrs: false,
- model: {
- prop: 'value',
- event: 'change'
- },
- props: {
- value: {
- type: String,
- default: ''
- }
- },
- methods: {
- onInput (e) {
- console.log(e.target.value)
- // 监听数值变化
- this.$emit('change', e.target.value)
- // 触发校验
- this.$parent.$emit('validate')
- }
- }
- }
- </script>
使用
使用组件就和 elementUI 一样进行处理即可
- <template>
- <div id="home">
- <j-form ref="ruleForm" :model="model" :rules="rules">
- <j-form-item label="姓名" prop="name">
- <j-input v-model="model.name" placeholder="请输入姓名" />
- </j-form-item>
- <j-form-item label="年龄" prop="age">
- <j-input v-model="model.age" placeholder="请输入年龄" />
- </j-form-item>
- </j-form>
- </div>
- </template>
- <script>
- export default {
- components: {},
- data () {
- return {
- model: {
- name: '',
- age: ''
- },
- rules: {
- name: [
- { required: true, message: '请填写姓名', trigger: 'change' },
- { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'change' }
- ],
- age: [
- { required: true, message: '请填写年龄', trigger: 'change' },
- { min: 1, max: 2, message: '长度在 1 到 2 个字符', trigger: 'change' }
- ]
- }
- }
- }
关键点
处理自定义组件, 一定要对 vue 中的传值比较清晰了解, 这里就不一一列举. 在这里主要使用的一些技术包括:
技术 | 概述 | 备注 |
---|---|---|
props 传值 | 父级传子级 | / |
provide-inject | 从上往下可以跨级传值 | 在代码里将自身传递下来 |
slot | 插槽,将子组件插入父组件中 | Input>FormIten>Form |
inheritAttrs-$attrs | 禁用继承的属性直接赋予给根标签,自定义继承 | / |
v-model | 自定义双向传值 | / |
Promise.all() | 同时完成所有的任务 | / |
后续会持续更新其他一些有用的组件提供参考...
来源: http://www.jianshu.com/p/01a07cbe8ceb