vue组件化开发实战 - 实现简易ElementUI的Form表单组件

Input 组件

功能:

  • 进行数据双绑
  • 通知FormItem组件校验
<template>
  <div>
     <input  :type="type" :value="value" @input="onInput" v-bind="$attrs" >
  </div>
</template>
<script>
export default {
    inheritAttrs:false,
    props:{
        value:{
            type: String,
            default: ''
        },
        type:{
            type: String,
            default: 'text'
        },
    },
    methods:{
        onInput(e){
            this.$emit('input',e.target.value);
            // 让父组件自己派发自己监听该valid事件进行校验。
            this.$parent.$emit('valid');
        }
    }
}
</script>

$attrsv-bind="$attrs" 使用

  • $attrs是vue内置属性用来存储外部传向一个组件但没有被props接收的属性。
  • 这些属性都有非prop特性
    1. 会被自动添加到组件的根元素上。
    2. 默认情况下,非prop特性的属性会覆盖组件根元素上同名的内容。 对于styleclass有特殊处理:进行合并(但是如果是同名样式则会覆盖)
    3. 如果不希望组件根元素继承非prop特性,可以在组件配置项中配置 inheritAttrs:false ( 该API对style和class没影响 )

v-bind="$attrs"是对$attrs进行解构赋值的一种方法,解构成:key="value"形式。

FormItem 组件

功能:

  • 校验
  • label显示
  • 错误显示
<template>
  <div>
    <label v-if="label">{{label}}</label>
    <slot></slot>
    <p v-if="error">{{error}}</p>
  </div>
</template>
<script>
  import Schema from 'async-validator'; // 校验包
  export default {
    inject:['form'],
    props:{
      label:{
        type:String,
        default:''
      },
      prop:{
        type:String,
        default:''
      }
    },
    data(){
      return {
        error:''
      }
    },
    mounted(){
      this.$on('valid',()=>{
          this.validate();
      })
    },
    methods:{
      validate(){
        const rules = this.form.rules[this.prop];
        const value = this.form.model[this.prop];

        const schema = new Schema({[this.prop]:rules});
        // 返回Promise<Boolean>
        return schema.validate({[this.prop]:value},(errors)=>{
          if(errors){
            this.error = errors[0].message;
          }else{
            this.error = '';
          }
        })
      }
    }
  }
</script>   

Form 组件

功能:

  • 提供数值
<template>
    <div>
        <slot></slot>
    </div>
</template>
<script>
export default {
    provide(){
        return {
            form:this  // 把form组件实例传给后代,后代可以通过该实例访问该组件上的属性 model、rule ...
        }
    },
    props:{
        model:{
            type:Object,
            reuqired:true
        },
        rules:{
            type:Object,
        }
    },
    methods:{
        validate(cb){
            const checkRes = this.$children
            .filter(item => item.prop)
            .map(item => item.validate());

            Promise.all(checkRes)
            .then(()=>cb(true))
            .catch(()=>cb(false));
        }
    }
}
</script>

通用库开发中常用的跨层级传参方法 provide / inject

  1. 祖代设置provide配置项,该项类似于data的用法,但是它的数据是给后代用的,不是给自己用的。
  2. 后代通过inject配置项获取祖代提供的数据。
        inject: ['form'] // 祖代provide中的key值

    通过该方式可以避免第三方库的引入如vuex,如果层级深也不需要通过props的方法进行繁琐的传递。

使用

<template>
    <div>
        <Form :model="model" :rules="rules" ref="myform">
            <FormItem label="用户名" prop="username">
                <Input v-model="model.username" placeholder="输入用户名" @ev="func" />
            </FormItem>
            <FormItem label="密码" prop="password" >
                <Input v-model="model.password" placeholder="输入密码" type="password" @ev="func" />
            </FormItem>
             <FormItem >
                 <button @click="submitForm('myform')">提交</button>
            </FormItem>
        </Form>
    </div>
</template>
<script>
import Input from '@/components/form/Input';
import Form from '@/components/form/Form';
import FormItem from '@/components/form/FormItem';
export default {
    components:{
        Input,
        Form,
        FormItem
    },
    data(){
        return{
            model:{
                username:'',
                password:'',
            },
            rules:{
                username:[{required:true,message:'用户名必填'}],
                password:[{required:true,message:'密码必填'}],
            },
        }
    },
    methods:{
        submitForm(form){
            this.$refs[form].validate(valid=>{
                if(valid){
                    alert('校验通过');
                }else{
                    alert('校验失败');
                }
            })
        }
    }
}
</script> 

问题总结

  1. 为什么数据模型model放在form上?
    为了验证方便,From内的FormItem验证可能有很多,如果都写在FormItem上会很繁琐。
  2. FormItem上为什么要写prop?
    为了判别是对model里的哪部分进行校验,也是通过这个prop去获取规则中的key。

原文地址:https://www.cnblogs.com/juyouji/p/12005509.html

时间: 2024-11-08 23:46:07

