600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 使用Vue封装一个radio组件 RadioGroup组件

使用Vue封装一个radio组件 RadioGroup组件

时间:2022-09-01 18:14:54

相关推荐

使用Vue封装一个radio组件 RadioGroup组件

一、封装radio组件

radio组件基本框架和样式:

<template><label class="one-radio" :class="{'is-checked':label == value}"><span class="one-radio_input"><!-- <span class="one-radio_inner"> --><input type="radio" class="one-radio_label" :value="label" :name="name"v-model="model"><!-- </span> --></span><span class="one-radio_label"><slot></slot><!-- 如果没有传值,就把label作为文本显示 --><template v-if="!$slots.default">{{label}}</template></span></label></template><script>// 定义一个value属性,value值是接收到的labelexport default {name: 'oneRadio',data(){return{}},props:{label: {type: String,default:'0'},value: {type: String,default: ''},name :{type: String,default: ''}},computed: {// 如果用双向绑定一个计算属性,必须提供一个get和set;需要写成一个对象model:{get(){// model的值是父组件传过来的valueconsole.log('value');return this.value},set(value){// 触发父组件给当前组件注册的input事件this.$emit('input',value)}}}}</script><style lang="scss" scoped>.one-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;.one-radio_input{white-space: nowrap;cursor: pointer;outline: none;display: inline-block;line-height: 1;position: relative;vertical-align: middle;.one-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;}}.one-radio_original{opacity: 0;outline: none;position: absolute;z-index: -1;top: 0;left: 0px;right: 0;bottom: 0;margin: 0;}}.one-radio_label{font-size: 14px;padding-left: 10px;;}}// 选中的样式.one-radio.is-checked{.one-radio_input{.one-radio_inner{border-color: #409eff;background-color: #409eff;&:after{transform: translate(-50%,-50%) scale(1);}}}.one-radio_label{color:#409eff;}}</style>

radio组件的数据双向绑定:

需要父组件传递label值和value值,其中value值使用v-model来绑定。

<one-radiov-model="gender" label="0">男</one-radio><one-radiov-model="gender" label="1">女</one-radio>

子组件接收数据后,对数据进行处理:

①当radio组件被点击时,绑定的数据应该变为该组件的label值,因此我们将子组件中的input标签的value属性绑定为传入的label值;并声明一个计算属性model双向绑定到input组件上(model通过get获取值–>父组件传过来的value,通过set方法将值回调给父组件)。

②改变样式:

当我们在点击radio组件时,让被选中的组件添加选中样式,可以通过label和value的比较来判断,:class="{'is-checked':label == value}",如果相同,则显示选中样式。

二、封装RadioGroup组件

因为存在两种①radio不被RadioGroup包裹和②radio被RadioGroup包裹的情况。第二种情况,如果radio被RadioGroup包裹时,我们在上面封装的组件就不能用了。因此,我们需要考虑radio是否被RadioGroup所包裹。

为了知晓radio是否被包裹,可以使用provide方法(在祖先组件中负责向子孙组件发送数据)和inject(在子孙组件中负责接收来自祖先组件的数据)。

在redio组件中,添加inject 来接收传入的值;

而且,我们想要拿到value值,并一定是从父组件中拿到(使用this.value),有可能是从祖先组件中拿到value值,因此,我们在computed计算属性中添加一个isGroup方法,用于判断是否radio被radioGroup所包裹。

当radio被radioGroup包裹时,不能用this.value,只能用this.radioGroup.value,因此,return this.isGroup ? this.RadioGroup.value : this.value;,根据isGroup来决定如何获取value的值,修改值set中相应地也要进行修改,this.isGroup ? this.RadioGroup.$emit('input',value) : this.$emit('input',value)

