实现自己的组件库<4>. 仿elementui,封装 radio组件,radiogroup组件,checkbox组件,checkbox-group组件,form组件和form-item组件

目录

封装radio组件

封装单选框组radio-group

封装checkbox组件和checkbox-group组件

form组件和form-item组件


封装radio组件

radio.vue里初步模版:

​​​​​​​

<template>
    <label class="miao-radio" >
        <span class="miao-radio_input">
            <span class="miao-radio_inner"></span>
            <input type="radio" class="miao-radio_original">
        </span>
        <span class="miao-radio_label" type="radio">
            我说label
        </span>
    </label>
</template>
<style lang="scss" scoped>
.miao-radio {
    color: #606266;
    font-weight: 500;
    line-height: 1;
    position: relative;
    cursor: pointer;
    display: inline-block;
    white-space: nowrap;
    outline: none;
    font-size: 14px;
    margin-right: 30px;
    -moz-user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;

    .miao-radio_input {
        white-space: nowrap;
        cursor: pointer;
        outline: none;
        display: inline-block;
        line-height: 1;
        position: relative;
        vertical-align: middle;

        .miao-radio_inner {
            border: 1px solid #dcdfe6;
            border-radius: 100%;
            width: 14px;
            height: 14px;
            background-color: #fff;
            position: relative;
            cursor: pointer;
            display: inline-block;
            box-sizing: border-box;

            &:after {
                width: 4px;
                height: 4px;
                border-radius: 100%;
                background-color: #fff;
                content: "";
                position: absolute;
                left: 50%;
                top: 50%;
                transform: translate(-50%, -50%) scale(0);
                transition: transform .15s ease-in;
            }
        }

        .miao-radio_original {
            opacity: 0;
            outline: none;
            position: absolute;
            z-index: -1;
            top: 0;
            left: 0px;
            right: 0;
            bottom: 0;
            margin: 0;
        }
    }

    .miao-radio_label {
        font-size: 14px;
        padding-left: 10px;
        ;
    }
}

// 选中的样式
.miao-radio.is-checked {
    .miao-radio_input {
        .miao-radio_inner {
            border-color: #409eff;
            background-color: #409eff;

            &:after {
                transform: translate(-50%, -50%) scale(1);
            }
        }
    }

    .miao-radio_label {
        color: #409eff;
    }
}
</style>

先把input_radio隐藏

首先设置v-model,name,label属性,需要传参数,

在radio.vue里设置:

label:{
        type:[String, Number, Boolean],
        default:''
    },
    value:null,

    // v-model给什么无所谓,最终需要得到的是label的值,有v-model肯定会接收到value
    // 作为表单元素可能传name
    name:{
        type:String,
        default:''

    },

 v-model给什么无所谓,最终需要得到的是label的值,有v-model肯定会接收到value

app.vue里

<miao-radio label="1" v-model="gender">男</miao-radio>
    <!-- 用来指定radio的值 -->
    <miao-radio label="0" v-model="gender">女</miao-radio>

在radio.vue里肯定不能写固定的,用插槽替代,让男和女两个出现在界面里

如果没写字,一般会把label内容显示

<template v-if="!$slots.default">{{ label }}</template>

由于父组件传入数据不能修改,在radio里绑定的v-model绑定的数据应该是重写定义的

但是该数据取决于外部传入的value值还得能修改这个数据

通过计算属性:

computed: {
	model: {
get(){
	return this.value
},
set(value){
//触发父组件给当前组件注册的input事件
this.$emit('input',value)
}

	}
}

修改template里第一句增加动态类

<label class="miao-radio" :class="{'is-checked': label===value}">

封装单选框组radio-group

这样不用给每个radio绑定变量

this.$parent找到组件的父组件,找到他找到value值从而触发input事件

但是有风险--

引出provide与inject:祖先给子孙组件依赖

在父组件用provide提供一个值,在任何孙组件里用inject获取值

radio-group.vue里:

