手摸手,带你封装一个vue component

92

项目地址:vue-countTo
配套完整后台demo地址:vue-element-admin
系类文章一:手摸手,带你用vue撸后台 系列一(基础篇)
系类文章二:手摸手,带你用vue撸后台 系列二(登录权限篇)
系类文章三:手摸手,带你用vue撸后台 系列三(实战篇)
系类文章四:手摸手,带你用vue撸后台 系列四(vueAdmin 一个极简的后台基础模板)
系类文章:手摸手,带你优雅的使用 icon

为什么选择自己封装第三方库

最近几个月我司把之前两三年的所有业务都用了 vue 重构了一遍,前台使用 vue+ssr,后台使用了 vue+element,在此过程中封装和自己写了很多 vue component。其实vue 写 component 相当简单和方便,github上有很多的 vue component 都只是简单的包装了一些 jquery 或者原生 js 的插件,但我个人是不太喜欢使用这些第三方封装的。理由如下:

  1. 很多第三方封装的组件参数配置项其实是有缺损的。如一些富文本或者图表组件,配置项远比你想想中的多得多,第三方封装组件很难覆盖全部所有配置。
  2. 第三方组件的更新频率很难保证。很多第三方封装组件并不能一直和原始组件保持同步更新速度,万一原始组件更新了某个你需要的功能,但第三方并没有更新那岂不是很尴尬,而且很多第三方组件维护一段时间之后就不维护了。
  3. 灵活性和针对性。还是那富文本来说,富文本在我司有很多定制化需求,我们需要将图片上传七牛,需要将图片打水印,需要很多针对业务的特殊需求,使用第三方包装的组件是不合适的,一般基于第三方封装的组件是很难拓展的。

所以我觉得大部分组件还是自己封装来的更为方便和灵活一些。

动手开干

接下来我们一起手摸手教改造包装一个js插件,只要几分钟就可以封装一个专属于你的 vue component。封装对象:countUp.js,改造后结果 vue-countTo

首先我们用官方提供的 vue-cli 来构建项目 这里选择了 webpack-simple (组件相对而言比较简单,不需要很多复杂的功能,所以 webpack-simple 已经满足需求了)

$ npm install -g vue-cli
$ vue init webpack-simple my-project
$ cd my-project
$ npm install

安装countup.js

$ npm install countup.js
$ npm run dev

启动项目之后按照 countup.js 官方 demo 初始化插件

app.vue

<template>
  <span ref='countup'></span>
</template>

<script>
import CountUp from 'countup.js'
export default {
  name: 'countup-demo',
  data () {
    return {
      numAnim:null
    }
  },
  mounted(){
    this.initCountUp()
  },
  methods:{
    initCountUp(){
      this.numAnim = new CountUp(this.$refs.countup,0, 2017)
      this.numAnim.start();
    }
  }
}
</script>

刷新页面,就这么简单,countUp.js 已经生效了。
图片描述

接下来查看 countUp.js 的 github 发现它定义了如下可配置参数

clipboard.png

对应 vue 就是 props,类型和初始化一目了然。

props: {
  start: {
    type: Number,
    default: 0
  },
  end: {
    type: Number,
    default: 2017
  },
  decimal: {
    type: Number,
    default: 0
  },
  duration: {
    type: Number,
    default: 2.5
  },
  options: {
    type: Object
  }
}

之后再将countup之前写死的配置项替换为动态props就可以了


this.numAnim = new CountUp(this.$refs.countup, 
                           this.start,
                           this.end,
                           this.decimal,
                           this.duration,
                           this.options)

使用组件

<vue-count-up :end="2500" :duration="2.5"></vue-count-up>

只要几分钟一个属于自己的原生组件就包装好了,就是这么简单。完整demo
这时候你如果觉得使用countUp.js 还有些不满足你的需求,那你可以选择自己来造轮子了。

造轮子篇

