mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
refactor(Checkbox): refactor with composition api
This commit is contained in:
parent
3ead2f4027
commit
278ea6a439
@ -1,12 +1,13 @@
|
|||||||
|
import { watch } from 'vue';
|
||||||
import { createNamespace } from '../utils';
|
import { createNamespace } from '../utils';
|
||||||
import { FieldMixin } from '../mixins/field';
|
import { CHECKBOX_KEY } from '../checkbox';
|
||||||
import { ParentMixin } from '../mixins/relation';
|
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');
|
const [createComponent, bem] = createNamespace('checkbox-group');
|
||||||
|
|
||||||
export default createComponent({
|
export default createComponent({
|
||||||
mixins: [ParentMixin('vanCheckbox'), FieldMixin],
|
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
max: [Number, String],
|
max: [Number, String],
|
||||||
disabled: Boolean,
|
disabled: Boolean,
|
||||||
@ -21,31 +22,31 @@ export default createComponent({
|
|||||||
|
|
||||||
emits: ['change', 'update:modelValue'],
|
emits: ['change', 'update:modelValue'],
|
||||||
|
|
||||||
watch: {
|
setup(props, { emit, slots }) {
|
||||||
modelValue(val) {
|
const { children, linkChildren } = useChildren(CHECKBOX_KEY);
|
||||||
this.$emit('change', val);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
const toggleAll = (checked) => {
|
||||||
// @exposed-api
|
|
||||||
toggleAll(checked) {
|
|
||||||
if (checked === false) {
|
if (checked === false) {
|
||||||
this.$emit('update:modelValue', []);
|
emit('update:modelValue', []);
|
||||||
return;
|
} else {
|
||||||
|
const names = children
|
||||||
|
.filter((item) => checked || !item.checked.value)
|
||||||
|
.map((item) => item.name);
|
||||||
|
emit('update:modelValue', names);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let { children } = this;
|
watch(
|
||||||
if (!checked) {
|
() => props.modelValue,
|
||||||
children = children.filter((item) => !item.checked);
|
(value) => {
|
||||||
|
emit('change', value);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const names = children.map((item) => item.name);
|
useExpose({ toggleAll });
|
||||||
this.$emit('update:modelValue', names);
|
useParentField(() => props.modelValue);
|
||||||
},
|
linkChildren({ emit, props });
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
return () => <div class={bem([props.direction])}>{slots.default?.()}</div>;
|
||||||
return <div class={bem([this.direction])}>{this.$slots.default?.()}</div>;
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
|
import { computed, watch } from 'vue';
|
||||||
import { createNamespace, pick } from '../utils';
|
import { createNamespace, pick } from '../utils';
|
||||||
import { FieldMixin } from '../mixins/field';
|
import { useExpose } from '../composition/use-expose';
|
||||||
import { ChildrenMixin } from '../mixins/relation';
|
import { useParentField } from '../composition/use-parent-field';
|
||||||
|
import { useParent } from '../composition/use-relation';
|
||||||
import Checker, { checkerProps } from './Checker';
|
import Checker, { checkerProps } from './Checker';
|
||||||
|
|
||||||
const [createComponent, bem] = createNamespace('checkbox');
|
const [createComponent, bem] = createNamespace('checkbox');
|
||||||
|
|
||||||
export default createComponent({
|
export const CHECKBOX_KEY = 'vanCheckbox';
|
||||||
mixins: [FieldMixin, ChildrenMixin('vanCheckbox')],
|
|
||||||
|
|
||||||
|
export default createComponent({
|
||||||
props: {
|
props: {
|
||||||
...checkerProps,
|
...checkerProps,
|
||||||
|
// TODO
|
||||||
bindGroup: {
|
bindGroup: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
@ -18,79 +21,77 @@ export default createComponent({
|
|||||||
|
|
||||||
emits: ['change', 'update:modelValue'],
|
emits: ['change', 'update:modelValue'],
|
||||||
|
|
||||||
computed: {
|
setup(props, { emit, slots }) {
|
||||||
checked: {
|
const { parent } = useParent(CHECKBOX_KEY);
|
||||||
get() {
|
|
||||||
if (this.parent) {
|
|
||||||
return this.parent.modelValue.indexOf(this.name) !== -1;
|
|
||||||
}
|
|
||||||
return this.modelValue;
|
|
||||||
},
|
|
||||||
|
|
||||||
set(val) {
|
const setParentValue = (checked) => {
|
||||||
if (this.parent) {
|
const { name } = props;
|
||||||
this.setParentValue(val);
|
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 {
|
} else {
|
||||||
this.$emit('update:modelValue', val);
|
const index = value.indexOf(name);
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
value.splice(index, 1);
|
||||||
|
parent.emit('update:modelValue', value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checked = computed({
|
||||||
|
get() {
|
||||||
|
if (parent) {
|
||||||
|
return parent.props.modelValue.indexOf(props.name) !== -1;
|
||||||
|
}
|
||||||
|
return props.modelValue;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
if (parent) {
|
||||||
|
setParentValue(value);
|
||||||
|
} else {
|
||||||
|
emit('update:modelValue', value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
let toggleTimer;
|
||||||
modelValue(val) {
|
const toggle = (newValue = !checked.value) => {
|
||||||
this.$emit('change', val);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
// @exposed-api
|
|
||||||
toggle(checked = !this.checked) {
|
|
||||||
// When toggle method is called multiple times at the same time,
|
// When toggle method is called multiple times at the same time,
|
||||||
// only the last call is valid.
|
// only the last call is valid.
|
||||||
// This is a hack for usage inside Cell.
|
// This is a hack for usage inside Cell.
|
||||||
clearTimeout(this.toggleTask);
|
clearTimeout(toggleTimer);
|
||||||
this.toggleTask = setTimeout(() => {
|
toggleTimer = setTimeout(() => {
|
||||||
this.checked = checked;
|
checked.value = newValue;
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
|
|
||||||
setParentValue(val) {
|
watch(
|
||||||
const { parent } = this;
|
() => props.modelValue,
|
||||||
const value = parent.modelValue.slice();
|
(value) => {
|
||||||
|
emit('change', value);
|
||||||
if (val) {
|
|
||||||
if (parent.max && value.length >= parent.max) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/* istanbul ignore else */
|
useExpose({ toggle, checked });
|
||||||
if (value.indexOf(this.name) === -1) {
|
useParentField(() => props.modelValue);
|
||||||
value.push(this.name);
|
|
||||||
parent.$emit('update:modelValue', value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const index = value.indexOf(this.name);
|
|
||||||
|
|
||||||
/* istanbul ignore else */
|
return () => (
|
||||||
if (index !== -1) {
|
|
||||||
value.splice(index, 1);
|
|
||||||
parent.$emit('update:modelValue', value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Checker
|
<Checker
|
||||||
v-slots={pick(this.$slots, ['default', 'icon'])}
|
v-slots={pick(slots, ['default', 'icon'])}
|
||||||
bem={bem}
|
bem={bem}
|
||||||
role="checkbox"
|
role="checkbox"
|
||||||
parent={this.parent}
|
parent={parent}
|
||||||
checked={this.checked}
|
checked={checked.value}
|
||||||
onToggle={this.toggle}
|
onToggle={toggle}
|
||||||
{...this.$props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user