mirror of
https://github.com/element-plus/element-plus.git
synced 2025-01-18 10:59:10 +08:00
refactor(components): [rate] switch to script-setup syntax (#6565)
Co-authored-by: 三咲智子 <sxzz@sxzz.moe>
This commit is contained in:
parent
61cfd369dc
commit
18bd8c4952
@ -20,6 +20,7 @@
|
||||
"packages/components/icon/",
|
||||
"packages/components/link/",
|
||||
"packages/components/page-header/",
|
||||
"packages/components/rate/",
|
||||
"packages/components/row/",
|
||||
"packages/components/slot/",
|
||||
"packages/components/tag/",
|
||||
|
@ -1,160 +0,0 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import Rate from '../src/rate.vue'
|
||||
|
||||
describe('Rate.vue', () => {
|
||||
test('create', () => {
|
||||
const wrapper = mount(Rate, {
|
||||
props: {
|
||||
max: 10,
|
||||
},
|
||||
})
|
||||
const stars = wrapper.findAll('.el-rate__item')
|
||||
expect(stars.length).toEqual(10)
|
||||
})
|
||||
|
||||
test('size', async () => {
|
||||
const wrapper = mount(Rate, {
|
||||
props: {
|
||||
size: 'large',
|
||||
},
|
||||
})
|
||||
expect(wrapper.find('.el-rate--large').exists()).toBe(true)
|
||||
await wrapper.setProps({ size: '' })
|
||||
expect(wrapper.find('.el-rate--default').exists()).toBe(true)
|
||||
})
|
||||
|
||||
test('allow half', async () => {
|
||||
const wrapper = mount({
|
||||
template: `
|
||||
<div>
|
||||
<el-rate v-model="value" allow-half ref='rate' />
|
||||
</div>
|
||||
`,
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
value: 0,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'el-rate': Rate,
|
||||
},
|
||||
})
|
||||
const vm = wrapper.vm
|
||||
const secondStar = wrapper.findAll('.el-rate__item')[1]
|
||||
.element as HTMLElement
|
||||
vm.$refs.rate.setCurrentValue(1, { target: secondStar, offsetX: 0 })
|
||||
// expect(vm.$refs.rate.currentValue).toEqual(0.5)
|
||||
secondStar.click()
|
||||
vm.$refs.rate.resetCurrentValue()
|
||||
expect(vm.value).toEqual(0.5)
|
||||
})
|
||||
|
||||
test('with texts', () => {
|
||||
const wrapper = mount(Rate, {
|
||||
props: {
|
||||
showText: true,
|
||||
modelValue: 4,
|
||||
texts: ['1', '2', '3', '4', '5'],
|
||||
},
|
||||
})
|
||||
const text = wrapper.find('.el-rate__text').element
|
||||
expect(text.textContent).toEqual('4')
|
||||
})
|
||||
|
||||
test('value change', async () => {
|
||||
const wrapper = mount(Rate, {
|
||||
props: {
|
||||
modelValue: 0,
|
||||
},
|
||||
})
|
||||
const vm = wrapper.vm
|
||||
await wrapper.setProps({ modelValue: 3 })
|
||||
expect(vm.modelValue).toEqual(3)
|
||||
})
|
||||
|
||||
test('click', () => {
|
||||
const wrapper = mount({
|
||||
template: `
|
||||
<div>
|
||||
<el-rate v-model="value1" />
|
||||
</div>
|
||||
`,
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
value1: 0,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'el-rate': Rate,
|
||||
},
|
||||
})
|
||||
const vm = wrapper.vm
|
||||
const thirdStar = wrapper.findAll('.el-rate__item')[2]
|
||||
.element as HTMLElement
|
||||
|
||||
thirdStar.click()
|
||||
expect(vm.value1).toEqual(3)
|
||||
})
|
||||
|
||||
test('colors', () => {
|
||||
const wrapper = mount({
|
||||
template: `
|
||||
<div>
|
||||
<el-rate v-model="value" :colors="['#99A9BF', '#F7BA2A', '#FF9900']"></el-rate>
|
||||
</div>
|
||||
`,
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
value: 4,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'el-rate': Rate,
|
||||
},
|
||||
})
|
||||
// const vm = wrapper.vm
|
||||
const thirdStar = (
|
||||
wrapper.findAll('.el-rate__item')[2].element as HTMLElement
|
||||
).querySelector('.el-rate__icon') as any
|
||||
|
||||
expect(thirdStar.style.color).toEqual('rgb(255, 153, 0)')
|
||||
})
|
||||
|
||||
test('change event', () => {
|
||||
const wrapper = mount({
|
||||
template: `
|
||||
<div>
|
||||
<el-rate v-model="value" @change="handleChange"></el-rate>
|
||||
</div>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
value: 4,
|
||||
changeCount: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange() {
|
||||
this.changeCount++
|
||||
},
|
||||
},
|
||||
components: {
|
||||
'el-rate': Rate,
|
||||
},
|
||||
})
|
||||
const vm = wrapper.vm
|
||||
const fourthStar = wrapper.findAll('.el-rate__item')[3]
|
||||
.element as HTMLElement
|
||||
fourthStar.click()
|
||||
expect(vm.value).toEqual(4)
|
||||
expect(vm.changeCount).toEqual(0)
|
||||
const fifthStar = wrapper.findAll('.el-rate__item')[4]
|
||||
.element as HTMLElement
|
||||
fifthStar.click()
|
||||
expect(vm.value).toEqual(5)
|
||||
expect(vm.changeCount).toEqual(1)
|
||||
})
|
||||
})
|
114
packages/components/rate/__tests__/rate.vitest.tsx
Normal file
114
packages/components/rate/__tests__/rate.vitest.tsx
Normal file
@ -0,0 +1,114 @@
|
||||
import { ref } from 'vue'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import Rate from '../src/rate.vue'
|
||||
|
||||
import type { RateInstance } from '../src/rate'
|
||||
|
||||
describe('Rate.vue', () => {
|
||||
it('create', () => {
|
||||
const wrapper = mount(Rate, {
|
||||
props: {
|
||||
max: 10,
|
||||
},
|
||||
})
|
||||
const stars = wrapper.findAll('.el-rate__item')
|
||||
expect(stars.length).toMatchInlineSnapshot('10')
|
||||
})
|
||||
|
||||
it('size', async () => {
|
||||
const wrapper = mount(Rate, {
|
||||
props: {
|
||||
size: 'large',
|
||||
},
|
||||
})
|
||||
expect(wrapper.find('.el-rate--large').exists()).toBe(true)
|
||||
await wrapper.setProps({ size: '' })
|
||||
expect(wrapper.find('.el-rate--default').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('allow half', async () => {
|
||||
const value = ref(0)
|
||||
const wrapper = mount(() => <Rate v-model={value.value} allowHalf />)
|
||||
const vm = wrapper.getComponent(Rate).vm as RateInstance
|
||||
|
||||
const secondStar = wrapper.findAll('.el-rate__item')[1]
|
||||
.element as HTMLElement
|
||||
vm.setCurrentValue(1, {
|
||||
target: secondStar,
|
||||
offsetX: 0,
|
||||
} as any as MouseEvent)
|
||||
secondStar.click()
|
||||
vm.resetCurrentValue()
|
||||
expect(value.value).toEqual(0.5)
|
||||
})
|
||||
|
||||
it('with texts', () => {
|
||||
const wrapper = mount(Rate, {
|
||||
props: {
|
||||
showText: true,
|
||||
modelValue: 4,
|
||||
texts: ['1', '2', '3', '4', '5'],
|
||||
},
|
||||
})
|
||||
const text = wrapper.find('.el-rate__text').element
|
||||
expect(text.textContent).toMatchInlineSnapshot('"4"')
|
||||
})
|
||||
|
||||
it('value change', async () => {
|
||||
const wrapper = mount(Rate, {
|
||||
props: {
|
||||
modelValue: 0,
|
||||
},
|
||||
})
|
||||
const vm = wrapper.vm
|
||||
await wrapper.setProps({ modelValue: 3 })
|
||||
expect(vm.modelValue).toMatchInlineSnapshot('3')
|
||||
})
|
||||
|
||||
it('click', () => {
|
||||
const value1 = ref(0)
|
||||
const wrapper = mount(() => <Rate v-model={value1.value} />)
|
||||
|
||||
const thirdStar = wrapper.findAll('.el-rate__item')[2]
|
||||
.element as HTMLElement
|
||||
thirdStar.click()
|
||||
|
||||
expect(value1.value).toEqual(3)
|
||||
})
|
||||
|
||||
it('colors', () => {
|
||||
const value = ref(4)
|
||||
const wrapper = mount(() => (
|
||||
<Rate v-model={value.value} colors={['#99A9BF', '#F7BA2A', '#FF9900']} />
|
||||
))
|
||||
|
||||
const thirdStar = (
|
||||
wrapper.findAll('.el-rate__item')[2].element as HTMLElement
|
||||
).querySelector<HTMLElement>('.el-rate__icon')!
|
||||
expect(thirdStar.style.color).toMatchInlineSnapshot('"rgb(255, 153, 0)"')
|
||||
})
|
||||
|
||||
it('change event', () => {
|
||||
const value = ref(4)
|
||||
const changeCount = ref(0)
|
||||
const handleChange = () => {
|
||||
changeCount.value++
|
||||
}
|
||||
const wrapper = mount(() => (
|
||||
<Rate v-model={value.value} onChange={handleChange} />
|
||||
))
|
||||
|
||||
const fourthStar = wrapper.findAll('.el-rate__item')[3]
|
||||
.element as HTMLElement
|
||||
fourthStar.click()
|
||||
|
||||
expect(value.value).toEqual(4)
|
||||
expect(changeCount.value).toEqual(0)
|
||||
const fifthStar = wrapper.findAll('.el-rate__item')[4]
|
||||
.element as HTMLElement
|
||||
fifthStar.click()
|
||||
expect(value.value).toEqual(5)
|
||||
expect(changeCount.value).toEqual(1)
|
||||
})
|
||||
})
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
:class="rateKls"
|
||||
:class="rateClasses"
|
||||
role="slider"
|
||||
:aria-valuenow="currentValue"
|
||||
:aria-valuetext="text"
|
||||
@ -44,19 +44,15 @@
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, inject, computed, ref, watch } from 'vue'
|
||||
import { isObject, isArray } from '@vue/shared'
|
||||
import { formContextKey } from '@element-plus/tokens'
|
||||
import { hasClass } from '@element-plus/utils'
|
||||
<script lang="ts" setup>
|
||||
import { inject, computed, ref, watch } from 'vue'
|
||||
import { EVENT_CODE, UPDATE_MODEL_EVENT } from '@element-plus/constants'
|
||||
import { isObject, isArray, hasClass } from '@element-plus/utils'
|
||||
import { formContextKey } from '@element-plus/tokens'
|
||||
import { ElIcon } from '@element-plus/components/icon'
|
||||
import { StarFilled, Star } from '@element-plus/icons-vue'
|
||||
import { useNamespace, useSize } from '@element-plus/hooks'
|
||||
import { rateProps, rateEmits } from './rate'
|
||||
|
||||
import type { FormContext } from '@element-plus/tokens'
|
||||
|
||||
function getValueFromMap<T>(
|
||||
value: number,
|
||||
map: Record<string, T | { excluded?: boolean; value: T }>
|
||||
@ -77,231 +73,210 @@ function getValueFromMap<T>(
|
||||
return (isExcludedObject(matchedValue) && matchedValue.value) || matchedValue
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
defineOptions({
|
||||
name: 'ElRate',
|
||||
components: {
|
||||
ElIcon,
|
||||
StarFilled,
|
||||
Star,
|
||||
},
|
||||
props: rateProps,
|
||||
emits: rateEmits,
|
||||
})
|
||||
|
||||
setup(props, { emit }) {
|
||||
const elForm = inject(formContextKey, {} as FormContext)
|
||||
const props = defineProps(rateProps)
|
||||
const emit = defineEmits(rateEmits)
|
||||
|
||||
const rateSize = useSize()
|
||||
const ns = useNamespace('rate')
|
||||
const formContext = inject(formContextKey, undefined)
|
||||
const rateSize = useSize()
|
||||
const ns = useNamespace('rate')
|
||||
|
||||
const currentValue = ref(props.modelValue)
|
||||
const hoverIndex = ref(-1)
|
||||
const pointerAtLeftHalf = ref(true)
|
||||
const currentValue = ref(props.modelValue)
|
||||
const hoverIndex = ref(-1)
|
||||
const pointerAtLeftHalf = ref(true)
|
||||
|
||||
const rateKls = computed(() => [ns.b(), ns.m(rateSize.value)])
|
||||
const rateClasses = computed(() => [ns.b(), ns.m(rateSize.value)])
|
||||
const rateDisabled = computed(() => props.disabled || formContext?.disabled)
|
||||
|
||||
const rateDisabled = computed(() => props.disabled || elForm.disabled)
|
||||
const text = computed(() => {
|
||||
let result = ''
|
||||
if (props.showScore) {
|
||||
result = props.scoreTemplate.replace(
|
||||
/\{\s*value\s*\}/,
|
||||
rateDisabled.value ? `${props.modelValue}` : `${currentValue.value}`
|
||||
)
|
||||
} else if (props.showText) {
|
||||
result = props.texts[Math.ceil(currentValue.value) - 1]
|
||||
}
|
||||
return result
|
||||
})
|
||||
const valueDecimal = computed(
|
||||
() => props.modelValue * 100 - Math.floor(props.modelValue) * 100
|
||||
const text = computed(() => {
|
||||
let result = ''
|
||||
if (props.showScore) {
|
||||
result = props.scoreTemplate.replace(
|
||||
/\{\s*value\s*\}/,
|
||||
rateDisabled.value ? `${props.modelValue}` : `${currentValue.value}`
|
||||
)
|
||||
const colorMap = computed(() =>
|
||||
isArray(props.colors)
|
||||
? {
|
||||
[props.lowThreshold]: props.colors[0],
|
||||
[props.highThreshold]: { value: props.colors[1], excluded: true },
|
||||
[props.max]: props.colors[2],
|
||||
}
|
||||
: props.colors
|
||||
)
|
||||
const activeColor = computed(() =>
|
||||
getValueFromMap(currentValue.value, colorMap.value)
|
||||
)
|
||||
const decimalStyle = computed(() => {
|
||||
let width = ''
|
||||
if (rateDisabled.value) {
|
||||
width = `${valueDecimal.value}%`
|
||||
} else if (props.allowHalf) {
|
||||
width = '50%'
|
||||
} else if (props.showText) {
|
||||
result = props.texts[Math.ceil(currentValue.value) - 1]
|
||||
}
|
||||
return result
|
||||
})
|
||||
const valueDecimal = computed(
|
||||
() => props.modelValue * 100 - Math.floor(props.modelValue) * 100
|
||||
)
|
||||
const colorMap = computed(() =>
|
||||
isArray(props.colors)
|
||||
? {
|
||||
[props.lowThreshold]: props.colors[0],
|
||||
[props.highThreshold]: { value: props.colors[1], excluded: true },
|
||||
[props.max]: props.colors[2],
|
||||
}
|
||||
return {
|
||||
color: activeColor.value,
|
||||
width,
|
||||
: props.colors
|
||||
)
|
||||
const activeColor = computed(() =>
|
||||
getValueFromMap(currentValue.value, colorMap.value)
|
||||
)
|
||||
const decimalStyle = computed(() => {
|
||||
let width = ''
|
||||
if (rateDisabled.value) {
|
||||
width = `${valueDecimal.value}%`
|
||||
} else if (props.allowHalf) {
|
||||
width = '50%'
|
||||
}
|
||||
return {
|
||||
color: activeColor.value,
|
||||
width,
|
||||
}
|
||||
})
|
||||
const componentMap = computed(() =>
|
||||
isArray(props.icons)
|
||||
? {
|
||||
[props.lowThreshold]: props.icons[0],
|
||||
[props.highThreshold]: {
|
||||
value: props.icons[1],
|
||||
excluded: true,
|
||||
},
|
||||
[props.max]: props.icons[2],
|
||||
}
|
||||
})
|
||||
const componentMap = computed(() =>
|
||||
isArray(props.icons)
|
||||
? {
|
||||
[props.lowThreshold]: props.icons[0],
|
||||
[props.highThreshold]: {
|
||||
value: props.icons[1],
|
||||
excluded: true,
|
||||
},
|
||||
[props.max]: props.icons[2],
|
||||
}
|
||||
: props.icons
|
||||
)
|
||||
const decimalIconComponent = computed(() =>
|
||||
getValueFromMap(props.modelValue, componentMap.value)
|
||||
)
|
||||
const voidComponent = computed(() =>
|
||||
rateDisabled.value ? props.disabledVoidIcon : props.voidIcon
|
||||
)
|
||||
const activeComponent = computed(() =>
|
||||
getValueFromMap(currentValue.value, componentMap.value)
|
||||
)
|
||||
const iconComponents = computed(() => {
|
||||
const result = Array.from({ length: props.max })
|
||||
const threshold = currentValue.value
|
||||
result.fill(activeComponent.value, 0, threshold)
|
||||
result.fill(voidComponent.value, threshold, props.max)
|
||||
return result
|
||||
})
|
||||
: props.icons
|
||||
)
|
||||
const decimalIconComponent = computed(() =>
|
||||
getValueFromMap(props.modelValue, componentMap.value)
|
||||
)
|
||||
const voidComponent = computed(() =>
|
||||
rateDisabled.value ? props.disabledVoidIcon : props.voidIcon
|
||||
)
|
||||
const activeComponent = computed(() =>
|
||||
getValueFromMap(currentValue.value, componentMap.value)
|
||||
)
|
||||
const iconComponents = computed(() => {
|
||||
const result = Array.from({ length: props.max })
|
||||
const threshold = currentValue.value
|
||||
result.fill(activeComponent.value, 0, threshold)
|
||||
result.fill(voidComponent.value, threshold, props.max)
|
||||
return result
|
||||
})
|
||||
|
||||
function showDecimalIcon(item: number) {
|
||||
const showWhenDisabled =
|
||||
rateDisabled.value &&
|
||||
valueDecimal.value > 0 &&
|
||||
item - 1 < props.modelValue &&
|
||||
item > props.modelValue
|
||||
const showWhenAllowHalf =
|
||||
props.allowHalf &&
|
||||
pointerAtLeftHalf.value &&
|
||||
item - 0.5 <= currentValue.value &&
|
||||
item > currentValue.value
|
||||
return showWhenDisabled || showWhenAllowHalf
|
||||
function showDecimalIcon(item: number) {
|
||||
const showWhenDisabled =
|
||||
rateDisabled.value &&
|
||||
valueDecimal.value > 0 &&
|
||||
item - 1 < props.modelValue &&
|
||||
item > props.modelValue
|
||||
const showWhenAllowHalf =
|
||||
props.allowHalf &&
|
||||
pointerAtLeftHalf.value &&
|
||||
item - 0.5 <= currentValue.value &&
|
||||
item > currentValue.value
|
||||
return showWhenDisabled || showWhenAllowHalf
|
||||
}
|
||||
|
||||
function getIconStyle(item: number) {
|
||||
const voidColor = rateDisabled.value
|
||||
? props.disabledVoidColor
|
||||
: props.voidColor
|
||||
return {
|
||||
color: item <= currentValue.value ? activeColor.value : voidColor,
|
||||
}
|
||||
}
|
||||
|
||||
function selectValue(value: number) {
|
||||
if (rateDisabled.value) {
|
||||
return
|
||||
}
|
||||
if (props.allowHalf && pointerAtLeftHalf.value) {
|
||||
emit(UPDATE_MODEL_EVENT, currentValue.value)
|
||||
if (props.modelValue !== currentValue.value) {
|
||||
emit('change', currentValue.value)
|
||||
}
|
||||
|
||||
function getIconStyle(item: number) {
|
||||
const voidColor = rateDisabled.value
|
||||
? props.disabledVoidColor
|
||||
: props.voidColor
|
||||
return {
|
||||
color: item <= currentValue.value ? activeColor.value : voidColor,
|
||||
}
|
||||
} else {
|
||||
emit(UPDATE_MODEL_EVENT, value)
|
||||
if (props.modelValue !== value) {
|
||||
emit('change', value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectValue(value: number) {
|
||||
if (rateDisabled.value) {
|
||||
return
|
||||
}
|
||||
if (props.allowHalf && pointerAtLeftHalf.value) {
|
||||
emit(UPDATE_MODEL_EVENT, currentValue.value)
|
||||
if (props.modelValue !== currentValue.value) {
|
||||
emit('change', currentValue.value)
|
||||
}
|
||||
} else {
|
||||
emit(UPDATE_MODEL_EVENT, value)
|
||||
if (props.modelValue !== value) {
|
||||
emit('change', value)
|
||||
}
|
||||
}
|
||||
function handleKey(e: KeyboardEvent) {
|
||||
if (rateDisabled.value) {
|
||||
return
|
||||
}
|
||||
let _currentValue = currentValue.value
|
||||
const code = e.code
|
||||
if (code === EVENT_CODE.up || code === EVENT_CODE.right) {
|
||||
if (props.allowHalf) {
|
||||
_currentValue += 0.5
|
||||
} else {
|
||||
_currentValue += 1
|
||||
}
|
||||
|
||||
function handleKey(e: KeyboardEvent) {
|
||||
if (rateDisabled.value) {
|
||||
return
|
||||
}
|
||||
let _currentValue = currentValue.value
|
||||
const code = e.code
|
||||
if (code === EVENT_CODE.up || code === EVENT_CODE.right) {
|
||||
if (props.allowHalf) {
|
||||
_currentValue += 0.5
|
||||
} else {
|
||||
_currentValue += 1
|
||||
}
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
} else if (code === EVENT_CODE.left || code === EVENT_CODE.down) {
|
||||
if (props.allowHalf) {
|
||||
_currentValue -= 0.5
|
||||
} else {
|
||||
_currentValue -= 1
|
||||
}
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
_currentValue = _currentValue < 0 ? 0 : _currentValue
|
||||
_currentValue = _currentValue > props.max ? props.max : _currentValue
|
||||
emit(UPDATE_MODEL_EVENT, _currentValue)
|
||||
emit('change', _currentValue)
|
||||
return _currentValue
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
} else if (code === EVENT_CODE.left || code === EVENT_CODE.down) {
|
||||
if (props.allowHalf) {
|
||||
_currentValue -= 0.5
|
||||
} else {
|
||||
_currentValue -= 1
|
||||
}
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
_currentValue = _currentValue < 0 ? 0 : _currentValue
|
||||
_currentValue = _currentValue > props.max ? props.max : _currentValue
|
||||
emit(UPDATE_MODEL_EVENT, _currentValue)
|
||||
emit('change', _currentValue)
|
||||
return _currentValue
|
||||
}
|
||||
|
||||
function setCurrentValue(value: number, event: MouseEvent) {
|
||||
if (rateDisabled.value) {
|
||||
return
|
||||
}
|
||||
if (props.allowHalf) {
|
||||
// TODO: use cache via computed https://github.com/element-plus/element-plus/pull/5456#discussion_r786472092
|
||||
let target = event.target as HTMLElement
|
||||
if (hasClass(target, ns.e('item'))) {
|
||||
target = target.querySelector(`.${ns.e('icon')}`)!
|
||||
}
|
||||
if (target.clientWidth === 0 || hasClass(target, ns.e('decimal'))) {
|
||||
target = target.parentNode as HTMLElement
|
||||
}
|
||||
pointerAtLeftHalf.value = event.offsetX * 2 <= target.clientWidth
|
||||
currentValue.value = pointerAtLeftHalf.value ? value - 0.5 : value
|
||||
} else {
|
||||
currentValue.value = value
|
||||
}
|
||||
hoverIndex.value = value
|
||||
function setCurrentValue(value: number, event: MouseEvent) {
|
||||
if (rateDisabled.value) {
|
||||
return
|
||||
}
|
||||
if (props.allowHalf) {
|
||||
// TODO: use cache via computed https://github.com/element-plus/element-plus/pull/5456#discussion_r786472092
|
||||
let target = event.target as HTMLElement
|
||||
if (hasClass(target, ns.e('item'))) {
|
||||
target = target.querySelector(`.${ns.e('icon')}`)!
|
||||
}
|
||||
|
||||
function resetCurrentValue() {
|
||||
if (rateDisabled.value) {
|
||||
return
|
||||
}
|
||||
if (props.allowHalf) {
|
||||
pointerAtLeftHalf.value =
|
||||
props.modelValue !== Math.floor(props.modelValue)
|
||||
}
|
||||
currentValue.value = props.modelValue
|
||||
hoverIndex.value = -1
|
||||
if (target.clientWidth === 0 || hasClass(target, ns.e('decimal'))) {
|
||||
target = target.parentNode as HTMLElement
|
||||
}
|
||||
pointerAtLeftHalf.value = event.offsetX * 2 <= target.clientWidth
|
||||
currentValue.value = pointerAtLeftHalf.value ? value - 0.5 : value
|
||||
} else {
|
||||
currentValue.value = value
|
||||
}
|
||||
hoverIndex.value = value
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
currentValue.value = val
|
||||
pointerAtLeftHalf.value =
|
||||
props.modelValue !== Math.floor(props.modelValue)
|
||||
}
|
||||
)
|
||||
function resetCurrentValue() {
|
||||
if (rateDisabled.value) {
|
||||
return
|
||||
}
|
||||
if (props.allowHalf) {
|
||||
pointerAtLeftHalf.value = props.modelValue !== Math.floor(props.modelValue)
|
||||
}
|
||||
currentValue.value = props.modelValue
|
||||
hoverIndex.value = -1
|
||||
}
|
||||
|
||||
if (!props.modelValue) {
|
||||
emit(UPDATE_MODEL_EVENT, 0)
|
||||
}
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
currentValue.value = val
|
||||
pointerAtLeftHalf.value = props.modelValue !== Math.floor(props.modelValue)
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
ns,
|
||||
hoverIndex,
|
||||
currentValue,
|
||||
rateDisabled,
|
||||
text,
|
||||
decimalStyle,
|
||||
decimalIconComponent,
|
||||
iconComponents,
|
||||
rateKls,
|
||||
if (!props.modelValue) {
|
||||
emit(UPDATE_MODEL_EVENT, 0)
|
||||
}
|
||||
|
||||
showDecimalIcon,
|
||||
getIconStyle,
|
||||
selectValue,
|
||||
handleKey,
|
||||
setCurrentValue,
|
||||
resetCurrentValue,
|
||||
}
|
||||
},
|
||||
defineExpose({
|
||||
/** @description set current value */
|
||||
setCurrentValue,
|
||||
/** @description reset current value */
|
||||
resetCurrentValue,
|
||||
})
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user