Vue组件(一)从CountUp.js 组件谈Vue中如何封装组件封装

本文主要从数字渐变组件谈第三方JS库的使用

1.组件封装基础

1.1准备阶段

在views文件夹下新建count-to页面
在路由中进行配置

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

组件封装需要放在components文件夹下,我们在components文件夹下创建count-to文件夹并创建count-to文件

<template>
  <div>
    
  </div>
</template>
<script>
export default {
  name: 'countTo'
}
</script>

在count-to文件夹下创建index.js文件并进行配置,目的是为了便于引入(可以用‘@/components/count-to’引入)

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

在(views)count-to页面组件引入

<template>
  <div>
    <count-to></count-to>
  </div>
</template>
<script>
import CountTo from '@/components/count-to'
export default {
  name: 'count_to',
  components: {
    CountTo
  }
}
</script>
封装组件

安装js库,并在(components)组件中引入并进行配置
countup官方链接.
countup教程解析.

  npm install vue-countupjs
<template>
  <div>
    <span :id="eleId"></span>
  </div>
</template>
<script>
import CountUp from 'countup'
export default {
  name: 'CountTo',
  // 使用计算属性确保id值不重复
  computed: {
    eleId () {
      // 可以根据每个组件的uid都不相同
      return `count_up_${this._uid}`
    }
  },
  // 由于创建的实例在后面需要调用方法,所以把创建的实例存在data中
  data () {
    return {
      counter: {}
    }
  },
  props: {
    // 动画延迟自定义事件(自定义属性)
    delay: {
      type: Number,
      default: 0
    },
    startVal: {
      type: Number,
      default: 0
    },
    endVal: {
      type: Number,
      require: true
    },
    decimals: {
      type: Number,
      default: 0
    },
    duration: {
      type: Number,
      default: 1

    },
    useEasing: {
      type: Boolean,
      default: false
    },
    useGrouping: {
      type: Boolean,
      default: true
    },
    separator: {
      type: String,
      default: ','
    },
    decimal: {
      type: String,
      default: '.'
    }
  },
  // mounted生命周期钩子会在实例挂载到html标签后触发
  mounted () {
    // 当页面上的所有dom都渲染完之后会调用这个回调函数
    this.$nextTick(() => {
      // 创建实例
      // 第一个参数为target用来匹配id值,通过计算属性可以解决id值的问题
      // 第二个参数为startVal,用来定义起始值(通过props属性传入)
      // 第三个参数为endVal,用来定义最终值
      // 第四个参数decimals用来定义小数点后保留几位
      // 第五个参数duration表示动画持续时间
      // 第六个参数为一个配置对象
      // 第一个参数useEasing设置变化速度 true为变速 false为匀速
      // 第二个参数useGrouping设置分组效果 true为变速 false为匀速
      // 第三个参数separatot设置分组符号
      // 第四个参数decimal设置小数分组符号
      this.counter = new CountUp(this.eleId, this.startVal, this.endVal, this.decimals, this.duration, {
        useEasing: this.useEasing,
        useGrouping: this.useGrouping,
        separator: ',',
        decimal: '.'
      })
      setTimeout(() => {
        this.counter.start()
      }, this.delay)
    })
  }
}
</script>

使用封装好的组件

在views中

<template>
  <div>
    <count-to :end-val='100'></count-to>
  </div>
</template>
<script>
import CountTo from '@/components/count-to'
export default {
  name: 'count_to',
  components: {
    CountTo
  }
}
</script>

使用插槽拓展组件

1.单个插槽
在components的组件中定义如下

<slot></slot><span :class="countClass" :id="eleId"></span>

在views页面组件中使用时候

<template>
  <div>
    <count-to :end-val='100'>
      <span>金额</span>
    </count-to>
  </div>
</template>

在这里插入图片描述
2.多个插槽,使用具名属性
在components的组件中定义如下

<template>
  <div>
    <slot name='left'></slot><span :class="countClass" :id="eleId"></span><slot name='right'></slot>
  </div>
</template>

在views页面组件中使用时候,对应slot属性

<template>
  <div>
    <count-to :end-val='100'>
      <span slot="left">金额</span>
      <span slot="right"></span>
    </count-to>
  </div>
</template>

2.组件中使用id值并且操作DOM

2.1使用组件中的方法获取组件中的值

首先我们使用ref为标签定义一个名字

<span ref="number" :class="countClass" :id="eleId"></span>

在methods中使用getCount方法获取dom元素中的值

methods: {
    // 获取当前span标签显示的数值
    getCount () {
      return this.$refs.number.innerText
    }
  }

接下来在父组件中调用,同样定义一个ref

<count-to ref="countTo" :end-val='100'>
      <span slot="left">金额</span>
      <span slot="right"></span>
    </count-to>

在methods中定义方法
ref如果设置在组件上则获取组件实例,设置在标签上则获取dom对象

methods: {
    getNumber () {
    // 获取实例后调用实例上的getCount方法
      this.$refs.countTo.getCount()
    }
  }

触发

    <button @click="getNumber">获取数值</button>

2.2使用组件中的方法更新组件中的值

由于该方法需要在endVal后调用,这里我们使用监听器watch(在components组件页面中)

watch: {
    endVal (newVal, oldVal) {
    // 使用js库中提供的update方法
      this.counter.update(newVal)
    }
  }

在父组件(views)中配置

// 绑定一个值
<count-to ref="countTo" :end-val='endVal'>
      <span slot="left">金额</span>
      <span slot="right"></span>
    </count-to>
data () {
    return {
      endVal: 100
    }
  }
methods: {
    up () {
      this.endVal += Math.random() * 100
    }
  }
    <button @click="up">更新值</button>

2.3为组件添加一个动画结束后的事件

methods: {
    // 获取当前span标签显示的数值
    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()
    }
  }

views部分

   <count-to ref="countTo" :end-val='endVal' @on-animation-end='handleEnd'>
      <span slot="left">金额</span>
      <span slot="right"></span>
    </count-to>

methods: {
    getNumber () {
      console.log(this.$refs.countTo.getCount())
    },
    up () {
      this.endVal += Math.random() * 100
    },
    handleEnd (endVal) {
      console.log('end —> ', endVal)
    }
  }

2.4为组件添加样式

在components文件夹下的count-to文件夹中新建count-to.sass,配置后在组件文件中导入
在组件中配置类名

    <slot name='left'></slot><span ref="number" :class="countClass" :id="eleId"></span><slot name='right'></slot>

computed: {
    countClass () {
      return [
      //组件固有类名
        'count-to-number',
        //组件传入使用的类名
        this.className
      ]
    }
  }
props: {
    className: {
      type: String,
      default: ''
    }
  }
import './count-to.sass'

sass文件中

.count-to-number
    color: red

如果要基于组件原有样式对使用的组件再次设置样式
<template>
  <div>
    <count-to ref="countTo" :end-val='endVal' @on-animation-end='handleEnd'>
      <span slot="left">金额</span>
      <span slot="right"></span>
    </count-to>
     <count-to ref="countTo" :end-val='endVal' @on-animation-end='handleEnd' :class="className">
      <span slot="left">金额</span>
      <span slot="right"></span>
    </count-to>
    <button @click="getNumber">获取数值</button>
    <button @click="up">更新值</button>
  </div>
</template>

在views页面引用组件中定义类名

data () {
    return {
      className: 'dada'
    }
  },

sass文件中

.count-to-number
    color: red
.dada
    font-size: 20px

效果
Vue组件(一)从CountUp.js 组件谈Vue中如何封装组件封装_第1张图片

你可能感兴趣的:(Vue)