render-page.vue
<template>
<div>
<list :list="list" :style="{color: 'red'}">
<count-to slot-scope="count" :end-val="count.number" ></count-to>
</list>
</div>
</template>
<script>
import List from '_c/ulList'
import CountTo from '_c/count-to'
export default {
data() {
return {
list: [
{number: 100 },
{number: 33 }
]
}
},
components: {
List,
CountTo
},
methods: {
renderFunc(h, number) {
return (
<CountTo
on-on-animation-end={this.handleEnd}
endVal={number}
nativeOn-click={this.handleClick}
style={{color: 'pink', fontSize: '40px'}}>{number}</CountTo>
)
},
handleClick(event) {
console.log(event)
},
handleEnd () {
console.log('end!')
}
}
}
</script>
ulList.vue
<template>
<div>
<ul>
<li @mousemove="handleMove" v-for="(item, index) in list" :key="`item_${index}`">
<!-- <span v-if="!render">
{{item.number}}
</span>
<render-dom v-else :render-func="render" :number="item.number"></render-dom> -->
<slot :number="item.number"></slot>
</li>
</ul>
</div>
</template>
<script>
import RenderDom from '_c/render-dom'
export default {
name: 'list',
components: {
RenderDom
},
props: {
list: {
type: Array,
default: () => []
},
render: {
type: Function,
default: () => {}
}
},
methods: {
handleMove(event) {
// 去除鼠标默认事件,例如双击默认选中
event.preventDefault()
}
}
}
</script>
CountTo.vue组件
<template>
<div>
<slot name="left"></slot><span ref="number" :class="countClass" :id="eleId"></span><slot name="right"></slot>
</div>
</template>
<script>
import CountUp from 'countup'
export default {
name: 'CountTo',
computed: {
eleId () {
return `count_up_${this._uid}`
},
countClass () {
return [
'count-to-number',
this.className
]
}
},
data () {
return {
counter: {}
}
},
props: {
/**
* @description 起始值
*/
startVal: {
type: Number,
default: 0
},
/**
* @description 最终值
*/
endVal: {
type: Number,
required: true
},
/**
* @description 小数点后保留几位小数
*/
decimals: {
type: Number,
default: 0
},
/**
* @description 动画延迟开始时间
*/
delay: {
type: Number,
default: 0
},
/**
* @description 渐变时长
*/
duration: {
type: Number,
default: 1
},
/**
* @description 是否使用变速效果
*/
useEasing: {
type: Boolean,
default: false
},
/**
* @description 是否使用变速效果
*/
useGrouping: {
type: Boolean,
default: true
},
/**
* @description 分组符号
*/
separator: {
type: String,
default: ','
},
/**
* @description 整数和小数分割符号
*/
decimal: {
type: String,
default: '.'
},
className: {
type: String,
default: ''
}
},
methods: {
getCount () {
return this.$refs.number.innerText
},
emitEndEvent () {
setTimeout(() => {
this.$nextTick(() => {
this.$emit('on-animation-end', Number(this.getCount()))
})
}, this.duration * 1000 + 5)
}
},
watch: {
endVal (newVal, oldVal) {
this.counter.update(newVal)
this.emitEndEvent()
}
},
mounted () {
this.$nextTick(() => {
this.counter = new CountUp(this.eleId, this.startVal, this.endVal, this.decimals, this.duration, {
useEasing: this.useEasing,
useGrouping: this.useGrouping,
separator: this.separator,
decimal: this.decimal
})
setTimeout(() => {
this.counter.start()
this.emitEndEvent()
}, this.delay)
})
}
}
</script>
<style lang="less">
@import './count-to.less';
</style>