rate.vue 3.4 KB
Newer Older
E
Ethan 已提交
1 2 3
<template>
  <!-- the preventDefault of touchmove is to prevent any default action caused by any touchmove event associated with the same active touch point, such as scrolling. -->
  <ul ref="rateContainer"
4 5
      class="cube-rate"
      :class="rateClass"
E
Ethan 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18
      @touchstart.stop="handleStart"
      @touchmove.stop.prevent="handleMove"
      @touchend.stop="handleEnd"
      @mousedown.stop="handleStart"
      @mousemove.stop="handleMove"
      @mouseup.stop="handleEnd">
      <slot>
        <cube-rate-item v-for="n in max" :key="n" :index="n"></cube-rate-item>
      </slot>
    </ul>
</template>

<script type="text/ecmascript-6">
D
dolymood 已提交
19
  import CubeRateItem from './rate-item.vue'
E
Ethan 已提交
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
  const COMPONENT_NAME = 'cube-rate'
  const EVENT_INPUT = 'input'

  const EVENT_TYPE_MOUSE = 'mouse'

  export default {
    name: COMPONENT_NAME,
    props: {
      value: {
        type: Number,
        default: 0
      },
      max: {
        type: Number,
        default: 5
      },
      disabled: {
        type: Boolean,
        default: false
39 40 41 42
      },
      justify: {
        type: Boolean,
        default: false
E
Ethan 已提交
43 44 45 46 47 48 49 50 51 52
      }
    },
    data() {
      return {
        tempValue: this.value
      }
    },
    created() {
      this.mousePressed = false
    },
53 54 55 56 57
    computed: {
      rateClass() {
        return this.justify && 'cube-rate-justify'
      }
    },
E
Ethan 已提交
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    watch: {
      value(val) {
        if (val !== this.tempValue) {
          this.tempValue = val
        }
      }
    },
    methods: {
      handleStart(e) {
        if (!this.disabled) {
          if (e.type.indexOf(EVENT_TYPE_MOUSE) > -1) {
            this.mousePressed = true
            document.addEventListener('mouseup', this.handleEnd)
            document.addEventListener('mousemove', this.handleMove)
          }
          const rect = this.$refs.rateContainer.getBoundingClientRect()
          this.left = rect.left
          this.containerWidth = rect.width
        }
      },
      handleMove(e) {
A
AmyFoxFN 已提交
79 80
        if (!this.disabled && (e.type.indexOf(EVENT_TYPE_MOUSE) === -1 || this.mousePressed)) {
          this.computeTempValue(e.type.indexOf(EVENT_TYPE_MOUSE) === -1 ? e.touches[0] : e)
E
Ethan 已提交
81 82 83
        }
      },
      handleEnd(e) {
A
AmyFoxFN 已提交
84
        if (!this.disabled && (e.type.indexOf(EVENT_TYPE_MOUSE) === -1 || this.mousePressed)) {
E
Ethan 已提交
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
          if (e.type.indexOf(EVENT_TYPE_MOUSE) > -1) {
            this.mousePressed = false
            document.removeEventListener('mouseup', this.handleEnd)
            document.removeEventListener('mousemove', this.handleMove)
          }
          this.computeTempValue(e.type.indexOf(EVENT_TYPE_MOUSE) > -1 ? e : e.changedTouches[0])
          this.$emit(EVENT_INPUT, this.tempValue)
        }
      },
      computeTempValue(touch) {
        let leftAmount = Math.ceil((touch.clientX - this.left) / this.containerWidth * this.max)
        if (leftAmount > 0 && leftAmount <= this.max) {
          this.tempValue = leftAmount
        } else if (leftAmount <= 0) {
          this.tempValue = 0
        } else {
          this.tempValue = this.max
        }
      }
D
dolymood 已提交
104 105 106
    },
    components: {
      CubeRateItem
E
Ethan 已提交
107 108 109 110 111 112 113
    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus">
  @require "../../common/stylus/variable.styl"

114
  .cube-rate
E
Ethan 已提交
115 116
    list-style: none
    display: inline-flex
117
    vertical-align: top
E
Ethan 已提交
118 119
    flex-wrap: nowrap
    max-width: 100%
120 121 122
  .cube-rate-justify
    width: 100%
    justify-content: space-between
E
Ethan 已提交
123
</style>