diff --git a/src/composition/use-parent-field.ts b/src/composition/use-parent-field.ts index f378adcd8..561c9fef2 100644 --- a/src/composition/use-parent-field.ts +++ b/src/composition/use-parent-field.ts @@ -2,7 +2,7 @@ import { watch, inject, WatchSource, getCurrentInstance } from 'vue'; import { FIELD_KEY } from '../field'; export function useParentField(watchSource: WatchSource) { - const field = inject(FIELD_KEY) as any; + const field = inject(FIELD_KEY, null) as any; if (field && !field.children) { field.children = getCurrentInstance()!.proxy; diff --git a/src/rate/index.js b/src/rate/index.js index d191d20b0..d092126f3 100644 --- a/src/rate/index.js +++ b/src/rate/index.js @@ -1,10 +1,13 @@ +import { computed } from 'vue'; + // Utils import { createNamespace, addUnit } from '../utils'; import { preventDefault } from '../utils/dom/event'; -// Mixins -import { TouchMixin } from '../mixins/touch'; -import { FieldMixin } from '../mixins/field'; +// Composition +import { useRefs } from '../composition/use-refs'; +import { useTouch } from '../composition/use-touch'; +import { useParentField } from '../composition/use-parent-field'; // Components import Icon from '../icon'; @@ -15,17 +18,13 @@ function getRateStatus(value, index, allowHalf) { if (value >= index) { return 'full'; } - if (value + 0.5 >= index && allowHalf) { return 'half'; } - return 'void'; } export default createComponent({ - mixins: [TouchMixin, FieldMixin], - props: { size: [Number, String], color: String, @@ -60,53 +59,51 @@ export default createComponent({ emits: ['change', 'update:modelValue'], - created() { - this.itemRefs = []; - }, + setup(props, { emit }) { + let ranges; - computed: { - list() { + const touch = useTouch(); + const [itemRefs, setItemRefs] = useRefs(); + + const untouchable = () => + props.readonly || props.disabled || !props.touchable; + + const list = computed(() => { const list = []; - for (let i = 1; i <= this.count; i++) { - list.push(getRateStatus(this.modelValue, i, this.allowHalf)); + for (let i = 1; i <= props.count; i++) { + list.push(getRateStatus(props.modelValue, i, props.allowHalf)); } - return list; - }, + }); - sizeWithUnit() { - return addUnit(this.size); - }, - - gutterWithUnit() { - return addUnit(this.gutter); - }, - }, - - mounted() { - this.bindTouchEvent(this.$el); - }, - - methods: { - select(index) { - if (!this.disabled && !this.readonly && index !== this.modelValue) { - this.$emit('update:modelValue', index); - this.$emit('change', index); + const select = (index) => { + if (!props.disabled && !props.readonly && index !== props.modelValue) { + emit('update:modelValue', index); + emit('change', index); } - }, + }; - onTouchStart(event) { - if (this.readonly || this.disabled || !this.touchable) { + const getScoreByPosition = (x) => { + for (let i = ranges.length - 1; i > 0; i--) { + if (x > ranges[i].left) { + return ranges[i].score; + } + } + return props.allowHalf ? 0.5 : 1; + }; + + const onTouchStart = (event) => { + if (untouchable()) { return; } - this.touchStart(event); + touch.start(event); - const rects = this.itemRefs.map((item) => item.getBoundingClientRect()); - const ranges = []; + const rects = itemRefs.value.map((item) => item.getBoundingClientRect()); + ranges = []; rects.forEach((rect, index) => { - if (this.allowHalf) { + if (props.allowHalf) { ranges.push( { score: index + 0.5, left: rect.left }, { score: index + 1, left: rect.left + rect.width / 2 } @@ -115,108 +112,101 @@ export default createComponent({ ranges.push({ score: index + 1, left: rect.left }); } }); + }; - this.ranges = ranges; - }, - - onTouchMove(event) { - if (this.readonly || this.disabled || !this.touchable) { + const onTouchMove = (event) => { + if (untouchable()) { return; } - this.touchMove(event); - - if (this.direction === 'horizontal') { - preventDefault(event); + touch.move(event); + if (touch.direction.value === 'horizontal') { const { clientX } = event.touches[0]; - this.select(this.getScoreByPosition(clientX)); + preventDefault(event); + select(getScoreByPosition(clientX)); } - }, + }; - getScoreByPosition(x) { - for (let i = this.ranges.length - 1; i > 0; i--) { - if (x > this.ranges[i].left) { - return this.ranges[i].score; - } - } - - return this.allowHalf ? 0.5 : 1; - }, - - genStar(status, index) { + const renderStar = (status, index) => { const { icon, + size, color, count, + gutter, voidIcon, disabled, voidColor, + allowHalf, + iconPrefix, disabledColor, - } = this; + } = props; const score = index + 1; const isFull = status === 'full'; const isVoid = status === 'void'; let style; - if (this.gutterWithUnit && score !== +count) { - style = { paddingRight: this.gutterWithUnit }; + if (gutter && score !== +count) { + style = { + paddingRight: addUnit(gutter), + }; } return (