mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(Rate): 当使用 readonly 和 allow-half 时支持 modelValue 设置小数 (#8528)
* feat(Rate): 当使用readonly和allow-half时支持modelValue设置小数 * docs(Rate): 完善文档 * docs(Rate): update snapshot * docs(Rate): add description of decimal value Co-authored-by: neverland <chenjiahan@buaa.edu.cn>
This commit is contained in:
parent
8e4e6d54a6
commit
8fb3560f39
@ -88,6 +88,23 @@ export default {
|
||||
<van-rate v-model="value" readonly />
|
||||
```
|
||||
|
||||
### Readonly Half Star
|
||||
|
||||
```html
|
||||
<van-rate v-model="value" readonly />
|
||||
```
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const value = ref(3.3);
|
||||
return { value };
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Change Event
|
||||
|
||||
```html
|
||||
|
@ -88,6 +88,25 @@ export default {
|
||||
<van-rate v-model="value" readonly />
|
||||
```
|
||||
|
||||
### 只读状态显示小数
|
||||
|
||||
设置 `readonly` 和 `allow-half` 属性后,Rate 组件可以展示任意小数结果。
|
||||
|
||||
```html
|
||||
<van-rate v-model="value" readonly allow-half />
|
||||
```
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const value = ref(3.3);
|
||||
return { value };
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 监听 change 事件
|
||||
|
||||
```html
|
||||
|
@ -15,18 +15,34 @@ const [name, bem] = createNamespace('rate');
|
||||
|
||||
type RateStatus = 'full' | 'half' | 'void';
|
||||
|
||||
type RateListItem = {
|
||||
status: RateStatus;
|
||||
value: number;
|
||||
};
|
||||
|
||||
function getRateStatus(
|
||||
value: number,
|
||||
index: number,
|
||||
allowHalf: boolean
|
||||
): RateStatus {
|
||||
allowHalf: boolean,
|
||||
readonly: boolean
|
||||
): RateListItem {
|
||||
if (value >= index) {
|
||||
return 'full';
|
||||
return { status: 'full', value: 1 };
|
||||
}
|
||||
if (value + 0.5 >= index && allowHalf) {
|
||||
return 'half';
|
||||
|
||||
if (value + 0.5 >= index && allowHalf && !readonly) {
|
||||
return { status: 'half', value: 0.5 };
|
||||
}
|
||||
return 'void';
|
||||
|
||||
if (value + 1 >= index && allowHalf && readonly) {
|
||||
const cardinal = 10 ** 10;
|
||||
return {
|
||||
status: 'half',
|
||||
value: Math.round((value - index + 1) * cardinal) / cardinal,
|
||||
};
|
||||
}
|
||||
|
||||
return { status: 'void', value: 0 };
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
@ -72,10 +88,17 @@ export default defineComponent({
|
||||
const untouchable = () =>
|
||||
props.readonly || props.disabled || !props.touchable;
|
||||
|
||||
const list = computed<RateStatus[]>(() =>
|
||||
const list = computed<RateListItem[]>(() =>
|
||||
Array(props.count)
|
||||
.fill('')
|
||||
.map((_, i) => getRateStatus(props.modelValue, i + 1, props.allowHalf))
|
||||
.map((_, i) =>
|
||||
getRateStatus(
|
||||
props.modelValue,
|
||||
i + 1,
|
||||
props.allowHalf,
|
||||
props.readonly
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
const select = (index: number) => {
|
||||
@ -130,7 +153,7 @@ export default defineComponent({
|
||||
}
|
||||
};
|
||||
|
||||
const renderStar = (status: RateStatus, index: number) => {
|
||||
const renderStar = (item: RateListItem, index: number) => {
|
||||
const {
|
||||
icon,
|
||||
size,
|
||||
@ -145,8 +168,8 @@ export default defineComponent({
|
||||
disabledColor,
|
||||
} = props;
|
||||
const score = index + 1;
|
||||
const isFull = status === 'full';
|
||||
const isVoid = status === 'void';
|
||||
const isFull = item.status === 'full';
|
||||
const isVoid = item.status === 'void';
|
||||
|
||||
let style;
|
||||
if (gutter && score !== +count) {
|
||||
@ -181,6 +204,7 @@ export default defineComponent({
|
||||
{allowHalf && (
|
||||
<Icon
|
||||
size={size}
|
||||
style={{ width: item.value + 'em' }}
|
||||
name={isVoid ? voidIcon : icon}
|
||||
class={bem('icon', ['half', { disabled, full: !isVoid }])}
|
||||
color={disabled ? disabledColor : isVoid ? voidColor : color}
|
||||
|
@ -39,8 +39,12 @@
|
||||
<van-rate v-model="value6" readonly />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="t('readonlyHalfStar')">
|
||||
<van-rate v-model="value7" readonly allow-half />
|
||||
</demo-block>
|
||||
|
||||
<demo-block v-if="!isWeapp" :title="t('changeEvent')">
|
||||
<van-rate v-model="value7" @change="onChange" />
|
||||
<van-rate v-model="value8" @change="onChange" />
|
||||
</demo-block>
|
||||
</template>
|
||||
|
||||
@ -57,6 +61,7 @@ const i18n = {
|
||||
customStyle: '自定义样式',
|
||||
customCount: '自定义数量',
|
||||
readonly: '只读状态',
|
||||
readonlyHalfStar: '只读状态小数显示',
|
||||
changeEvent: '监听 change 事件',
|
||||
toastContent: (value: number) => `当前值:${value}`,
|
||||
},
|
||||
@ -67,6 +72,7 @@ const i18n = {
|
||||
customStyle: 'Custom Style',
|
||||
customCount: 'Custom Count',
|
||||
readonly: 'Readonly',
|
||||
readonlyHalfStar: 'Readonly Half Star',
|
||||
changeEvent: 'Change Event',
|
||||
toastContent: (value: number) => `current value:${value}`,
|
||||
},
|
||||
@ -82,7 +88,8 @@ export default {
|
||||
value4: 2.5,
|
||||
value5: 4,
|
||||
value6: 3,
|
||||
value7: 2,
|
||||
value7: 3.3,
|
||||
value8: 2,
|
||||
});
|
||||
|
||||
const onChange = (value: number) => Toast(t('toastContent', value));
|
||||
|
@ -225,7 +225,7 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
>
|
||||
</i>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--half van-rate__icon--full"
|
||||
style="font-size: 25px;"
|
||||
style="font-size: 25px; width: 1em;"
|
||||
data-score="0.5"
|
||||
>
|
||||
</i>
|
||||
@ -243,7 +243,7 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
>
|
||||
</i>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--half van-rate__icon--full"
|
||||
style="font-size: 25px;"
|
||||
style="font-size: 25px; width: 1em;"
|
||||
data-score="1.5"
|
||||
>
|
||||
</i>
|
||||
@ -261,7 +261,7 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
>
|
||||
</i>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--half van-rate__icon--full"
|
||||
style="font-size: 25px;"
|
||||
style="font-size: 25px; width: 0.5em;"
|
||||
data-score="2.5"
|
||||
>
|
||||
</i>
|
||||
@ -279,7 +279,7 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
>
|
||||
</i>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--half"
|
||||
style="color: rgb(238, 238, 238); font-size: 25px;"
|
||||
style="color: rgb(238, 238, 238); font-size: 25px; width: 0em;"
|
||||
data-score="3.5"
|
||||
>
|
||||
</i>
|
||||
@ -297,7 +297,7 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
>
|
||||
</i>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--half"
|
||||
style="color: rgb(238, 238, 238); font-size: 25px;"
|
||||
style="color: rgb(238, 238, 238); font-size: 25px; width: 0em;"
|
||||
data-score="4.5"
|
||||
>
|
||||
</i>
|
||||
@ -517,6 +517,98 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div role="radiogroup"
|
||||
class="van-rate van-rate--readonly"
|
||||
tabindex="0"
|
||||
>
|
||||
<div role="radio"
|
||||
class="van-rate__item"
|
||||
tabindex="0"
|
||||
aria-setsize="5"
|
||||
aria-posinset="1"
|
||||
aria-checked="true"
|
||||
>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--full"
|
||||
data-score="1"
|
||||
>
|
||||
</i>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--half van-rate__icon--full"
|
||||
style="width: 1em;"
|
||||
data-score="0.5"
|
||||
>
|
||||
</i>
|
||||
</div>
|
||||
<div role="radio"
|
||||
class="van-rate__item"
|
||||
tabindex="0"
|
||||
aria-setsize="5"
|
||||
aria-posinset="2"
|
||||
aria-checked="true"
|
||||
>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--full"
|
||||
data-score="2"
|
||||
>
|
||||
</i>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--half van-rate__icon--full"
|
||||
style="width: 1em;"
|
||||
data-score="1.5"
|
||||
>
|
||||
</i>
|
||||
</div>
|
||||
<div role="radio"
|
||||
class="van-rate__item"
|
||||
tabindex="0"
|
||||
aria-setsize="5"
|
||||
aria-posinset="3"
|
||||
aria-checked="true"
|
||||
>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--full"
|
||||
data-score="3"
|
||||
>
|
||||
</i>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--half van-rate__icon--full"
|
||||
style="width: 1em;"
|
||||
data-score="2.5"
|
||||
>
|
||||
</i>
|
||||
</div>
|
||||
<div role="radio"
|
||||
class="van-rate__item"
|
||||
tabindex="0"
|
||||
aria-setsize="5"
|
||||
aria-posinset="4"
|
||||
aria-checked="true"
|
||||
>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star-o van-rate__icon"
|
||||
data-score="4"
|
||||
>
|
||||
</i>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star van-rate__icon van-rate__icon--half van-rate__icon--full"
|
||||
style="width: 0.3em;"
|
||||
data-score="3.5"
|
||||
>
|
||||
</i>
|
||||
</div>
|
||||
<div role="radio"
|
||||
class="van-rate__item"
|
||||
tabindex="0"
|
||||
aria-setsize="5"
|
||||
aria-posinset="5"
|
||||
aria-checked="false"
|
||||
>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star-o van-rate__icon"
|
||||
data-score="5"
|
||||
>
|
||||
</i>
|
||||
<i class="van-badge__wrapper van-icon van-icon-star-o van-rate__icon van-rate__icon--half"
|
||||
style="width: 0em;"
|
||||
data-score="4.5"
|
||||
>
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div role="radiogroup"
|
||||
class="van-rate"
|
||||
|
@ -127,3 +127,16 @@ test('should not emit change event when untouchable rate is touchmoved', () => {
|
||||
triggerDrag(wrapper, 100, 0);
|
||||
expect(wrapper.emitted('change')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should get decimal when using allow-half and readonly prop', () => {
|
||||
const wrapper = mount(Rate, {
|
||||
props: {
|
||||
allowHalf: true,
|
||||
readonly: true,
|
||||
modelValue: 3.3,
|
||||
},
|
||||
});
|
||||
|
||||
const item4 = wrapper.findAll('.van-rate__icon--half')[3];
|
||||
expect(item4.style.width).toEqual('0.3em');
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user