provide(){
    //提供一个对象
return {
    RadioGroup: this
}

这是把自己提供出去了

radio.vue里:

inject:{
    RadioGroup
},

能拿到group就能访问他的值

然后发现被radiogroup包裹的不能获取值,因为可能从radiogroup.value里获取

因此修改computed为:

computed: {
        model: {
            get() {
                return this.iGroup? this.RadioGroup.value : this.value
            },
            set(value) {
                
                this.iGroup ? this.RadioGroup.$emit('input', value) : this.$emit('input', value)
            }
        },
        iGroup(){
            //用于判断radio是否被radio group包裹,两个感叹号表示改成布尔值
            return !!this.RadioGroup

        }


    }

最后修改radio.vue里:

 <label class="miao-radio" :class="{'is-checked': label===model}">

封装checkbox组件和checkbox-group组件

首先checkbox里同radio:

<slot></slot>
            <template v-if="!$slots.default">{{ label }}</template>

没值显示label

同样传参数:

value: {
      type: Boolean,
      default: false
    },
    label: {
      type: String,
      default: ''
    },
    name: {
      type: String,
      default: ''
    }

同样通过provide和inject孙子和祖先通信:

可以把inject理解为加强版的props,不仅能接受父组件还能接受爷爷组件

checkbox.vue里:

inject: {
    CheckboxGroup: {
      default: ''
    }
  },

checkbox-group.vue里

provide () {
    return {
      CheckboxGroup: this
    }
  },

不同点在于,如果在checkbox-group里说明多个checkbox,则需要指明传参是数组:

props: {
    value: {
      type: Array
    }
  }

同radio和radiogroup一样,添加计算属性

model: {
      get () {
        return this.isGroup ? this.CheckboxGroup.value : this.value
      },
      set (value) {
        this.isGroup ? this.CheckboxGroup.$emit('input', value) : this.$emit('input', value)
        console.log(value)
      }
    },
    isGroup () {
      return !!this.CheckboxGroup
    },

如果是多个box一起用,value就有用了,因为选中的是value,这个value就是label

checkbox.vue里,新添加value="label"

<span class="miao-checkbox_input">
            <span class="miao-checkbox_inner"></span>
            <input type="checkbox" 
            class="miao-checkbox_original" 
            :name="name" 
            v-model="model"
            value="label"
            >
        </span>

有group时候有value="label"

然后还缺一个选中状态

ischecked() {
        //如果是group包裹,判断label是否在model中
        //如果没有group包裹,直接使用modle
        return this.isgroup ? this.model.includes(this.label) : this.model
    }

模版里更换为:

 <label class="miao-checkbox" :class="{'is-checked':ischecked}">

form组件和form-item组件

通过form和form-item两个组件将前面的组件包起来:

form.vue:

<template>
  <div class="miao-form">
    <slot></slot>
  </div>
</template>

<script>
export default {
name:'miaoForm',
props:{
    model: {
        type: Object,
        required:true
        // 用form必须传入model
    }
}
}

form-item.vue:

<template>
    <div class="miao-form-item">
        <label class="miao-form-item_label">{{ label }}</label>
        <div class="miao-form-item_content">
            <slot></slot>
        </div>
    </div>
</template>

app.vue

<template>
  <div id="app">

    <miao-form :model="model">
      <!-- :model用来收集所有的值 -->
      <miao-form-item label="用户名">
        <miao-input placeholder="请输入用户名" v-model="model.username"></miao-input>
      </miao-form-item>

      <miao-form-item label="选择">
        <miao-switch v-model="model.active"></miao-switch>
      </miao-form-item>

    </miao-form>

  </div>

</template>

将form组件传下去:

provide (){
return {
  Form:this
 }
}

接受form:

<label class="miao-form-item_label" :style="{width: this.Form.labelWidth}">{{ label }}</label>
inject:['Form']

具体代码详见: 

GitHub - Alicca-miao/component-library-vue-ui-Contribute to Alicca-miao/component-library-vue-ui- development by creating an account on GitHub.icon-default.png?t=N7T8https://github.com/Alicca-miao/component-library-vue-ui-

  • 25
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值