vue组件化开发实战 - 实现简易ElementUI的Form表单组件的相关文章

deirective写form表单组件

directive 在使用隔离 scope 的时候,提供了三种方法同隔离之外的地方交互.这三种分别是 @ 绑定一个局部 scope 属性到当前 dom 节点的属性值.结果总是一个字符串,因为 dom 属性是字符串.& 提供一种方式执行一个表达式在父 scope 的上下文中.如果没有指定 attr 名称,则属性名称为相同的本地名称.= 通过 directive 的 attr 属性的值在局部 scope 的属性和父 scope 属性名之间建立双向绑定 但是当我们不使用隔离scope的时候,我们要能够

vue elementUI之Form表单 验证

首先说一下 我在form表单里面遇见的坑: 1.例如我要给后台传的不是对象,而是一个数组,怎么写验证? 2.比如我有四个弹出框,都要做验证,这个时候就要注意了,每一个弹出框的ref都不能给的一样,并且一定要与当前弹框的确定或者保存按钮一一对应,例如:第一个弹框的ref='number',按钮的click比如为xxxxxx('number'),第二个弹出框的ref='number2',对应的按钮>>xxxxxx('number2').如果ref用的都一样,就会出现,点击下一步我没有去做验证,我再

easyUI之Form(表单)组件

一.对于在easyui中使用的组件,具有输入.输出功能的使用<input>标签,其它的使用<div>标签. 二.对于<input>标签,在使用过程,将name属性和id属性同时赋一样的值,否则在传值的过程中有可能出现取不到值的情况. 三.<form>组件方法有两大类:1.submit:进行提交2.load:信息取回.其格式为: $("#selector").form("load",)或$("#selector

JS 组件化开发 系列(一)

JS 组件化开发 系列 作为前端开发,组件化开发是你成长的必经之路.时间的积累逐渐摸索出自己比较好的开发方式. --- zenking (1)实现最简单的组件化: var jdb ={ alert: function(str) { alert(str); }, console:function (str) { console.log(str) } } 这样就是简单的实现 jdb.alert.jdb.console 两个方法. 但是呢? 现在需求改了, 需要实现链式调用. 就是像jquery 一样

Webpack+Vue+ES6 前端组件化开发mobile-multi-page应用实战总结

本文版权归博客园和作者吴双本人共同所有 转载和爬虫请注明原文地址 www.cnblogs.com/tdws 一.写在前面 项目上线有一段时间了,一个基于webpack+vue+ES6的手机端多页面应用.其实说是多页面应用,实际上在webpack中属于四个app,  如果真是做纯单页面,那应该有二三十个页面吧.所以我这里的多页面应用,是分为四个SPA.比如微信最下面,有四个导航,微信,通讯录,发现,我. 那么这四个导航,就是我的四个SPA,配置多个入口即可. 在这里就不说太多代码了,项目结构将会放

vue.js组件化开发实践

前言 公司以往制作一个H5活动,特别是有一定统一结构的活动都要每次用html.css.js滚一次重复的轮子,费时费力.后来接到了一个基于模板的活动发布系统的需求,于是就有了下面的内容. 开始 需求一到,接就是怎么实现,技术选型自然成为了第一个问题.鉴于目前web前端mvvm框架的流行,以及组件化开发方式的出现,决定采用vue进行开发. 这里首先简单说下web前端组件化开发方式的历程: 最早的组件化结构,或者叫做组件化1.0时代,代码结构可能如下: 1 - lib/components/calen

vue中的组件化开发

常常听一些前辈说vue是react的组件化+angular的数据绑定的结合体: 最近刚刚开始使用vue开发项目,我也是在摸索中前进,现在我们来说一说vue的组件化开发. 实际的项目开发,并不像一些文章中的提到的模式,而是如图所示的模式: App.vue是项目的入口.组件实则也是一个以.vue为后缀的文件.我们可以在src\components文件夹下创建一个xxx.vue: 然后在文件中编写可以提出的公共部分的代码为组件.然后在您需要调用该组件的页面,如下图方式调用: 是不是很简单.现在来解释一

Vue组件化开发

一. 通过axios实现数据请求 1. json简介 json是 JavaScript Object Notation 的首字母缩写,单词的意思是javascript对象表示法,这里说的json指的是类似于javascript对象的一种数据格式. json的作用:在不同的系统平台,或不同编程语言之间传递数据. 1.1 json数据的语法 json数据对象类似于JavaScript中的对象,但是它的键对应的值里面是没有函数方法的,值可以是普通变量,不支持undefined,值还可以是数组或者jso

前端框架Vue自学之Vue组件化开发(三)

终极目标:掌握和使用Vue(全家桶:Core+Vue-router+Vuex) 本博客目的:记录Vue学习的进度和心得(Vue组件化开发) 内容:通过官网说明,掌握Vue组件化开发. 正文: Vue组件化开发 一.认识组件化 原文地址:https://www.cnblogs.com/xinkuiwu/p/12037281.html