在Vue将第三方JS库封装为组件使用

第三方JS库地址:https://github.com/inorganik/CountUp.js

使用NPM进行安装:

npm install --save countup

根据官方回答,CountUp.js是一个无依赖,轻量级的Javascript类,可用于快速创建以更有趣的方式显示数值数据的动画。

在代码开始之前,先补充几个Vue.js的基础知识:

1.this._uid的使用:每个组件都有一个唯一的id,可以作为this._uid访问。

具体使用场景:组件是要在多个地方多次使用 ,而一个页面上每一个id值都要互不相同。如果id值固定的话 在多次使用这个组件的时候就会出现多个元素的id都是同一个值。

2.计算属性computed

设计它的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。

使用官网的例子通俗易懂:

<div id="example">
{{ message.split('').reverse().join('') }}
</div>

在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。所以,对于任何复杂逻辑,你都应当使用计算属性。

<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})

2.1计算属性和方法的区别:

计算属性是基于它们的响应式依赖进行缓存的,只在相关响应式依赖发生改变时它们才会重新求值,两者的计算结果完全相同

2.1计算属性和侦听属性(Watch)的区别:

   计算属性更适合于通常的场景,如下代码:

<div id="demo">{{ fullName }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})

若改为计算属性则可以缩减代码量:

var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

3.组件的默认值写法。

当组件的属性类型时Object或者Array时,需要使用工厂函数返回'的默认值(注意括号):

props: {
yourProp: {
type: Object,
default: () => ({
param: value,
param2: value,
}),
},
}
props: {
arr: {
type: Array,
default: function () { return [] }
}
}
//ES6写法
props: {
arr: {
type: Array,
default: () => []
}
}

4.在Vue中获取并操作dom:

要在mounted中使用,因为只有在执行mounted的时候,vue已经渲染了dom节点,这个时候是可以获取dom节点的,vue中尽量不去操作dom元素,选用ref操作属性获取。

<button ref="btn">获取ref</button>
this.$refs.btn.style.backgroundColor="#ff0000"

 5.理解Vue中的nextTick

应用场景:需要在视图更新之后,基于新的视图进行操作。

具体可参考:https://segmentfault.com/a/1190000012861862?utm_source=tag-newest

下面回到正题:

代码目录结构:

在Vue将第三方JS库封装为组件使用

./src/components/count-to/count-to.less:

  .count-to-number{
color: palevioletred;
}

./src/components/count-to/count-to.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>

./src/components/count-to/index.js:

import CountTo from './count-to.vue'
export default CountTo

./src/router/router.js增加对count-to.vue的路由:

{
path: '/count-to',
name: 'count_to',
component: () => import('@/views/count-to.vue')
}

./src/views/count-to.vue:

<template>
<div>
<count-to ref="countTo" :end-val="endVal" @on-animation-end="handleEnd">
<span slot="left">总金额:</span>
<span slot="right">元</span>
</count-to>
<button @click="getNumber">获取数值</button>
<button @click="up">更新值</button>
</div>
</template>
<script>
import CountTo from "@/components/count-to";
export default {
name: "count_to",
components: {
CountTo
},
data() {
return {
endVal: 100
};
},
methods: {
getNumber() {
this.$refs.countTo.getCount();
},
up() {
this.endVal += Math.random() * 100;
},
handleEnd(endVal) {
console.log("end -> ", endVal);
}
}
};
</script>

运行效果:

在Vue将第三方JS库封装为组件使用

上一篇:Vue中如何引入第三方icon库(阿里巴巴矢量图标库)


下一篇:Hibernate二级缓存(未完待续)