diff --git a/src/checkbox-group/index.js b/src/checkbox-group/index.js index fd77c0ed9..172572516 100644 --- a/src/checkbox-group/index.js +++ b/src/checkbox-group/index.js @@ -1,12 +1,13 @@ +import { watch } from 'vue'; import { createNamespace } from '../utils'; -import { FieldMixin } from '../mixins/field'; -import { ParentMixin } from '../mixins/relation'; +import { CHECKBOX_KEY } from '../checkbox'; +import { useExpose } from '../composition/use-expose'; +import { useChildren } from '../composition/use-relation'; +import { useParentField } from '../composition/use-parent-field'; const [createComponent, bem] = createNamespace('checkbox-group'); export default createComponent({ - mixins: [ParentMixin('vanCheckbox'), FieldMixin], - props: { max: [Number, String], disabled: Boolean, @@ -21,31 +22,31 @@ export default createComponent({ emits: ['change', 'update:modelValue'], - watch: { - modelValue(val) { - this.$emit('change', val); - }, - }, + setup(props, { emit, slots }) { + const { children, linkChildren } = useChildren(CHECKBOX_KEY); - methods: { - // @exposed-api - toggleAll(checked) { + const toggleAll = (checked) => { if (checked === false) { - this.$emit('update:modelValue', []); - return; + emit('update:modelValue', []); + } else { + const names = children + .filter((item) => checked || !item.checked.value) + .map((item) => item.name); + emit('update:modelValue', names); } + }; - let { children } = this; - if (!checked) { - children = children.filter((item) => !item.checked); + watch( + () => props.modelValue, + (value) => { + emit('change', value); } + ); - const names = children.map((item) => item.name); - this.$emit('update:modelValue', names); - }, - }, + useExpose({ toggleAll }); + useParentField(() => props.modelValue); + linkChildren({ emit, props }); - render() { - return
{this.$slots.default?.()}
; + return () =>
{slots.default?.()}
; }, }); diff --git a/src/checkbox/index.js b/src/checkbox/index.js index 9b6c96659..3604596bd 100644 --- a/src/checkbox/index.js +++ b/src/checkbox/index.js @@ -1,15 +1,18 @@ +import { computed, watch } from 'vue'; import { createNamespace, pick } from '../utils'; -import { FieldMixin } from '../mixins/field'; -import { ChildrenMixin } from '../mixins/relation'; +import { useExpose } from '../composition/use-expose'; +import { useParentField } from '../composition/use-parent-field'; +import { useParent } from '../composition/use-relation'; import Checker, { checkerProps } from './Checker'; const [createComponent, bem] = createNamespace('checkbox'); -export default createComponent({ - mixins: [FieldMixin, ChildrenMixin('vanCheckbox')], +export const CHECKBOX_KEY = 'vanCheckbox'; +export default createComponent({ props: { ...checkerProps, + // TODO bindGroup: { type: Boolean, default: true, @@ -18,79 +21,77 @@ export default createComponent({ emits: ['change', 'update:modelValue'], - computed: { - checked: { + setup(props, { emit, slots }) { + const { parent } = useParent(CHECKBOX_KEY); + + const setParentValue = (checked) => { + const { name } = props; + const { max, modelValue } = parent.props; + const value = modelValue.slice(); + + if (checked) { + const overlimit = max && value.length >= max; + + if (!overlimit && value.indexOf(name) === -1) { + value.push(name); + parent.emit('update:modelValue', value); + } + } else { + const index = value.indexOf(name); + + if (index !== -1) { + value.splice(index, 1); + parent.emit('update:modelValue', value); + } + } + }; + + const checked = computed({ get() { - if (this.parent) { - return this.parent.modelValue.indexOf(this.name) !== -1; + if (parent) { + return parent.props.modelValue.indexOf(props.name) !== -1; } - return this.modelValue; + return props.modelValue; }, - - set(val) { - if (this.parent) { - this.setParentValue(val); + set(value) { + if (parent) { + setParentValue(value); } else { - this.$emit('update:modelValue', val); + emit('update:modelValue', value); } }, - }, - }, + }); - watch: { - modelValue(val) { - this.$emit('change', val); - }, - }, - - methods: { - // @exposed-api - toggle(checked = !this.checked) { + let toggleTimer; + const toggle = (newValue = !checked.value) => { // When toggle method is called multiple times at the same time, // only the last call is valid. // This is a hack for usage inside Cell. - clearTimeout(this.toggleTask); - this.toggleTask = setTimeout(() => { - this.checked = checked; + clearTimeout(toggleTimer); + toggleTimer = setTimeout(() => { + checked.value = newValue; }); - }, + }; - setParentValue(val) { - const { parent } = this; - const value = parent.modelValue.slice(); - - if (val) { - if (parent.max && value.length >= parent.max) { - return; - } - - /* istanbul ignore else */ - if (value.indexOf(this.name) === -1) { - value.push(this.name); - parent.$emit('update:modelValue', value); - } - } else { - const index = value.indexOf(this.name); - - /* istanbul ignore else */ - if (index !== -1) { - value.splice(index, 1); - parent.$emit('update:modelValue', value); - } + watch( + () => props.modelValue, + (value) => { + emit('change', value); } - }, - }, + ); - render() { - return ( + useExpose({ toggle, checked }); + useParentField(() => props.modelValue); + + return () => ( ); },