<template>
<div class="ion-radio" :class="[modeClass,colorClass,{'radio-disabled':isDisabled}]">
<div class="radio-icon" :class="{'radio-checked':isChecked}">
<div class="radio-inner"></div>
</div>
<button role="radio" @click="onPointerDownHandler($event)"
type="button"
:id="id"
ion-button="item-cover"
class="item-cover">
</button>
</div>
</template>
<style lang="scss" src="./style.scss"></style>
<script type="text/javascript">
/**
* @component Radio
* @description
*
* ## 表单组件 / Radio单选框组件
*
* ### 注意
*
* 使用v-modal切换状态(数据控制), 不支持checked属性, value为纯string字段, 用于唯一标识;
*
* ### 其他
*
* - 组件支持异步操作实例化
* - 目前组件的层级嵌套关系如下: List -> Item -> Radio
* - 动态设置了单个radio的禁用状态, 如果之前是选中的则取消选中, 手动点击和数据选中都会生效
*
* ### 组件通讯关系
*
* 1. 初始化时, radio组件自己的this传递给radio-group, recordRadio()
* 2. Radio点击时, 调用List组件的onRadioChange函数, 传递自己的value
* 3. List组件得到value触发input更新v-modal值, 之后遍历子组件Radio, 触发组件的setChecked, 传递value
* 4. 子组件根据传入的value设置自己的状态
*
*
* ### 如何引入
* ```
* // 引入
* import { Radio } from 'vimo'
* // 安装
* Vue.component(Radio.name, Radio)
* // 或者
* export default{
* components: {
* Radio
* }
* }
* ```
*
* @props {String} [mode='ios'] - 模式
* @props {String} [color] - 颜色
* @props {Boolean} [disabled=false] - 单向选择, 点击且换并不对父组件传递
*
* @fire component:Radio#onSelect - 点按选择时触发
* @demo #/radio
* @usage
* <List radio-group v-model="fruits" :disabled="isListDisabled">
* <ListHeader>Fruits</ListHeader>
* <Item>
* <Label>Apple</Label>
* <Radio value="apple" :disabled="isAppleDisabled" @onSelect="onSelectHandler"></Radio>
* </Item>
* <Item>
* <Label>Banana</Label>
* <Radio value="banana" color="danger" @onSelect="onSelectHandler"></Radio>
* </Item>
* <Item>
* <Label>Cherry (secondary color)</Label>
* <Radio value="cherry" color="secondary" @onSelect="onSelectHandler"></Radio>
* </Item>
* <Item>
* <Label>Disabled</Label>
* <Radio value="disabled" :disabled="true" @onSelect="onSelectHandler"></Radio>
* </Item>
* <Item>
* <Label>Default</Label>
* <Radio value="default" @onSelect="onSelectHandler"></Radio>
* </Item>
* </List>
*
* */
import { setElementClass } from '../../util/util'
import { isTrueProperty } from '../../util/type'
let id = 0
export default {
name: 'Radio',
inject: {
itemComponent: {
from: 'itemComponent',
default: null
},
listComponent: {
from: 'listComponent',
default: null
}
},
data () {
return {
isChecked: false, // 内部 选中
isDisabled: this.disabled, // 内部 禁用
radioGroupComponent: null, // list(radioGroup)组件实例
isInit: false, // 初始化状态
id: `rb-${id++}` // id
}
},
props: {
// 固定值
value: String,
disabled: Boolean,
color: String,
mode: {
type: String,
default () { return this.$config && this.$config.get('mode', 'ios') || 'ios' }
}
},
watch: {
disabled (val) {
this.setDisabled(isTrueProperty(val))
}
},
computed: {
modeClass () {
return `radio radio-${this.mode}`
},
colorClass () {
return this.color ? (`radio-${this.mode}-${this.color}`) : ''
}
},
methods: {
/**
* 设置当前radio的禁用状态
* */
setDisabled (isDisabled) {
this.setChecked(null)
this.isDisabled = isDisabled
this.itemComponent && setElementClass(this.itemComponent.$el, 'item-radio-disabled', isDisabled)
},
/**
* 设置当前的radio的选中状态
* */
setChecked (checked) {
let isChecked = (checked === this.value) && !this.isDisabled
if (this.isChecked !== isChecked) {
this.isChecked = isChecked
this.isInit && this.isChecked && this.$emit('onSelect', this.value)
this.itemComponent && setElementClass(this.itemComponent.$el, 'item-checkbox-checked', this.isChecked)
}
},
/**
* 当radio点击时
* */
onPointerDownHandler ($event) {
$event.preventDefault()
$event.stopPropagation()
!this.isDisabled && this.radioGroupComponent && this.radioGroupComponent.onRadioChange(this.value)
},
/**
* init
* */
init () {
// 找到外部item实例
if (this.itemComponent) {
setElementClass(this.itemComponent.$el, 'item-radio', true)
}
// 找到外部List实例
if (this.listComponent) {
if (this.listComponent.radioGroup) {
this.radioGroupComponent = this.listComponent
this.radioGroupComponent.recordRadio(this)
}
}
// 初始化禁用状态
this.setDisabled(this.disabled)
this.isInit = true
}
},
mounted () {
this.init()
}
}
</script>