這是我參與8月更文挑戰的第6天,活動詳情查看:8月更文挑戰javascript
在上一篇中,咱們已經封裝了radio組件,在radio組件的基礎上,還須要一個radio-group組件來方便咱們使用css
radio-group組件是再radio組件上進行優化的,它的目的是在咱們使用radio組件時,沒必要給每一個組件都添加一個v-model,而是經過綁定一個v-model來實現數據綁定,並能夠對radio組件樣式進行總體規定,適用於在多個互斥的選項中選擇的場景。html
<template>
<div class="lol-radio-group"> <slot></slot> </div>
</template>
<script> export default { name: 'lolRadioGroup', provide () { return { RadioGroup: this } }, props: { value: null } } </script>
複製代碼
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')
複製代碼
<lol-radio-group v-model="model">
<lol-radio label="1">匹配模式</lol-radio>
<lol-radio label="2">排位模式</lol-radio>
</lol-radio-group>
複製代碼
在radio組件顯示中默認是水平方向vue
而咱們想經過傳入屬性的方式顯示爲垂直方向java
<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>
複製代碼
props: {
vertical: {
type: Boolean,
default: false
}
}
複製代碼
<template>
<div class="lol-radio-group" :class="[{'is-vertical': vertical}]" >
<slot></slot>
</div>
</template>
複製代碼
.is-vertical {
display: flex;
flex-direction: column;
}
複製代碼
inject: {
RadioGroup: {
default: ''
}
}
複製代碼
computed: {
isGrouped () {
return !!this.RadioGroup
}
}
複製代碼
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)
}
}
}
複製代碼
methods: {
handleChange () {
this.$nextTick(() => {
this.isGrouped
? this.RadioGroup.$emit('change', this.model)
: this.$emit('change', this.model)
})
}
}
複製代碼
isDisabled () {
return this.isGrouped
? this.RadioGroup.disabled || this.disabled
: this.disabled
},
複製代碼
<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>
複製代碼
<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>
複製代碼
至此,radio組件與radio-group組件封裝完畢,接下來將封裝Checkbox多選框markdown
你的贊是我繼續更文的動力!!app
respect by myself框架