首先当然是阅读源码
其实源码也就两部分核心代码
第一部分:主要是就是 requestAnimationFrame,在游览器不支持requestAnimationFrame 的情况下使用 setTimeout 来模拟,这段代码值得仔细阅读,自己在平时的项目中也能借鉴使用这段代码。
第二部分:就是 count 函数
看懂这两部分之后造轮子就相当的简单了, demo

造轮子过程中发现 countUp,并没有 autoplay 这个参数项可以让组件自动开始count,没关系。。。我们可以自己来撸,我们首先定义 autoplay 这个props为布尔值,默认所有组件 autoplay 为 true

 props:{
   autoplay: {
     type: Boolean,
     required: false,
     default: true
   }
 }

定义好 props 之后只要在 mounted 生命周期内加一个判断就完事了。

mounted() {
  if (this.autoplay) {
    this.start();
  }
}

我们的 countUp 组件可以自动 count 了!
clipboard.png

上传 npm

在不跨项目的情况下之前所做的已经满足需求了。但我们不能就此满足,我想让世界上更多的人来使用我的插件,这时候就要上传 npmdemo

首先我们新建一个index.js

import CountTo from './vue-countTo.vue'

// 导出模块
export default CountTo

//global 情况下 自动安装
if (typeof window !== 'undefined' && window.Vue) {
  window.Vue.component('count-to', CountTo)
}

同时我们也要改造一下 webpack 的配置,因为不是所有使用你组件的人都是通过 npm 安装使用 import 引入组件的的。

还有很多人是通过 <script> 标签的方式直接引入的,所以我们要将 libraryTarget 改为 umd 格式

library: 'CountTo',
libraryTarget: 'umd',
umdNamedDefine: true

大功告成,现在只要将它发布到 npm 就可以了,首先注册一个npm 账号,
之后配置自己的 package.json (注意填写 version,每次发布的 version 不能相同;main 为入口文件地址)。
之后只要一行命令 npm publish 你的项目就发到 npm 了,快让小伙伴们一起来用你的vue component 吧!

clipboard.png

总结

这里这是拿了一个很简单的 countUp 组件举了一个简单例子,有的时候自己动手丰衣足食,很多插件的封装比想象中简单的多。产品经理再也不会看到我因为这个fu**插件怎么不支持这个功能而愁眉苦脸了,我们可以更好地满足产品了~~
完整项目地址:https://github.com/PanJiaChen... 欢迎 star

占坑

常规占坑,这里是手摸手,带你用vue撸后台系类
完整项目地址:vue-element-admin
系类文章一:手摸手,带你用vue撸后台 系列一(基础篇)
系类文章二:手摸手,带你用vue撸后台 系列二(登录权限篇)
系类文章三:手摸手,带你用vue撸后台 系列三(实战篇)
系类文章四:手摸手,带你用vue撸后台 系列四(vueAdmin 一个极简的后台基础模板)
系类文章:手摸手,带你优雅的使用 icon
楼主个人免费圈子


如果觉得我的文章对你有用,请随意赞赏
已赞赏

你可能感兴趣的

24 条评论
SeeYouAgain · 2017年04月18日

错别字多的可怕?

回复

1

让技术写文章生不如死

花裤衩 作者 · 2017年04月18日
0

@花裤衩 心疼你一秒,不过你技术确实厉害,给你点个赞。

安静的木马 · 2017年04月18日
0

我心疼你三秒,正在跟随你的脚步,我在github第一个给星的男人,加油,继续领导我。

tzj1413009213 · 7月18日
安静的木马 · 2017年04月18日

github上给你加星了,感觉你是大神,github上描述都是英文。

回复

0

thx

花裤衩 作者 · 2017年04月18日
与国那岛 · 2017年04月19日

你这个下载了全是gif图片,还让我npm 了半天,

回复

0

gif的是占坑项目啊。。。过段时间会开源

花裤衩 作者 · 2017年04月19日
风雅颂 · 2017年06月12日

大神,我是哪里错了?为什么我把你的demo敲一遍,运行时报错了
ERROR Failed to compile with 1 errors 17:50:09

error in ./src/App.vue