<template><label class="one-radio" :class="{'is-checked':label == value}"><span class="one-radio_input"><!-- <span class="one-radio_inner"> --><input type="radio" class="one-radio_label" :value="label" :name="name"v-model="model"><!-- </span> --></span><span class="one-radio_label"><slot></slot><!-- 如果没有传值,就把label作为文本显示 --><template v-if="!$slots.default">{{label}}</template></span></label></template><script>// 定义一个value属性,value值是接收到的labelexport default {name: 'oneRadio',data(){return{}},inject: {RadioGroup:{default: ''}},computed: {// 如果用双向绑定一个计算属性,必须提供一个get和set;需要写成一个对象model:{get(){// model的值是父组件传过来的value// return this.valuereturn this.isGroup ? this.RadioGroup.value : this.value;},set(value){// 触发祖先组件RadioGroup给当前组件注册的input事件//this.$emit('input',value)this.isGroup ? this.RadioGroup.$emit('input',value) : this.$emit('input',value)}},isGroup(){// 用于判断radio是否被radioGroup所包裹(使用2个感叹号,将其改为布尔值)return !!this.RadioGroup}}}</script>

最终效果:

这里附上 完整代码 radioGroup.vue:

<template><div class="one-radio-group"><slot></slot></div></template><script>export default {name:'HmRadioGroup',provide(){return {RadioGroup: this}},props:{value: null},}</script><style></style>

radio.vue

<template><label class="one-radio" :class="{'is-checked':label === model}"><span class="one-radio_input"><!-- <span class="one-radio_inner"> --><input type="radio" class="one-radio_label" :value="label" :name="name"v-model="model"><!-- </span> --></span><span class="one-radio_label"><slot></slot><!-- 如果没有传值,就把label作为文本显示 --><template v-if="!$slots.default">{{label}}</template></span></label></template><script>// 定义一个value属性,value值是接收到的labelexport default {name: 'oneRadio',data(){return{}},inject: {RadioGroup:{default: ''}},props:{label: {type: String,default:'0'},value: {type: String,default: ''},name :{type: String,default: ''}},computed: {// 如果用双向绑定一个计算属性,必须提供一个get和set;需要写成一个对象model:{get(){// model的值是父组件传过来的valueconsole.log('value');// return this.valuereturn this.isGroup ? this.RadioGroup.value: this.value},set(value){// 触发父组件给当前组件注册的input事件// this.$emit('input',value)this.isGroup ? this.RadioGroup.$emit('input',value) : this.$emit('input',value)}},isGroup(){// 用于判断radio是否被radioGroup所包裹(使用2个感叹号,将其改为布尔值)return !!this.RadioGroup}}}</script><style lang="scss" scoped>.one-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;.one-radio_input{white-space: nowrap;cursor: pointer;outline: none;display: inline-block;line-height: 1;position: relative;vertical-align: middle;.one-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;}}.one-radio_original{opacity: 0;outline: none;position: absolute;z-index: -1;top: 0;left: 0px;right: 0;bottom: 0;margin: 0;}}.one-radio_label{font-size: 14px;padding-left: 10px;;}}// 选中的样式.one-radio.is-checked{.one-radio_input{.one-radio_inner{border-color: #409eff;background-color: #409eff;&:after{transform: translate(-50%,-50%) scale(1);}}}.one-radio_label{color:#409eff;}}</style>

App.vue 中使用

<template><div id="app"><one-radiov-model="gender" label="0">男</one-radio><one-radiov-model="gender" label="1">女</one-radio><hm-radio-group v-model="gender"><one-radio label="0">男</one-radio><one-radio label="1">女</one-radio></hm-radio-group></div></template><script>export default {name: 'App',components: {},data(){return {money: 100,visible: false,active: true,password: '',swFlag: false,swFlag2: false,gender:''}},mounted(){},methods:{// 父组件在使用时定义自己的点击事件,其本质是子组件中的点击事件触发父组件中的点击事件getInfo() {console.log('获取信息!!'); // 获取子传父的信息},// 父组件控制dialog的显示与隐藏// switchDialog(value){ // this.visible = value// },db(value){this.money = value}}}</script><style></style>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。