总文件入口-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...