This is the 6th day of my participation in the August More Text Challenge

In the last article, we have encapsulated the Radio component. On the basis of the Radio component, we also need a radio-Group component to facilitate our use

1. Understand radio-Group components

1. What is radio-group component

The radio-group component is optimized on the radio component. Its purpose is that when we use the radio component, we do not need to add a V-Model to each component, but bind a V-Model to realize data binding, and the style of the radio component can be defined as a whole. Suitable for scenarios where multiple mutually exclusive options are selected.

2. Basic framework of radio-group components

<template>
  <div class="lol-radio-group">
    <slot></slot>
  </div>
</template>
<script>
export default {
  name: 'lolRadioGroup',
  provide () {
    return {
      RadioGroup: this}},props: {
    value: null}}</script>
Copy the code

3. Radio-group component registration

import Vue from 'vue'
import App from './App.vue'
// Reference the font icon
import './assets/fonts/iconfont.css'
// Import the button component
import lolButton from './components/button.vue'
// Import button-group components
import lolButtonGroup from './components/button-group.vue'
// Import the Radio component
import lolRadio from './components/radio.vue'
// Import radio-group components
import lolRadioGroup from './components/radio-group.vue'
 
Vue.config.productionTip = false
 
// Register the component
Vue.component(lolButton.name, lolButton)
Vue.component(lolButtonGroup.name, lolButtonGroup)
Vue.component(lolRadio.name, lolRadio)
Vue.component(lolRadioGroup.name, lolRadioGroup)
 
new Vue({
  render: h= > h(App)
}).$mount('#app')

Copy the code

4. Use radio-group components

<lol-radio-group v-model="model">
    <lol-radio label="1">Match the pattern</lol-radio>
    <lol-radio label="2">Patterns of qualifying</lol-radio>
</lol-radio-group>
Copy the code

5. Radio-group component properties

The default in the Radio component display is horizontal

And we want it to be vertical by passing in attributes

  1. Parent component passed inverticalattribute
<lol-radio-group v-model="model" vertical>
    <lol-radio label="1">Match the pattern</lol-radio>
    <lol-radio label="2">A single position</lol-radio>
    <lol-radio label="3">Many people ranking</lol-radio>
</lol-radio-group>
Copy the code
  1. acceptverticalattribute
props: {
    vertical: {
      type: Boolean.default: false}}Copy the code
  1. Dynamic bindingverticalstyle
<template>
  <div class="lol-radio-group"
    :class="[{'is-vertical': vertical}]"
  >
    <slot></slot>
  </div>
</template>
Copy the code
  1. setverticalstyle
.is-vertical {
  display: flex;
  flex-direction: column;
}
Copy the code

2. Communicate with radio components

1. Radio accepts parameters through inject

inject: {
    RadioGroup: {
      default: ' '}}Copy the code

2. Check whether the radio component is wrapped by the radio-group component

computed: {
    isGrouped () {
      return!!!!!this.RadioGroup
    }
}
Copy the code

3. Select the value of Model

computed: {
    isGrouped () {
      return!!!!!thisRadioGroup},model: {
      get () {
        return this.isGrouped
          ? this.RadioGroup.value
          : this.value
      },
      set (value) {
        this.isGrouped
          ? this.RadioGroup.$emit('input', value)
          : this.$emit('input', value)
      }
    }
}
Copy the code

4. Bind the user-defined change event

  methods: {
    handleChange () {
      this.$nextTick(() = > {
        this.isGrouped
          ? this.RadioGroup.$emit('change'.this.model)
          : this.$emit('change'.this.model)
      })
    }
  }
Copy the code

5. Calculate the Disabeld attribute

isDisabled () {
      return this.isGrouped
        ? this.RadioGroup.disabled || this.disabled
        : this.disabled
},
Copy the code

Iii. Complete code of Radio series components

1. The radio components

