You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
6.2 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view
:class="`wd-checkbox ${innerCell ? 'is-cell-box' : ''} ${innerShape === 'button' ? 'is-button-box' : ''} ${isChecked ? 'is-checked' : ''} ${
isFirst ? 'is-first-child' : ''
} ${isLast ? 'is-last-child' : ''} ${innerInline ? 'is-inline' : ''} ${innerShape === 'button' ? 'is-button' : ''} ${
innerDisabled ? 'is-disabled' : ''
} ${innerSize ? 'is-' + innerSize : ''} ${customClass}`"
@click="toggle"
>
<!--shape为button时移除wd-checkbox__shape只保留wd-checkbox__label-->
<view
v-if="innerShape !== 'button'"
:class="`wd-checkbox__shape ${innerShape === 'square' ? 'is-square' : ''} ${customShapeClass}`"
:style="isChecked && !innerDisabled && innerCheckedColor ? 'color :' + innerCheckedColor : ''"
>
<wd-icon custom-class="wd-checkbox__check" name="check-bold" size="14px" />
</view>
<!--shape为button时只保留wd-checkbox__label-->
<view
:class="`wd-checkbox__label ${customLabelClass}`"
:style="isChecked && innerShape === 'button' && !innerDisabled && innerCheckedColor ? 'color:' + innerCheckedColor : ''"
>
<!--button选中时展示的icon-->
<wd-icon v-if="innerShape === 'button' && isChecked" custom-class="wd-checkbox__btn-check" name="check-bold" size="14px" />
<!--文案-->
<view class="wd-checkbox__txt" :style="maxWidth ? 'max-width:' + maxWidth : ''">
<slot></slot>
</view>
</view>
</view>
</template>
<script lang="ts">
export default {
name: 'wd-checkbox',
options: {
addGlobalClass: true,
virtualHost: true,
styleIsolation: 'shared'
}
}
</script>
<script lang="ts" setup>
import { computed, getCurrentInstance, onBeforeMount, watch } from 'vue'
import { useParent } from '../composables/useParent'
import { CHECKBOX_GROUP_KEY } from '../wd-checkbox-group/types'
import { isDef } from '../common/util'
type checkShape = 'circle' | 'square' | 'button'
interface Props {
customLabelClass?: string
customShapeClass?: string
customClass?: string
modelValue: string | number | boolean
shape?: checkShape
checkedColor?: string
disabled?: boolean | null
trueValue?: string | number | boolean
falseValue?: string | number | boolean
size?: string
maxWidth?: string
}
const props = withDefaults(defineProps<Props>(), {
customLabelClass: '',
customShapeClass: '',
customClass: '',
shape: 'circle',
trueValue: true,
falseValue: false,
disabled: null
})
const { parent: checkboxGroup, index } = useParent(CHECKBOX_GROUP_KEY)
const isChecked = computed(() => {
if (checkboxGroup) {
return checkboxGroup.props.modelValue.indexOf(props.modelValue) > -1
} else {
return props.modelValue === props.trueValue
}
}) // 是否被选中
const isFirst = computed(() => {
return index.value === 0
})
const isLast = computed(() => {
const children = isDef(checkboxGroup) ? checkboxGroup.children : []
return index.value === children.length - 1
})
const { proxy } = getCurrentInstance() as any
watch(
() => props.modelValue,
() => {
// 组合使用走这个逻辑
if (checkboxGroup) {
checkName()
}
}
)
watch(
() => props.shape,
(newValue) => {
const type = ['circle', 'square', 'button']
if (type.indexOf(newValue) === -1) console.error(`shape must be one of ${type.toString()}`)
}
)
const innerShape = computed(() => {
if (!props.shape && checkboxGroup && checkboxGroup.props.shape) {
return checkboxGroup.props.shape
} else {
return props.shape
}
})
const innerCheckedColor = computed(() => {
if (!props.checkedColor && checkboxGroup && checkboxGroup.props.checkedColor) {
return checkboxGroup.props.checkedColor
} else {
return props.checkedColor
}
})
const innerDisabled = computed(() => {
let innerDisabled = props.disabled
if (checkboxGroup) {
if (
// max 生效时group 已经选满,禁止其它节点再选中。
(checkboxGroup.props.max && checkboxGroup.props.modelValue.length >= checkboxGroup.props.max && !isChecked.value) ||
// min 生效时group 选中的节点数量仅满足最小值,禁止取消已选中的节点。
(checkboxGroup.props.min && checkboxGroup.props.modelValue.length <= checkboxGroup.props.min && isChecked.value) ||
// 只要子节点自己要求 disabled那就 disabled。
props.disabled === true ||
// 父节点要求全局 disabled子节点没吱声那就 disabled。
(checkboxGroup.props.disabled && props.disabled === null)
) {
innerDisabled = true
}
}
return innerDisabled
})
const innerInline = computed(() => {
if (checkboxGroup && checkboxGroup.props.inline) {
return checkboxGroup.props.inline
} else {
return false
}
})
const innerCell = computed(() => {
if (checkboxGroup && checkboxGroup.props.cell) {
return checkboxGroup.props.cell
} else {
return false
}
})
const innerSize = computed(() => {
if (!props.size && checkboxGroup && checkboxGroup.props.size) {
return checkboxGroup.props.size
} else {
return props.size
}
})
onBeforeMount(() => {
// eslint-disable-next-line quotes
if (props.modelValue === null) console.error("checkbox's value must be set")
})
const emit = defineEmits(['change', 'update:modelValue'])
/**
* @description 检测checkbox绑定的value是否和其它checkbox的value冲突
* @param {Object} self 自身
* @param myName 自己的标识符
*/
function checkName() {
checkboxGroup &&
checkboxGroup.children &&
checkboxGroup.children.forEach((child: any) => {
if (child.$.uid !== proxy.$.uid && child.modelValue === props.modelValue) {
console.error(`The checkbox's bound value: ${props.modelValue} has been used`)
}
})
}
/**
* @description 点击checkbox的Event handle
*/
function toggle() {
if (innerDisabled.value) return
// 复选框单独使用时点击反选并且在checkbox上触发change事件
if (checkboxGroup) {
emit('change', {
value: !isChecked.value
})
checkboxGroup.changeSelectState(props.modelValue)
} else {
const newVal = props.modelValue === props.trueValue ? props.falseValue : props.trueValue
emit('update:modelValue', newVal)
emit('change', {
value: newVal
})
}
}
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>