ant-design-vue/components/rate/Rate.vue

139 lines
3.1 KiB
Vue
Raw Normal View History

2017-11-01 09:03:42 +00:00
<script>
2017-11-02 07:05:31 +00:00
import Star from './Star.vue'
2017-11-09 09:24:00 +00:00
import Icon from '../icon'
2017-12-20 02:56:21 +00:00
import { getOffsetLeft } from './util'
2017-12-14 04:13:15 +00:00
import { cloneVNodes } from '../_util/vnode'
2018-01-12 08:10:41 +00:00
import hasProp from '../_util/props-util'
2017-11-01 09:03:42 +00:00
export default {
name: 'Rate',
props: {
2017-11-02 07:05:31 +00:00
prefixCls: {
type: String,
default: 'ant-rate',
},
2017-11-01 09:03:42 +00:00
count: {
type: Number,
default: 5,
},
2017-11-02 07:05:31 +00:00
value: Number,
2017-11-01 09:03:42 +00:00
defaultValue: {
type: Number,
default: 0,
},
allowHalf: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
2017-11-02 02:56:18 +00:00
character: {
type: String,
2017-11-02 07:05:31 +00:00
default: '★',
2017-11-02 02:56:18 +00:00
},
2017-11-01 09:03:42 +00:00
},
2017-11-02 07:05:31 +00:00
data () {
const { value, defaultValue } = this
2017-12-27 10:15:11 +00:00
const reValue = !hasProp(this, 'value') ? defaultValue : value
2017-11-01 09:03:42 +00:00
return {
2017-11-09 10:57:34 +00:00
hoverValue: undefined,
2017-11-02 07:05:31 +00:00
stateValue: reValue,
2017-11-01 09:03:42 +00:00
}
},
2017-11-02 07:05:31 +00:00
computed: {
classes () {
const { prefixCls, disabled } = this
return {
[`${prefixCls}`]: true,
[`${prefixCls}-disabled`]: disabled,
2017-11-01 09:03:42 +00:00
}
2017-11-02 02:56:18 +00:00
},
2017-12-13 09:58:05 +00:00
countList () {
return new Array(this.count).fill(1)
},
hasDefaultSlot () {
return !!this.$slots.default
},
2017-11-01 09:03:42 +00:00
},
methods: {
2017-11-02 07:05:31 +00:00
onClick (event, index) {
2017-11-09 09:24:00 +00:00
const value = this.getStarValue(index, event.pageX)
2017-12-27 10:15:11 +00:00
if (!hasProp(this, 'value')) {
this.stateValue = value
}
2017-11-02 07:05:31 +00:00
this.onMouseLeave()
2017-11-09 09:24:00 +00:00
this.$emit('input', value)
this.$emit('change', value)
2017-11-01 09:03:42 +00:00
},
2017-11-02 07:05:31 +00:00
onHover (event, index) {
2017-11-09 09:24:00 +00:00
const value = this.getStarValue(index, event.pageX)
this.hoverValue = value
this.$emit('hover-change', value)
2017-11-01 09:03:42 +00:00
},
getStarDOM (index) {
2017-12-13 09:58:05 +00:00
return this.$refs['stars' + index].$el
2017-11-01 09:03:42 +00:00
},
getStarValue (index, x) {
2017-11-09 09:24:00 +00:00
const { allowHalf, getStarDOM } = this
let value = index + 1
if (allowHalf) {
const leftEdge = getOffsetLeft(getStarDOM(0))
const width = getOffsetLeft(getStarDOM(1)) - leftEdge
if ((x - leftEdge - width * index) < width / 2) {
2017-11-01 09:03:42 +00:00
value -= 0.5
}
}
return value
},
2017-11-02 07:05:31 +00:00
onMouseLeave () {
2017-11-09 09:24:00 +00:00
if (this.disabled) return
this.hoverValue = undefined
this.$emit('hover-change')
2017-11-02 07:05:31 +00:00
},
},
watch: {
2017-11-09 09:24:00 +00:00
value (val) {
this.stateValue = val
2017-11-01 09:03:42 +00:00
},
},
components: {
Star,
Icon,
2017-11-02 07:05:31 +00:00
},
2017-12-14 02:12:19 +00:00
render (createElement) {
2017-12-14 02:17:07 +00:00
const {
classes, onMouseLeave, onClick, countList, onHover,
disabled, prefixCls, allowHalf, hoverValue,
stateValue, character, hasDefaultSlot,
} = this
2017-12-14 02:12:19 +00:00
return (
<ul
2017-12-14 02:17:07 +00:00
class={classes}
onMouseleave={onMouseLeave}>
2017-12-14 02:12:19 +00:00
{
2017-12-14 02:17:07 +00:00
countList.map((item, i) => {
2017-12-14 02:12:19 +00:00
return (
<Star
ref={'stars' + i}
index={i}
2017-12-14 02:17:07 +00:00
disabled={disabled}
prefixCls={`${prefixCls}-star`}
allowHalf={allowHalf}
value={hoverValue === undefined ? stateValue : hoverValue}
onClick={onClick}
onHover={onHover}
2017-12-14 02:12:19 +00:00
key={i}>
2017-12-14 04:15:48 +00:00
{(hasDefaultSlot) ? (cloneVNodes(this.$slots.default, true)) : character}
2017-12-14 02:12:19 +00:00
</Star>
)
})
}
</ul>
)
2017-12-13 09:58:05 +00:00
},
2017-11-01 09:03:42 +00:00
}
</script>