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

refactor: rate

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