http://eslint.org/docs/rules/... Missing space bef
ore value for key 'numAnim'
E:gmldemosrcApp.vue:15:15

    numAnim:null
             ^

http://eslint.org/docs/rules/... Expected indentat
ion of 2 spaces but found 3
E:gmldemosrcApp.vue:18:4

 props: {
  ^

回复

1

eslint,不是代码本身问题

官东东NP · 2017年07月06日
0

谢谢,我已经知道了,因为一开始用eslint,不大懂

风雅颂 · 2017年07月06日
花裤衩 作者 · 2017年06月12日

这是eslint报错。。。错误提示也很明确啊。。

回复

Dian · 2017年06月14日

666已星

回复

爱妹粉丝 · 2017年09月06日

为何我报错了,项目跑不起来
Uncaught Error: Module build failed: SyntaxError: Unexpected token {

at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:373:25)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Module.require (module.js:353:17)
at require (internal/module.js:12:17)
at loadLoader (E:\svnwork\UiSrc\Pages\Vue-project\Vue-project\navdemo\vueAdmin-template\node_modules\loader-runner\lib\loadLoader.js:13:17)
at iteratePitchingLoaders (E:\svnwork\UiSrc\Pages\Vue-project\Vue-project\navdemo\vueAdmin-template\node_modules\loader-runner\lib\LoaderRunner.js:169:2)
at runLoaders (E:\svnwork\UiSrc\Pages\Vue-project\Vue-project\navdemo\vueAdmin-template\node_modules\loader-runner\lib\LoaderRunner.js:362:2)
at NormalModule.doBuild (E:\svnwork\UiSrc\Pages\Vue-project\Vue-project\navdemo\vueAdmin-template\node_modules\webpack\lib\NormalModule.js:179:3)
at NormalModule.build (E:\svnwork\UiSrc\Pages\Vue-project\Vue-project\navdemo\vueAdmin-template\node_modules\webpack\lib\NormalModule.js:268:15)
at Compilation.buildModule (E:\svnwork\UiSrc\Pages\Vue-project\Vue-project\navdemo\vueAdmin-template\node_modules\webpack\lib\Compilation.js:146:10)
at factoryCallback (E:\svnwork\UiSrc\Pages\Vue-project\Vue-project\navdemo\vueAdmin-template\node_modules\webpack\lib\Compilation.js:329:11)
at E:\svnwork\UiSrc\Pages\Vue-project\Vue-project\navdemo\vueAdmin-template\node_modules\webpack\lib\NormalModuleFactory.js:253:5
at E:\svnwork\UiSrc\Pages\Vue-project\Vue-project\navdemo\vueAdmin-template\node_modules\webpack\lib\NormalModuleFactory.js:99:14

回复

小玖_jiu · 2017年11月08日

你这里是对countUp.js 进行再次封装吗? 还是全是自己重新写了!

回复

Awen123 · 3月29日

我npm run dev 运行vue-countTo-master时 页面报错:
Uncaught DOMException: Failed to execute 'createShadowRoot' on 'Element': Shadow root cannot be created on a host which already hosts a shadow tree.
这个问题咋解决

回复

你快乐吗 · 4月22日

楼主辛苦,给我们这些想学习vue的小白提供了很大的便利,给技术大牛致敬,哈哈,已星

回复

亚古 · 4月24日

楼主在哪个厂

回复

pursuitToM · 4月26日

又见花裤衩大大

回复

object · 6月3日

公司马上要用vue开发后台管理 看完大神的文章 有了一点思路 楼主大婶 赞赞赞!

回复

0

帅哥能不能一起交流下,最近也要搞后台管理

pgdragons · 7月9日
前端网 · 6月22日

不错,赞一个。

回复

大柳树村村民 · 8月29日

大佬 有关于混入的文章么 最好是项目中有实际应用那种

回复

黑色技术 · 11月3日

请教下如何把单独的编译成js,引用,就是你上面说的

library: 'CountTo',
libraryTarget: 'umd',
umdNamedDefine: true

这个在哪来配置?

回复

载入中...