vue-模拟Element-UI实现form表单

哦哈哈

总文件入口-index.vue

用户使用层
  • 主要是用来定义:
  1. 校验规则
  2. 登陆事件处理(全部校验通过与否调用全局弹窗)

项目结构说明

用户入口文件-inex.vue
<template>
  <div>
    <Vfrom :model="model" :rules="rules" ref="from">
      <Vfromitem label="用户名" prop="username">
        <Vinpnt v-model="model.username"></Vinpnt>
      </Vfromitem>
      <Vfromitem  label="密码" prop="password">
        <Vinpnt v-model="model.password"></Vinpnt>
      </Vfromitem>
      <Vfromitem>
      <button @click="login">
        提交
      </button>
      </Vfromitem>
    </Vfrom>
    {{model}}
  </div>
</template>
<script>
import Vfrom from './vfrom';
import Vfromitem from './vfromitem';
import Vinpnt from './vinput';
export default {
  components:{
    Vfrom,
    Vfromitem,
    Vinpnt
  },
  data() {
    return {
      model:{
        username: 'sss',
        password:''
      },
      rules:{
        username:[
         {required:true, message:'请输入姓名'},
        ],
        password:[
         {required:true, message:'请输入密码'},
        ]
      }
    }
  },
  methods:{
    login(){
      this.$refs.from.validator((isvalid)=>{
        // console.log(isvalid, 'isvalid')
        // if(isvalid) {
        //   console.log('验证通过')
        // } else {
        //   console.log('验证失败')
        // }
        // this.$notice({
        //   title:'校验结果',
        //   message:isvalid?'验证通过':'验证失败',
        //   duration:2000
        // }).show()
        // console.log(isvalid,'isvalid')
          this.$notice({
            title: '校验结果',
            message: isvalid ? '请求登录' : '校验失败',
            duration: 2000
          }).show()
      })
    }
  }
}
</script>
<style>

</style>
提交按钮<button @click="login">登录</button>
登陆事件处理(全部校验通过与否调用全局弹窗)
全局校验-From.vue
  • 全局的校验,调用每个自组建的校验结果
<template>
  <div>
    <slot></slot>
  </div>
</template>
<script>
export default {
  name:'vfrom',
  provide(){
    return{
      from: this
    }
  },
  props:{
    model:{
      type:Object,
      requiree:true
    },
    rules:Object
  },
  methods:{
    validator:function(cb){
      const tasks =this.$children
      .filter(item=> item.prop)
      .map(item=> item.validator())
      Promise.all(tasks)
      .then(()=>{cb(true)})
      .catch(()=>{cb(false)})
    }
  }
}
</script>
<style>

</style>
单一input内容校验-FromItem.vue
  1. 获取校验规则
  2. 获取当前的值
  3. import Schema from "async-validator"; 引入校验模块
  4. 创建校验规则
  5. 执行校验
  6. if(erro){thi.message='错误信息'}else{this.messgae=''}
<template>
  <div>
    <label :for="prop">{{label}}</label>
    <slot></slot>
    <span v-if="error">{{error}}</span>
  </div>
</template>
<script>
import Schema from 'async-validator';
export default {
  name: 'vfromitem',
  inject:['from'],
  props:{
    // label="用户名" prop="username"
    label:{
      default:'',
      type:String
    },
    prop:{
      default:'',
      type:String
    }
  },
  data() {
    return {
      error:''
    }
  },
  mounted(){
    this.$on('validator', ()=>{
      this.validator()
    })
  },
  methods:{
    validator:function(){
      // console.log('进来了吗')
      // 获取校验规则
       const rules =this.from.rules[this.prop]
      // 获取当前的值
      const value =this.from.model[this.prop]
      // 创造校验器
      const schema= new Schema({
        [this.prop]:rules
      })
      // console.log({[this.prop]:rules}, '[this.prop]:rules')
      return schema.validate({
        [this.prop]:value
      },errors=>{
        // console.log(errors,'sdsds')
          if(errors){
            this.error=errors[0].message
          }else{
            this.error=''
          }
      })
    }
  }
}
</script>
<style>
 span{
   color:red;
   font-size: 10px;
 }
</style>
type:text填写信息-Input.vue
  1. 改变value值
  2. 调用父组建校验方法
