LOLstyle-ui組件開發實戰(四)—— Radio-group組件

這是我參與8月更文挑戰的第6天,活動詳情查看:8月更文挑戰javascript

在上一篇中,咱們已經封裝了radio組件,在radio組件的基礎上,還須要一個radio-group組件來方便咱們使用css

1、認識radio-group組件

1. 什麼是radio-group組件

radio-group組件是再radio組件上進行優化的,它的目的是在咱們使用radio組件時,沒必要給每一個組件都添加一個v-model,而是經過綁定一個v-model來實現數據綁定,並能夠對radio組件樣式進行總體規定,適用於在多個互斥的選項中選擇的場景。html

2. radio-group組件基本框架

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

3. radio-group組件註冊

import Vue from 'vue'
import App from './App.vue'
// 引用字體圖標
import './assets/fonts/iconfont.css'
// 導入button組件
import lolButton from './components/button.vue'
// 導入button-group組件
import lolButtonGroup from './components/button-group.vue'
// 導入Radio組件
import lolRadio from './components/radio.vue'
// 導入radio-group組件
import lolRadioGroup from './components/radio-group.vue'
 
Vue.config.productionTip = false
 
// 註冊組件
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')

複製代碼

4. radio-group組件使用

<lol-radio-group v-model="model">
    <lol-radio label="1">匹配模式</lol-radio>
    <lol-radio label="2">排位模式</lol-radio>
</lol-radio-group>
複製代碼

5. radio-group組件屬性

在radio組件顯示中默認是水平方向vue

image.png 而咱們想經過傳入屬性的方式顯示爲垂直方向java

image.png

  1. 父組件傳入vertical屬性
<lol-radio-group v-model="model" vertical>
    <lol-radio label="1">匹配模式</lol-radio>
    <lol-radio label="2">單人排位</lol-radio>
    <lol-radio label="3">多人排位</lol-radio>
</lol-radio-group>
複製代碼
  1. 接受vertical屬性
props: {
    vertical: {
      type: Boolean,
      default: false
    }
  }
複製代碼
  1. 動態綁定vertical樣式
<template>
  <div class="lol-radio-group" :class="[{'is-vertical': vertical}]" >
    <slot></slot>
  </div>
</template>
複製代碼
  1. 設定vertical樣式
.is-vertical {
  display: flex;
  flex-direction: column;
}
複製代碼

2、與radio組件通信

1. radio經過inject接受參數

inject: {
    RadioGroup: {
      default: ''
    }
}
複製代碼

2. 判斷radio組件是否被radio-group組件包裹

computed: {
    isGrouped () {
      return !!this.RadioGroup
    }
}
複製代碼

3. 判斷完成後選擇model的值

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)
      }
    }
}
複製代碼

4. 綁定自定義change事件

methods: {
    handleChange () {
      this.$nextTick(() => {
        this.isGrouped
          ? this.RadioGroup.$emit('change', this.model)
          : this.$emit('change', this.model)
      })
    }
  }
複製代碼

5. 計算disabeld屬性

isDisabled () {
      return this.isGrouped
        ? this.RadioGroup.disabled || this.disabled
        : this.disabled
},
複製代碼

3、radio系列組件完整代碼

1. radio組件

<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 .15s ease-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>
複製代碼

2. radio-group組件

<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>
複製代碼

end

至此,radio組件與radio-group組件封裝完畢,接下來將封裝Checkbox多選框markdown

你的贊是我繼續更文的動力!!app

0070E00E.pngrespect by myself框架

相關文章
相關標籤/搜索