input输入框

功能分析

1 .可以使用v-model实现数据的双向绑定,组件里面绑定v-model
2 .支持style改变输入框的宽度,如果小于某一个值的话,当输入内容特别多的时候,上面开启一个显示输入内容的信息框
3 .加一个清空按钮,可以添加图标-search输入框,或者是一般人物信息的输入框
4 .可以变成textarea
5 .前面和后面都有自动补充内容的选项,比如163邮箱,或者输入网站的时候
6 .下方提供历史记录,推荐搜索词汇
7 .如果没有选择历史记录,当玩家输入的时候,给自动补全
8 .玩家返回的信息要做本地缓存,这样再次请求的时候直接返回缓存(适用于特定业务)
9 .输入框可以设置只读
10 .最大输入长度
11 .对输入的内容进行正则验证 加在那个的onBlur事件下面,取消焦点的时候进行验证
12 .还要提供事件绑定,给组件
13 .事件触发的代码
14 .icon的显示要变成slot方式。用slot的地方这么多
15 .长度限制
16 .并不需要限制输入数字的类型,不知道之前为什么要加这个
17 .密码框要显示隐藏
18 .textarea根据输入自适应高度
19 .复合输入框

1 .通过前置和后置的slot可以实现复合型的输入框
2 .也就是前后各有一个下拉选择框。进行一些自动补全
3 .看源码实现这个dom结构,这种的都是必须slot传入整个组件选择组件。
4 .依照golang的设计哲学,我们需要的而是组合而不是继承,那写组件的实质也是希望组合这个东西
5 .所以我们完全可以在原来的select组件上面进行扩展,让他多一个左边不全的样式,右边补全的样式。这样写源码的时候其实不用考虑这么多,其实使用的时候是分开使用的。然后把前面不全和后面不全的值传到这个组件里面,统一的输出都是走这个组件
6 .既然是写组件,为什么不在拆分的更彻底一点呢。
7 .这样的话slot的插槽其实只是用来添加icon的一个用处了。。
9 .之前的还是会和notice组件进行联动,比如各种弹得提示,或者其他的辅助提示
10 .在进一步拆分,icon是否能拆分。。
11 .发现的bug

20 .结合Poptip组件,实现一个数值输入框,方便内容超长时的全景展现

handleBlur () {
                this.$emit('on-blur');
                this.$dispatch('on-form-blur', this.value);
            },
//dispatch了解一下

最核心的还是组件里面加上v-model操作

1 .这个竟然都没有实现
2 .其实核心就是当使用组件的时候使用v-model 进行操作的话
3 .父对子

1 .子组件自动接收这个参数,上面v-model所绑定的数据如果外面改的话,里面也会改变
value:{
            type:[String,Number],
            default:function(){
                return null
            }
        }
//可以做一些清空操做

4 .子对父

1 .this.$emit('input',this.inputValue)
//当需要把里面修改的数据传递到外面的时候,就走这个逻辑

Input组件使用的时候传入slot插槽,不能正确触发里面组件的input事件

1 .使用的代码

<InputP size="small" v-model="value">
        777
</InputP>
//将777作为默认插槽传入,其实是想传一些图标组件

2 .代码

<template>
    <div :class="wrapClasses">
        <div v-if="type!=='textarea'">
            <div v-if="computedPreappend" class="li-input-preappend">
                <slot name="preappend"></slot>
            </div>
            <input  
                    ref="input"
                    :id="elementId"
                    :autocomplete="autocomplete"
                    :spellcheck="spellcheck"
                    :class="inputClass"
                    :placeholder="placeholder"
                    :disabled="disabled"
                    :maxlength="maxlength"
                    :readonly="readonly"
                    :value="currentValue"
                    :number="number"
                    :name="name"
                    :autofocus="autofocus"
                    :type="currentType"
                    @keyup.enter="handleEnter"
                    @keyup="handleKeyup"
                    @keypress="handleKeypress"
                    @keydown="handleKeydown"
                    @focus="handleFocus"
                    @blur="handleBlur"
                    @input="handleInput"
                    @change="handleChange"
                    >
            <div v-if="computedAppend" class="li-input-append">
                <span v-if="showWordLimit">{{textLength/upperLimit}}</span>
                <slot name="append"></slot>
            </div>
            <slot>default</slot>
        </div>
        <div v-else>
            <textarea></textarea>
            <span v-if="showWordLimit"></span>
        </div>
        
    </div>    
