Vue 组件应用:仿element UI中的Form组件 简单版

调用
  • 由Form, FormItem 及实现双向绑定的Input组成
<template>
    <div>
        <h3>Element表单</h3>
        <hr>
        <k-form :model="model" :rules="rules" ref="loginForm">
            <k-form-item label="用户名" prop="username">
                <k-input v-model="model.username" autocomplete="off" placeholder="输入用户名"></k-input>
            </k-form-item>
            <k-form-item label="确认密码" prop="password">
                <k-input type="password" v-model="model.password" autocomplete="off"  placeholder='请输入密码'></k-input>
            </k-form-item>
            <k-form-item>
                <button @click="submitForm('loginForm')">提交</button>
            </k-form-item>
        </k-form>
        {{model}}
    </div>
</template>

<script>
import KForm from "./Form";
import KFormItem from "./FormItem";
import KInput from "./Input";

export default {
    components: {
        KForm,
        KFormItem,
        KInput
    },
    data() {
        return {
            model: { username: "tom", password: "" },
            rules: {
                username: [{ required: true, message: "请输入用户名" }],
                password: [{ required: true, message: "请输入密码" }]
            }
        };
    },
    methods: {
        submitForm(form) {
            this.$refs[form].validate(valid => {
                if (valid) { alert('请求登录!') } else { alert('校验失败!') }
            });
        }
    }
};
</script>
Input
  • 双向绑定:@input、:value
  • 派发校验事件
  • v-bind='$attrs',实现非props属性绑定
<template>
    <div>
        <input :value="value" @input="onInput" v-bind="$attrs">
    </div>
</template>

<script>
export default {
    inheritAttrs: false,
    props: {
        value: {
            type: String,
            default: ''
        },
    },
    methods: {
        onInput(e) {
            this.$emit('input', e.target.value)
            // 派发校验事件
            this.$parent.$emit('validate')
        }
    },
}
</script>
FormItem
  • 为Input预留插槽 slot
  • 能够展示label和校验信息
  • 能够进行校验
<template>
    <div>
        <label v-if="label">{{label}}</label>
        <slot></slot>
        <p v-if="errorMessage">{{errorMessage}}</p>
    </div>
</template>

<script>
import Schema from 'async-validator'

export default {
    inject: ['form'],
    props: {
        label: {
            type: String,
            default: ''
        },
        prop: {
            type: String
        }
    },
    data() {
        return {
            errorMessage: ''
        }
    },
    mounted() {
        this.$on('validate', this.validate)
    },
    methods: {
        validate() {
            const value = this.form.model[this.prop]
            const rules = this.form.rules[this.prop]
            // npm i async-validator -S
            const desc = { [this.prop]: rules }
            const schema = new Schema(desc)
            // return的是校验结果的Promise
            return schema.validate({ [this.prop]: value }, error => {
                if (error) {
                    this.errorMessage = error[0].message
                } else {
                    this.errorMessage = ''
                }
            })
        }
    },
}
</script>
Form
  • 给FormIten预留插槽 slot
  • 设置数据和校验规则
  • 全局校验
<template>
  <div>
    <slot></slot>
  </div>
</template>

<script>
export default {
  provide() {
    return {
      form: this
    };
  },
  props: {
    model: {
      type: Object,
      required: true
    },
    rules: {
      type: Object
    }
  },
  methods: {
    validate(cb) {
      const tasks = this.$children
        .filter(item => item.prop)
        .map(item => item.validate());

      // 所有任务都通过才算校验通过
      Promise.all(tasks)
        .then(() => cb(true))
        .catch(() => cb(false));
    }
  }
};
</script>
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 组件(Component)是Vue.js最核心的功能,也是整个架构设计最精彩的地方,当然也是最难掌握的。...
    六个周阅读 5,659评论 0 32
  • 什么是组件? 组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装...
    youins阅读 9,556评论 0 13
  • 一、了解Vue.js 1.1.1 Vue.js是什么? 简单小巧、渐进式、功能强大的技术栈 1.1.2 为什么学习...
    蔡华鹏阅读 3,417评论 0 3
  • 以下内容是我在学习和研究Vue时,对Vue的特性、重点和注意事项的提取、精练和总结,可以做为Vue特性的字典; 1...
    科研者阅读 14,173评论 3 24
  • 原文 初,郑武公娶于申,曰武姜,生庄公及共叔段。庄公寤生,惊姜氏,故名曰寤生,遂恶之。爱共叔段,欲立之。亟请于武公...
    鸾英阅读 1,663评论 3 1