<template>
  <label class="lol-radio"
    :class="[ {'is-disabled': isDisabled}, {'is-focus': focus}, {'is-checked': model === label} ]"
    role="radio"
    :aria-checked="model === label"
    :aria-disabled="isDisabled"
    :tabindex="tabIndex"
  >
    <span class="lol-radio_input"
    >
      <span class="lol-radio_inner"></span>
        <input
          type="radio"
          class="lol-radio_original"
          :value="label"
          :name="name"
          :disabled="isDisabled"
          @focus="focus = true"
          @blur="focus = false"
          @change="handleChange"
          aria-hidden="true"
          v-model="model"
          tabindex="1"
        >
      </span>
      <span class="lol-radio_label" @keydown.stop>
        <slot></slot>
        <template v-if=! "" $slots.default">{{label}}</template>
      </span>
  </label>
</template>

<script>

export default {
  name: 'lolRadio'.inject: {
    RadioGroup: {
      default: ' '}},props: {
    label: {
      type: [String.Number.Boolean].default: ' '
    },
    value: null.name: {
      type: String.default: ' '
    },
    disabled: {
      type: Boolean.default: false
    }
  },

  data () {
    return {
      focus: false}},computed: {
    isGrouped () {
      return!!!!!this.RadioGroup
    },
    model: {
      get () {
        return this.isGrouped
          ? this.RadioGroup.value
          : this.value
      },
      set (value) {
        this.isGrouped
          ? this.RadioGroup.$emit('input', value)
          : this.$emit('input', value)
      }
    },
    isDisabled () {
      return this.isGrouped
        ? this.RadioGroup.disabled || this.disabled
        : this.disabled
    },
    tabIndex () {
      return (this.isDisabled || (this.isGrouped && this.model ! = =this.label)) ? -1 : 0}},methods: {
    handleChange () {
      this.$nextTick(() = > {
        this.isGrouped
          ? this.RadioGroup.$emit('change'.this.model)
          : this.$emit('change'.this.model)
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.lol-radio{
  color: #E0CE9C;
  font-weight: 500;
  line-height: 1;
  position: relative;
  cursor: pointer;
  display: inline-block;
  white-space: nowrap;
  outline: none;
  font-size: 14px;
  margin-right: 30px;
  user-select: none;
  &:focus,
  &:hover{
    color: #E8DFCC;
  }
  & + & {
    margin-top: 14px;
  }
  .lol-radio_input{
    white-space: nowrap;
    cursor: pointer;
    outline: none;
    display: inline-block;
    line-height: 1;
    position: relative;
    vertical-align: middle;
    .lol-radio_inner{
      display: inline-block;
      box-sizing: border-box;
      position: relative;
      border: 2px solid #C59533;
      width: 14px;
      height: 14px;
      background-color: rgba(0.0.0.0);
      transform: rotate(45deg);
      &:after{
        width: 5px;
        height: 5px;
        background-color: #E8DFCC;
        content: "";
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%) scale(0);
        transition: transform .15sease-in; }}.lol-radio_original{
      opacity: 0;
      outline: none;
      position: absolute;
      z-index: -1;
      top: 0;
      left: 0;
      margin: 0; }}.lol-radio_label{
    font-size: 14px;
    padding-left: 10px; }}.lol-radio.is-checked{
  .lol-radio_input{
    .lol-radio_inner{
      border-color: #C79734;
      &:after{
        transform: translate(-50%, -50%) scale(1); }}}.lol-radio_label{
    color: #E8DFCC; }}.lol-radio.is-disabled {
  cursor: not-allowed;
  .lol-radio_input{
    cursor: not-allowed;
    .lol-radio_inner{
      cursor: not-allowed;
      border-color: #5C5B57}}.lol-radio_label{
    color: #5C5B57; }}</style>
Copy the code

2. The radio – group components

<template>
  <div class="lol-radio-group"
    :class="[{'is-vertical': vertical}]"
  >
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'lolRadioGroup',
  provide () {
    return {
      RadioGroup: this}},props: {
    value: null.disabled: {
      type: Boolean.default: false
    },
    vertical: {
      type: Boolean.default: false}}}</script>

<style>
.is-vertical {
  display: flex;
  flex-direction: column;
}
</style>
Copy the code

end

At this point, the radio component and radio-group component are wrapped, and the Checkbox Checkbox is wrapped next

Your praise is my motivation to continue writing!!

respect by myself