10.Vue技术栈开发实战-Vue中第三方JS库的使用
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232250166-2105381457.png)
创建一个示例页
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232250675-1559936870.png)
路由配置
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232251182-189716431.png)
给这个组件一个名字
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232251714-1904466169.png)
组件都放components文件夹下
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232252059-1307679716.png)
定义组件的name值,可以在其他组件用的时候,获取组件的名称
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232252403-1518239000.png)
把countTo组件引进来,再导出去。这样在使用这个组件的时候,路径只需要写_c/count-to
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232253017-1142350754.png)
引入这个组件只需要这么写就可以了。引进来之后,要在这个实例下注册这个组件。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232253487-979365476.png)
在用的时候,我们建议用这种横线的形式来使用
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232253912-1701772444.png)
开始封装组件
npm install安装这个库
npm install countup -S
组件内把它引入
看看官网的实例,使用CountUp创建一个实例,然后里面可以传入一些参数
参数1:要创建动画的html标签的id值。
最后是一个options对象,里面还有一些参数
首先需要一个基础的标签,我们用span标签,需要给他一个id值。
我们使用CountUp创建实例的时候呢,需要把这个id传进去。那么在哪里去创建这个实例 呢?
在mounted这个生命周期钩子里。它会在你的实例创建并且挂载到html标签上之后,触发,当你调用这个生命周期钩子的时候呢,你的dom元素已经都挂载上了。但是还不确定元素已经渲染完成。
所以我们要确保这个元素渲染完成了,要在this.$nextTick()这个方法里面,传入一个回到函数,当页面的所有Dom都渲染完成后,它会调用nextTikc这个方法里面的回调函数。
我们在这个里面去创建实例,第一个参数是span的id值,比如这里我们定义为cout_up
传入这个id后就会有问题了。你这个组件是要在多个地方多次使用的,页面上每一个元素的id值都要互不相同,不能有一样的id,如果这个地方的id值固定的话,那么多次使用这个组件的时候,就会存在多个相同id的元素。这个时候再去创建这个实例,就会有问题了
所以我们每个组件应该有它自己的id值。使用一个计算属性
保证这个组件的id值,和其他组件的id值不相同呢?每一个vue实例,都有一个属性叫做_uid,每个组件的_uid都不相同。是保证全局唯一的,我们用它来做为组件id的一部分。
前面我们再拼上count_up_
随后把这个eleId绑定到span的id上,这是一个计算属性,我们绑定一个计算属性或者一个数值之类的变量,这个地方要用v-bind的形式来写。
:是v-bind:的简写形式
这样创建CountUp的时候,id就是计算属性了
interface CountUpOptions { startVal?: number; // number to start at (0) decimalPlaces?: number; // number of decimal places (0) duration?: number; // animation duration in seconds (2) useGrouping?: boolean; // example: 1,000 vs 1000 (true) useEasing?: boolean; // ease animation (true) smartEasingThreshold?: number; // smooth easing for large numbers above this if useEasing (999) smartEasingAmount?: number; // amount to be eased for numbers above threshold (333) separator?: string; // grouping separator (',') decimal?: string; // decimal ('.') // easingFn: easing function for animation (easeOutExpo) easingFn?: (t: number, b: number, c: number, d: number) => number; formattingFn?: (n: number) => string; // this function formats result prefix?: string; // text prepended to result suffix?: string; // text appended to result numerals?: string[]; // numeral glyph substitution }
第二个参数是开始动画的值,我们使用属性传入到这个组件内 。属性设置在props里面。类型是number类型的,默认值是0
第三个参数,动画停止的时候,要让他变成哪个值。
这个值是必填的。没有默认值
小数点 后保留几位小数,默认是0
动画要持续多长时间。单位是秒,默认值是2
options:配置对象
还有一些其他的方法
更新值
调用start方法就开始了。
更新方法是在实例对象上去更新,所以创建实例的时候的变量我们要存起来。
我们把它定义在对象里,counter是一个对象。默认是一个空对象。
这样在创建的时候,我们把他存到this.counter里面
dealy设置动画延迟的效果,单位用的是毫秒。默认是0
组件对象调用start方法动画就开始了。我们使用settimeOut的形式来设置延迟。
使用组件
在定义组件的时候endVal是这么定义的。![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232306455-1627344684.png)
但是我们建议在写的时候用横线连接的形式
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232306854-1962137633.png)
定义一个值,比如到100
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232307203-1026537697.png)
gif动图
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200528091815246-1826468698.gif)
前面加个内容可以直接这么写
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232307598-1254236766.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232307944-2049849189.png)
给组件加个样式
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232308253-1242042266.png)
默认的类型是count-to-number
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232308614-429268622.png)
可以再传入一个类名。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232309082-1950103574.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232309497-249082002.png)
组件内部加入文字
这个时候就需要用到vue的内置组件 slot![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232309923-56736841.png)
那么我们组件调用的标签内就可以传入的slot内容
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232310330-58487330.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232310771-840719991.png)
如果有多个slot,需要让固定的内容显示在固定的位置。那我们就给slot一个name值,如果不设置name值就是default
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232311138-489286671.png)
加上slot的name值
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232311562-856336222.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232311910-1981190561.png)
后面显示的字符
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232312256-1846370623.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232312670-534552162.png)
获取dom和vue组件实例
有时候组件有些内部方法,可以供外部使用比如说我们要获取这个组件的span标签显示的数值是多少。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232312990-1431270426.png)
我们就在这里定义个方法
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232313517-19900062.png)
肯定是要获取到这个元素,然后取它里面的内容
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232313961-804609253.png)
可以通过这个id来取,因为我们这个id是唯一的。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232314278-1817819340.png)
还可以通过ref
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232314643-1490025911.png)
给它定义个名字 例如叫做number
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232315025-1300824976.png)
那么如何使用呢。this.$refs.number就是取到当前这个dom元素。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232315456-2053538753.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232315935-408911564.png)
父组件调用子组件的getCount。也是用到了refs。在父组件内调用子组件的地方 定义ref
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232316454-569552796.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232316863-2067828017.png)
ref用在一个封装的组件上,它获取的就是这个组件的实例,如果用在原生的html标签上呢,它获取的就是dom对象。
获取到实例后,那么我们就可以调用这个实例上的方法getCount()方法
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232317296-42569256.png)
增加一个按钮,调用这个方法
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232317735-119688266.png)
打印出了span标签。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232318231-1206485047.png)
那么如何获取到标签里面的值呢?通过innerText
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232318618-776413020.png)
更新值方法封封装
官方封装的方法是update
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232319866-825808331.png)
结束值发生变化的时候,来调用,
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232320200-2053647714.png)
那么我们就用到了监听值的变化。watch。我们来监听endVal这个值的变化。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232320640-1566917054.png)
把新的值传进去。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232321059-1706964716.png)
让传入的值变化,这里要绑定一个变量。endVal默认是100。增加一个按钮。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232321444-935764461.png)
加上0到100的随机数。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232321942-1401003332.png)
![](https://img2020.cnblogs.com/blog/87548/202006/87548-20200622225618493-350744019.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232322241-238110031.png)
点击更新后,变成了253
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232322538-2028884432.png)
它会随即加一个值
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232322820-2107234075.png)
给组件定义事件
当值变化的时候,我们希望有个onChaneg事件,其实你在更新这个值的时候你就知道了值在更新。所以onChange事件就不需要。但是你可能需要知道这个值更新之后的状态
所以我们可以来添加一个值,动画结束之后的事件,首先值更新有一个时间
是我们定义的属性duration。这是一个以秒为单位的值,
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232323213-193384772.png)
当你调用update的时候呢,动画开始。经过了duration结束后,我们来触发一个事件on-animation-end事件
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232323607-1568250965.png)
事件传一个值,结束后的值,我们通过getCount()方法来获取这个值。结束之后呢,得到的是一个字符串。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232324052-1395271795.png)
在外面我们要转换成一个数值类型的
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232324461-518256398.png)
父组件内接收事件
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232324911-956776089.png)
它有个参数enVal就是我们在 子组件内通过emit传过来的
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232325498-546942315.png)
我们来把这个endVal输出一下
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232326118-1606804387.png)
输出的值和实际的值不等
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232326491-1949639602.png)
这是因为存在一个小小的延迟。
我们在子组件内使用 this.nextTick.就是渲染之后。再触发这个事件
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232326881-635517030.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232327325-1364442922.png)
加上5毫秒的延迟
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232327736-524885858.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232328124-1873444388.png)
一开始我们也是需要触发这样一个事件的,所以我们把它封装到一个方法里面共用
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232328504-1713813915.png)
这样默认情况下也会触发这个事件
![](https://img2020.cnblogs.com/blog/87548/202006/87548-20200622230517998-1747693155.png)
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232328990-1718052585.png)
给组件一个初始的样式
我们就less。单独放到count-to.less文件内。![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232329354-2040300220.png)
vue内引入样式
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232329745-391505077.png)
这是我们默认的样式
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232330141-999941010.png)
简单的来定义样式
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232330499-1733951189.png)
数字颜色就会变成粉色
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232330779-1563465902.png)
第二种方法引入less、直接写在组件内。定义less的标签。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232331176-997398570.png)
也可以引入外部的文件。
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232331683-720062236.png)
回顾-定义属性的时候
如果类型是个Object类型, 可以通过回调函数的形式return 返回空对象{}![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232331992-1422152369.png)
也可以返回一个对象,那么这个对象是通过这个函数返回的
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232332323-550605759.png)
如果类型是个数组,可以这么返回
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232332619-810268782.png)
本节代码
![](https://img2020.cnblogs.com/blog/87548/202005/87548-20200523232332919-248916242.png)