vue表单组件封装

栏目 Vue

你封装过最复杂最牛逼的组件是啥?

要讨论封装过最复杂最牛逼的组件,我们得先破题,它问的是组件吗,不,它问的是封装的思路。

这里尝试跟着技术大神的思路,封装几个组件,懂得自然懂。

这里是 element-uiform部分应用代码:

<el-form :model="model" :rules="rules" ref="loginForm">
  <el-form-item label="用户名" prop="username">
    <el-input v-model="model.username" autocomplete="off"></el-input>
  </el-form-item>
  <el-form-item label="确认密码" prop="password">
    <el-input type="password" v-model="model.password" autocomplete="off"></el-input>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="submitForm('loginForm')">提交</el-button>
  </el-form-item>
</el-form>
  • el-form :model rules ref
  • el-form-item label prop
  • el-input v-model autocomplete tpye

el-input #

先看 el-input

<el-input v-model="model.username"  autocomplete="off"></el-input>
<el-input type="password" v-model="model.password" autocomplete="off"></el-input>

父组件可传 type v-model autocomplete

v-model #

都说 v-model是语法糖: input事件触发事件,拿到输入的值。对外emit input事件。 组件本身再监听 value属性,展示位,值是刚才触发的input给的值。

但不仅仅语法糖,我们观察输入中文,打拼音时候是不触发事件的,等到字选中才展示出来。

请看我的实例,右边框输入拼音,左边自动就出现了字母,如果是 v-model 就会等到选完字才出现。这里就不演示了。

补充一个你可能不知道的: compositionstart compositionend 这两个事件就是语言输入开始和结束监听的变化。

我们监听 input compositionstart compositionend 这三个事件,借助 e.target.composing 就能组合文字状态,start时候composing设置为true,end时候设置false,然后赋值input

<template>
    <div>
        <input :type="type" :value="value" @input="onInput">
    </div>
</template>
<script>
    export default {
        props:{
            value:{
                type:String,
                default:''
            },
            type:{
                type:String,
                default:'text'
            }
        },
        methods: {
            onInput(e) {
                let value = e.target.value;
                this.$emit('input',value);
                this.$parent.$emit('validate')
            }
        },
    }
</script>

不算复杂。讲清楚了 v-model 语法糖的实现。

el-form-item #

<k-form-item label="用户名" prop="username">
  <k-input v-model="model.username"></k-input>
</k-form-item>

组件本身可以传入其他内容,那就得用 slot占位。 props可使用 label prop

<div>
    <label for="">{{label}}</label>
    <div>
        <slot></slot>
        <p v-if="errStatus">{{errMessage}}</p>
    </div>
</div>

js部分,props没啥特点就label和prop