<template>
  <div>
    <input :type="type" :value="value" @input="Oninput">
  </div>
</template>
<script>
export default {
  name:'vinput',
  props:{
    type:{
      type:String,
      default:'text'
    },
    value:{
      type:String,
      default:''
    }
  },
  methods:{
    Oninput:function (e) { 
      this.$emit('input',e.target.value)
      this.$parent.$emit('validator')
     }
  }
}
</script>
<style>

</style>
通知全局组建-Vue.prototype.$notice
(弹窗类组建封装)-全局注册组建
  1. 在vue定义方法$notice
  2. 方法内部调用create方法
  3. 传入组建和props
使用new Vue 生成组建挂在在dome上;
思路:
  1. 创建dom元素
  2. 将dom元素放在body里面
  3. 显示后,消失操作, 删除dom元素以及销毁实例
在new Vue中,redner中的参数 h
  h: 是一个`createElement函数` 可以返回一个虚拟dome
调用new Vue().$mount()
`$mount()`的目的 :将vdome -> dom
vm
 `vm` :  new Vue()构造函数
vm.$el
 真实的dom元素
vm.$children
[Vuecomponent]
const comp = vm.$children[0] comp.remove=()=>{}
给vue组建定义删除组建的方法
 使用new Vue 生成组建挂在在dome上;

/utils/create-构造组件实例
import Vue from 'vue'  
  
// 实现一个create方法,能够创建指定组件实例  
// 并将其挂载至body上  
// Component是组件配置对象  
export default function create(Component, props) {  
// 怎么创建组件实例  
// 方案1:可以通过Vue.extend(Component)获取组件构造函数  
// const Ctor = Vue.extend(Component)  
// const comp = new Ctor()  
  
// 方案2:借助Vue构造组件实例  
const vm = new Vue({  
render(h) {  
// h是createElement函数,可以返回vdom  
return h(Component, {props})  
}  
}).$mount() // $mount()目标:将vdom=》dom  
  
// 手动追加dom  
document.body.appendChild(vm.$el)  
  
const comp = vm.$children[0]  
  
// 淘汰逻辑  
comp.remove = () => {  
document.body.removeChild(vm.$el)  
// 执行 remove 方法时,执行 $destroy 销毁实例  
comp.$destroy()  
}  
  
return comp  
}
组建内容-/components/Notice.vue
<template>  
<div class="box" v-if="isShow"> //ishow 是用来判断是否展示  
<h3>{{title}}</h3> //传入进来的参数的title  
<p class="box-content">{{message}}</p> //提示信息  
</div>  
</template>
<script>  
export default {  
    props: {  
        title: { // 弹窗的标题  
            type: String,  
            default: ""  
        },  
        message: { // 展示内容  
            type: String,  
            default: ""  
        },  
        duration: { // 延迟的关闭的时间  
            type: Number,  
            default: 1000  
        }  
},  
data() {  
    return {  
        isShow: false // 默认组建为隐藏状态不限时  
    };  
},  
methods: {  
    show() {   
        // 调用show 方法显示组建时,先将内部data定义的isShow改为true  
        // 展示之后,执行hide 进行隐藏。使用setTimeout;隐藏的时间将有传进来的参数进行调动  
        this.isShow = true;  
        // 当执行show方法之后,执行hide方法  
        setTimeout(this.hide, this.duration);  
        },  
        hide() {  
            this.isShow = false;  
            this.remove();  
        }  
    }  
};  
</script>
<style>  
.box {  
position: fixed;  
width: 100%;  
top: 16px;  
left: 0;  
text-align: center;  
pointer-events: none;  
background-color: #fff;  
border: grey 3px solid;  
box-sizing: border-box;  
}  
.box-content {  
width: 200px;  
margin: 10px auto;  
font-size: 14px;   
padding: 8px 16px;  
background: #fff;  
border-radius: 3px;  
margin-bottom: 8px;  
}  
</style>

学习资源

思维导图: https://www.processon.com/vie...
github:https://github.com/speak44/Vu...

阅读 1.7k

我相信:发光不是太阳的权利,每个人都可以。

17 声望
6 粉丝
0 条评论
你知道吗?

我相信:发光不是太阳的权利,每个人都可以。

17 声望
6 粉丝
宣传栏