提交 d36322b6 编写于 作者: richard_1015's avatar richard_1015

refactor: rate

上级 3a1db07d
<template>
<div class="demo">
<h2>基本用法</h2>
<div>
<nut-rate v-model:value="state.val"></nut-rate>
</div>
<nut-rate v-model="state.val" />
<h2>半星</h2>
<nut-rate allow-half v-model="state.val1"></nut-rate>
<h2>自定义 icon </h2>
<div>
<nut-rate
checked-icon="heart-fill1"
unchecked-icon="heart"
v-model:value="state.val3"
></nut-rate>
</div>
<nut-rate
checked-icon="heart-fill1"
unchecked-icon="heart"
v-model="state.val2"
></nut-rate>
<h2>自定义数量</h2>
<div>
<nut-rate :total="6" v-model:value="state.val4"></nut-rate>
</div>
<nut-rate :count="6" v-model="state.val3"></nut-rate>
<h2>自定义颜色</h2>
<div>
<nut-rate active-color="#FFC800" v-model:value="state.val5"></nut-rate>
</div>
<nut-rate active-color="#FFC800" v-model="state.val4"></nut-rate>
<h2>禁用状态</h2>
<div>
<nut-rate :disabled="true" v-model:value="state.val6"></nut-rate>
</div>
<nut-rate disabled v-model="state.val5"></nut-rate>
<h2>只读状态</h2>
<div>
<nut-rate :value="2" :read-only="true"></nut-rate>
</div>
<nut-rate v-model="state.val6" readonly></nut-rate>
<h2>绑定事件,{{ state.result }}</h2>
<div>
<nut-rate @click="onClick"></nut-rate>
</div>
<h2>自定义尺寸</h2>
<div>
<nut-rate :size="35"></nut-rate>
</div>
<nut-rate @change="onChange"></nut-rate>
<h2>自定义尺寸 35px</h2>
<nut-rate v-model="state.val7" icon-size="35"></nut-rate>
</div>
</template>
<script>
import { reactive } from 'vue';
import { reactive, getCurrentInstance } from 'vue';
import { createComponent } from '@/utils/create';
const { createDemo } = createComponent('rate');
export default createDemo({
setup() {
let { ctx } = getCurrentInstance();
const state = reactive({
val: 4,
val: 3,
val1: 3.5,
val2: 3,
val3: 3,
val4: 3,
val5: 3,
......@@ -60,21 +51,16 @@ export default createDemo({
val7: 3,
result: ''
});
const onClick = idx => {
state.result = '您点击了第' + idx + '个!';
const onChange = val => {
state.result = '您点击了第' + val + '个!';
ctx.$toast.text(state.result);
};
return {
state,
onClick
onChange
};
}
});
</script>
<style lang="scss" scoped>
.demo {
}
h4 {
padding: 0 10px;
}
</style>
<style lang="scss" scoped></style>
......@@ -18,98 +18,86 @@ app.use(Rate);
### 基础用法
```html
<nut-rate
v-model:value="state.val"
>
</nut-rate>
``` html
<nut-rate v-model="value" />
```
``` javascript
import { ref } from 'vue';
setup() {
const value = ref(3);
return { value }
}
```
### 自定义icon
```html
<nut-rate
checked-icon="heart-fill1"
unchecked-icon="heart"
v-model:value="state.val3"
>
</nut-rate>
``` html
<nut-rate checked-icon="heart-fill1" unchecked-icon="heart" v-model="value" />
```
### 自定义数量
```html
<nut-rate
:total="6"
v-model:value="state.val4"
>
</nut-rate>
``` html
<nut-rate :total="6" v-model="value" />
```
### 自定义颜色
```html
<nut-rate
active-color="#FFC800"
v-model:value="state.val5"
>
</nut-rate>
``` html
<nut-rate active-color="#FFC800" v-model="value" />
```
### 禁用状态
```html
<nut-rate
:disabled="true"
v-model:value="state.val6"
>
</nut-rate>
``` html
<nut-rate disabled v-model="value" />
```
### 只读
```html
<nut-rate
v-model:value="val"
:readOnly="true"
>
</nut-rate>
``` html
<nut-rate v-model="value" readOnly />
```
### 绑定事件
```html
<nut-rate
@click="onClick"
>
</nut-rate>
``` html
<nut-rate v-model="value" @change="onChange" />
```
``` javascript
import { ref } from 'vue';
setup() {
const value = ref(3);
const onChange = (val)=>{
Toast.text(val);
}
return { value }
}
```
### 自定义尺寸
```html
<nut-rate
:size="35"
>
</nut-rate>
``` html
<nut-rate v-model="value" icon-size="35" />
```
## Prop
| 字段 | 说明 | 类型 | 默认值
| ----- | ----- | ----- | -----
| total | star 总数 | Number | 5
| value | 当前 star 数,可使用 v-model 双向绑定数据 | Number | 0
| size | star 大小 | Number | 25
| spacing | 两个star的间距 | Number | 20
| read-only | 是否只读 | Boolean | false
| unchecked-icon | 使用图标(未选中) | String | -
| checked-icon | 使用图标(选中) | String | -
| 字段 | 说明 | 类型 | 默认值 |
|----------------|-------------------------------------------|---------|-------------|
| count | star 总数 | Number | 5 |
| v-model | 当前 star 数,可使用 v-model 双向绑定数据 | Number | - |
| icon-size | star 大小 | Number | 18 |
| active-color | 自定义图标颜色 | String | #FA200C |
| unchecked-icon | 使用图标(未选中) | String | star-n |
| checked-icon | 使用图标(选中) | String | star-fill-n |
| allow-half | 是否半星 | Boolean | false |
| readonly | 是否只读 | Boolean | false |
| disabled | 是否禁用 | Boolean | false |
| spacing | 间距 | Number | 20 |
## Event
| 字段 | 说明 | 回调参数
|----- | ----- | -----
| click | 点击star时触发 | star的index
\ No newline at end of file
| 字段 | 说明 | 回调参数 |
|--------|----------------------------|----------|
| change | 当前分值修改时时触发的事件 | 当前值 |
\ No newline at end of file
@function toRGB($color) {
@return 'rgb(' + red($color) + ', ' + green($color) + ', ' + blue($color) +
')';
}
@mixin nut-rate-bg($color) {
$svgColor: toRGB($color);
background: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='16' height='16' viewBox='0 0 16 16'%3E %3Cpath fill='#{$svgColor}' d='M16 6.204l-5.528-0.803-2.472-5.009-2.472 5.009-5.528 0.803 4 3.899-0.944 5.505 4.944-2.599 4.944 2.599-0.944-5.505 4-3.899zM8 11.773l-3.492 1.836 0.667-3.888-2.825-2.753 3.904-0.567 1.746-3.537 1.746 3.537 3.904 0.567-2.825 2.753 0.667 3.888-3.492-1.836z'%3E%3C/path%3E %3C/svg%3E")
center no-repeat;
}
@mixin nut-rate-active-bg($color) {
$svgColor: toRGB($color);
background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='16' height='16' viewBox='0 0 16 16'%3E %3Cpath fill='#{$svgColor}' d='M16 6.204l-5.528-0.803-2.472-5.009-2.472 5.009-5.528 0.803 4 3.899-0.944 5.505 4.944-2.599 4.944 2.599-0.944-5.505 4-3.899z'%3E%3C/path%3E %3C/svg%3E");
}
.nut-rate {
.nut-rate-item {
display: inline-block;
vertical-align: bottom;
margin-right: 15px;
display: flex;
&-item {
flex-shrink: 0;
position: relative;
background-size: cover;
&:last-child {
margin-right: 0;
}
&__icon-half {
position: absolute;
width: 50%;
left: 0;
top: 0;
overflow: hidden;
}
}
}
......@@ -2,40 +2,43 @@
<view :class="classes">
<view
class="nut-rate-item"
:class="{ 'nut-rate-active': n <= state.current }"
v-for="n in total"
v-for="n in count"
:key="n"
@click="onClick($event, n)"
:style="{
marginRight: spacing + 'px'
}"
:style="{ marginRight: spacing + 'px' }"
>
<nut-icon
:size="size + 'px'"
:color="n <= state.current ? (disabled ? '#ccc' : activeColor) : '#ccc'"
:name="n <= state.current ? checkedIcon : uncheckedIcon"
>
</nut-icon>
:size="iconSize"
:color="n <= modelValue ? (disabled ? '#ccc' : activeColor) : '#ccc'"
:name="n <= modelValue ? checkedIcon : uncheckedIcon"
/>
<nut-icon
v-if="allowHalf && modelValue + 1 > n"
:class="{ 'nut-rate-item__icon-half': allowHalf }"
:size="iconSize"
:color="activeColor"
:name="checkedIcon"
/>
</view>
</view>
</template>
<script lang="ts">
import { watch, reactive, computed } from 'vue';
import { computed } from 'vue';
import { createComponent } from '@/utils/create';
const { componentName, create } = createComponent('rate');
export default create({
props: {
total: {
count: {
type: [String, Number],
default: 5
},
value: {
modelValue: {
type: [String, Number],
default: 0
},
size: {
iconSize: {
type: [String, Number],
default: 25
default: 18
},
activeColor: {
type: String,
......@@ -49,7 +52,7 @@ export default create({
type: String,
default: 'star-fill-n'
},
readOnly: {
readonly: {
type: Boolean,
default: false
},
......@@ -57,17 +60,17 @@ export default create({
type: Boolean,
default: false
},
allowHalf: {
type: Boolean,
default: false
},
spacing: {
type: [String, Number],
default: 20
default: 14
}
},
emits: ['update:value', 'click'],
emits: ['update:modelValue', 'change'],
setup(props, { emit }) {
const state = reactive({
current: props.value
});
const classes = computed(() => {
const prefixCls = componentName;
return {
......@@ -75,29 +78,25 @@ export default create({
};
});
const onClick = (e: Event, idx: number) => {
const onClick = (e: Event, index: number) => {
e.preventDefault();
e.stopPropagation();
if (props.disabled || props.readOnly) return;
if (idx === 1 && state.current === idx) {
state.current = 0;
if (props.disabled || props.readonly) return;
let value = 0;
if (index === 1 && props.modelValue === index) {
} else {
state.current = idx;
value = index;
if (props.allowHalf) {
if ((e?.target as Element).className.includes('__icon-half')) {
value -= 0.5;
}
}
}
emit('update:value', state.current);
emit('click', state.current);
emit('update:modelValue', value);
emit('change', value);
};
watch(
() => props.value,
newVal => {
state.current = newVal;
}
);
return {
state,
classes,
onClick
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册