vue -简版form

241 阅读1分钟

基础知识

组件通信方法

props --父子
$emit/$on --子父自定义事件 派发/监听事件
evuent bus --事件总线
vuex

$parent $children --有强耦合性 减少使用
$root
$ref
provide/inject
非prop特性: $attrs $listeners

兄弟节点可以通过祖辈搭桥
//brother1
this.$parent.$emit('foo')
//brother2
this.$parent.$on('foo',handle)

$attrs $listeners 属性透传

//v-bind v-on 可以将对象直接展开
<grandson v-bind="$attrs" v-on="$listeners" />

provide/inject 隔代传参

//grandpa
export default{
  provide(){
      return {
          foo:'this is foo',
          grandpa:this
      }
  }
}


//grandson
export default{
    inject:['foo','grandpa'],
    inject:{
        'alias':{}
    }
}

插槽 内容分发

匿名插槽

//comp1 子组件占位符
<div>
    <slot></slot>
</div>
//parent
<comp>helllo</comp>

具名插槽

//comp1 子组件占位符
<div>
    <slot></slot>
    <slot name='content'></slot>
</div>

//parent
<comp>
 <template v-slot:default>默认不带名字的</template>
 <template v-slot:content>内容</template>
</comp>

作用域插槽

//comp1 子组件占位符
<div>
    <slot :foo="foo  "></slot> //被替换的对象
</div>

//parent
//有一部分的数据来自于子组件 v-slot为作用域上下文对象
<comp>
 <template v-slot:default=“slotProps”> //函数(参数)
     子组件数据 {{slotProps.foo}}
 </template>
 
</comp>

通用表单组件

实现内容:收集和校验数据

index页面

<template>
 <MForm :model="model" :rules="rules" ref="loginForm">
   <MFormItem label="用户名:" prop="username">
    <MInput v-model="model.username" placeholder="请输入"</MInput>
   </MFormItem>
   <MFormItem>
       <button @click="onLogin">登录</button>
   </MFormItem>
 </MForm>
    
</template>
<script>
    import MInput from './MInput'
    import MFormItem from './MFormItem'
    import MForm from './MForm'
     
    export default{
         components:{
             MForm,
             MFormItem,
             MInput
         },
         data(){
             return {
                 model:{
                     username:'',
                     rules:{
                         username:[{
                             required:true,message:"用户名必填"
                         }]
                     }
                 }
             }
         },
         methods:{
             onLogin(){
                 this.$refs.loginForm.validate(isValid=>{
                     if(isValid){
                         //login
                     }else{
                         console.log('失败!')
                     }
                 })
             }
         }
    }
</script>
[input组件] 双向绑定组件
<template>
    <div>
       <input type="text" :value="value" @input="onInput"
       v-bind="$attrs"
       />
    </div>
</template>

<script>
 inheritAttrs:false,//不要将属性赋值到根组件上
  export default{
      props:{
          value:{
              type:String,
              default:''
          }
      },
      methods:{
          onInput(e){
              this.$emit('input',e.target.value)
              //通知校验
              // this.dispatch('el-form-item','validate') //源码的方法 不断找parent,根据组件名字找
              this.$parent.$emit('validate')
          }
      }

  }
</script>

<style></style>
[my-form-item]检验执行、显示错误
<template>
   <div>
       <label v-if="label">{{label}}</label>
       <slot></slot>
       <p v-if="error">{{error}}</p>
        <p>{{form.rules[prop]}}</p>
   </div>
</template>
<script>
    import Validator from 'async-validator'
    export default{
        inject:['form'],
         props:{
            label:{
                type:String,
                default:''
            },
            prop:String
         },
         data(){
             return {
                 error:'
             }
         },
         mounted(){
             this.$on('validate',()=>{
                 this.validate()
             })
         },
         methods:{
             validate(){
                 //检验库 async-validator
                 //获取规则和值
                 const rules = this.form.rules[this.prop]
                 const value = this.form.model[this.prop]
                 //校验器 
                 //键值对 对什么检验
                 const validator = new Validator({[this.prop]:rules})
                 //return promise
                 return validator.validate({[this.prop]:value},(errors)=>{
                     if(errors){
                         this.error = errors[0].message
                     }else{
                         this.error=''
                     }
                 })
             }
         }
         
    }
</script>
[my-form]  model、rules
<template>
     <div>
         <slot></slot>
     </div>
</template>
<script>
    export default{
         components:{
            
         },
         props:{
             model:{
                 type:Object,
                 required:true
             },
             rules:Object
         },
         //隔代传下去 到form item
         provide(){
             return{
                 form:this
             }
         },
         data(){
             return {
                 
             }
         },
         methods:{
             validate(cb){
             //遍历所有有prop属性的item校验方法
                 const promises=this.$children.filter(item=>item.prop)
                 .map(item=>item.validate())
             //全部通过则通过
                 Promise.all(promises).then(()=>cb(true)).catch(()=>cb(false))
             }
         }
    }
</script>