zoukankan      html  css  js  c++  java
  • 在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

    下面回到正题:

    代码目录结构:

    ./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>

    运行效果:

  • 相关阅读:
    Linux上安装Oracle 10g 装后感
    分享16个javascript&jQuery的MVC教程
    6个出色的基于JQuery的Tab选项卡实例
    8 个高可用的 jQuery 表单验证插件
    6 套多点触摸屏的手势图标集
    PHP V5.3 中的新特性,第 4 部分: 创建并使用 Phar 归档
    精选15个国外最流行的CSS框架
    PHP V5.3 中的新特性,第 1 部分: 对象接口的变化
    分享10个便利的HTML5/CSS3框架
    XAMPP下pear安装
  • 原文地址:https://www.cnblogs.com/qicao/p/10805715.html
Copyright © 2011-2022 走看看