</template>
<script>
const pre ="li-input"
export default {
    name:"Input",
    props:{
        type:{
            validator(value){
                return ["text","textarea","password","url","email","data","number","tel"].includes(value)
            },
            default:"text",
        },
        value:{
            type:[String,Number],
            default:'',
        },
        size:{
            validator(value){
                return ["small","large","default"].includes(value)
            },
            default:"default"
        },
        placeholder:{
            type:String,
            default:"",
        },
        maxlength:{
            type:[Number,String]
        },
        disabled:{
            type:Boolean,
            default:false,
        },
        autosize:{
            type:[Boolean,Object],
            default:false,
        },
        // textarea下有效,自适应高度
        rows:{
            type:Number,
            default:2,
        },
        readonly:{
            type:Boolean,
            default:false,
        },
        // 限制只读
        name:{
            type:String,
        },
        Number:{
            type:Boolean,
            default:false,
        },
        autofocus:{
            type:Boolean,
            default:false,
        },
        autocomplete:{
            type:String,
            default:"off",
        },
        elementId:{
            type:String,
        },
        wrap:{
            validator(value){
                return ["hadr","soft"].includes(value)
            }
        },
        showWordLimit:{
            type:Boolean,
            default:false,
        },
        password:{
            type:Boolean,
            default:false,
        },
        spellcheck:{
            type:String,
            default:"spellcheck"
        }

    },
    data(){
        return {
            currentValue:this.value,
            showPassword:false,
            number:''
        }
    },
    computed:{
        wrapClasses(){
            return [
                `${pre}-wrapper`,
                {
                    // [`${pre}-wrapper-${this.size}`]:!!this.size,
                    [`${pre}-type-${this.type}`]:this.type,
                }
            ]
            // 父级样式
        },
        inputClass(){
            return [
                `${pre}`,
                {
                    [`${pre}-${this.size}`]:this.size,
                    [`${pre}-disabled`]:this.disabled,
                }
            ]
            // input样式
            // 决定大小
        },
        currentType(){
            let type=this.type
            if(type==="password"&&this.password&&this.showPassword){
                type="text"
            }
            return type
        },
        computedAppend(){
            let state=false;
            // if(this.type!=="textarea"){
            //     if(this.$slots.append!==undefined){
            //         state=true
            //     }else{
            //         state=false
            //     }
            // }
            // console.log(state)
            // return state;
            return true
        },
        computedPreappend(){
            let state=false;
            // if(this.type!=="textarea"){
            //     if(this.$slots.preappend!==undefined){
            //         state=true
            //     }else{
            //         state=false
            //     }
            // }
            // return state
            return true
        },
        textLength(){
            if (typeof this.value=="number"){
                return String(this.value).length
            }
            return (this.value||"").length
        },
        upperLimit(){
            return this.maxlength
        }

    },
    methods:{
        handleEnter(event){
            this.$emit("on-enter",event)

            if(this.search) this.$emit("on-search",this.currentType)
        },
        handleKeydown(event){
            this.$emit("on-keydown",event)
        },
        handleKeypress(event){
            this.$emit("on-keypress",event)
        },
        handleKeyup(event){
            this.$emit("on-keyup",event)
        },
        handleFocus(event){
            this.$emit("on-focus",event)
        },
        handleBlur(event){
            this.$emit("on-blur",event)
        },
        handleInput(event){
            let value=event.target.value
            this.$emit("input",value)
//这样使用的时候这里的事件触发是有点问题滴
            console.log("handleInput",event.target.value)
        },
        handleChange(event){
            console.log('handle change')
            this.$emit("on-input-change",event)
        },
        setCurrentValue(value){
            if(value==this.currentType)return;
            this.$nextTick(()=>{
                this.resizeTextarea();
            })
            this.currentValue=value
        },
        handleComposition(event){
            console.log("handleComposition")
        }

    }
    ,
    watch:{
        value(o,n){
            console.log(n)
        }
    }
}
</script>
<style lang="less" src="./inputP.less">

</style>

1 .解决方法,在里面的input部分加一个内部的v-model属性,然后最后输出的时候操作整体返回这个属性
2 .层级关系是怎么决定的,为什么他按照顺序,后面的样式就能覆盖前面的样式,我这就不行。样式表中,谁的在后面就用谁的,并不是class里面的排序
3 .v-else,v-else-if必须紧紧的连在一起,中间不能有任何dom元素
4 .他之前的会包括很多type类型,数字,电话号码,邮箱,日期,但是很多都是没有效果的。这里统一改成密码,数字,字符串这三个类型,别的都写各自的组件吧

原来写的input组件的优点

1 .第一次就是看了下他怎么写,然后就自己写了。走出了自己的一条路,联系业务
2 .第二次一行一行的看源码。然后在写的时候需要加一些东西
3 .数字组件的时候:限制大小,限制小数点
4 .提示语太长还会省略.升级版就是上方有提示组件的那个
5 .input的事件还会根据组件的类型进行判断,结合notice组件进行表格填写的提示
6 .

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容