实现一个自己定制的函数库-项目初建篇

263 阅读4分钟

前言

写业务这么长时间,总是有些函数需要粘贴来复制去,第三方提供的库总只是部分函数满足自己的需求,你是不是有一种想法,定制一个专给自己用的库函数呢,放着你所有能从业务里抽象出来的函数。或者你对其他库是不是感到好奇而无从得知这是怎么搭建起来的呢,本篇就来和你一步一步搭建一个库,做一个集成markdown文档,集成单测的完整项目。

搭一个库有许许多多的细小的知识点,很难一篇讲的完碰上的所有障碍,于是我决定以写记事的形式来记载我每次的想法以及实现的步骤还有碰上的问题,所以文章会分很多篇,并且持续更新写上我最新放入的函数。

大致规定会有以下目录,并且贴上本项目 github 地址

  • 项目初建
  • hello world
  • 第一个函数 formatTime
  • 单测编写
  • npm 发布相关
  • example 实例文档使用 markdown
  • 第x个函数 ......

项目初建

本人的 vue-cli 版本是 2.8.2,本篇的实例代码都放在这个tag v0.0.1,请自行访问参考。

$ vue init webpack tt-utils

? Project name tt-utils
? Project description ctt's utils library
? Author everlose <ever-lose@foxmail.com>
? Vue build?  standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset?  Standard
? Setup unit tests?  Yes
? Pick a test runner?  karma
? Setup e2e tests with Nightwatch?  No
   vue-cli · Generated "tt-utils".

   To get started:

     cd tt-utils
     npm install
     npm run dev

   Documentation can be found at https://vuejs-templates.github.io/webpack

既然是个人的函数库,自然是照着我自己喜欢的格式来了,我喜欢用 Standard 的 eslint 规则,并且加入 karma 和 mocha 进行 unit 单测,这里不进行业务测试所以不需要 e2e 测试。

以防有人会问 unit test 和 e2e test 什么区别吧,贴个科普链接

hello world

一、本人是忠实的4格党,vue-cli检出的项目却是2格缩进的,所以首先整改 .editorconfig 文件后在全局调整代码格式

.editorconfig

# ...

indent_size = 4

# ...

二、将原 src 文件夹重命名为 example,这个目录很合适作为我们函数库的 demo 演示和说明页面。

三、再新建一个 src 文件夹作为我们的函数库源码所在,并加入一个 src/main.js 文件作为我们的初始函数库,那么就导出一个 hello world 吧。

src/main.js

export default {
    text: 'hello world'
};

四、与此同时得修改 webpack 的编译文件中关于引用src路径的代码,以供能够运行起 example 的代码

build/webpack.base.conf.js

// ...
entry: {
    app: './example/main.js'
}

// ...
alias: {
    'vue$': 'vue/dist/vue.esm.js',
    '@': resolve('example'),
    '~': resolve('src'),
}

// ...
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('example'), resolve('test')],

//...
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('example'), resolve('test')]

package.json

"lint": "eslint --ext .js,.vue src example test/unit/specs",

五、修改 example/main.js 让我们的 demo 能输出 hello world

example/main.js

//...
import ttUtils from '~/main.js';

console.log(ttUtils.text);
//...

六、此时 npm install && npm run dev 启动的时候会发现控制台一堆 eslint 输出的错误,于是再加一步修改 eslint 规则的吧

.eslintrc.js

'rules': {
    // allow paren-less arrow functions
    'arrow-parens': 0,
    // 缩进规定为4个空格
    "indent": [2, 4, {"SwitchCase": 1}],
    // allow async-await
    'generator-star-spacing': 0,
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
    // 语句必须以分号结尾
    "semi": [
        2,
        "always"
    ],
    "no-console": 1,
    "no-alert": 1,
    "space-before-function-paren": [0, "always"]
}

我喜欢带分号结尾,并且缩进是四个空格的代码。保存生效后还得调整一些eslint提示的错误,这里不一一例举,众位看官自己处理吧。

结论

万事总得以hello world开始。

初始化项目的代码放在tag v0.0.1,请自行访问参考。

接着来具体加入第一个函数。

第一个函数 formatTime

呃,我平日里写业务的时候,最为频繁遇见的大概就是时间格式化函数了,公司里的时间格式比较混乱,后端传回来的可能是时间戳,2017-01-01,或者2017/01/01这样的,我也不希望这么简单的一个函数还得引入 moment 来解决。

src 源码

src/formatTime.js

/**
 * 格式化时间函数,create by chentongta。
 *
 * @param  Number  value    [时间戳,number类型,以毫秒为单位]
 * @param  String  format   [格式化的结构,常见填'YYYY/MM/DD hh:mm:ss+S',最多可精确到毫秒级别]
 * @return String           [参照format的格式化结果]
 */

let formatTime = function (value, format) {
    // for example => new Date(null) or new Date('') or new Date(0) or or new Date(undefined)
    if (!value) return '';
    // for example => new Date('2011年12月') or new Date('adsdf')
    if (Number.isNaN(+value)) return value;

    var date = new Date(value);
    // Can't parse to a invalid Date object. for example => new Date(149077400686412312313)
    if (Number.isNaN(date.getTime())) {
        return value;
    }

    var o = {
        'M+': date.getMonth() + 1, // month
        'D+': date.getDate(), // day
        'h+': date.getHours(), // hour
        'm+': date.getMinutes(), // minute
        's+': date.getSeconds(), // second
        'S': date.getMilliseconds() // millisecond
    };

    if (/(Y+)/.test(format)) {
        format = format.replace(RegExp.$1,
            date.getFullYear().toString().substr(4 - RegExp.$1.length));
    }

    for (var k in o) {
        if (new RegExp('(' + k + ')').test(format)) {
            format = format.replace(RegExp.$1,
                RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length));
        }
    }
    return format;
};

export default {
    install (Vue, pluginOptions = {}) {
        // Vue.formatTime, vm.$formatTime
        Vue.formatTime = Vue.prototype.$formatTime = formatTime;
        // {{ time | formatTime('YYYY-MM-DD') }}
        Vue.filter('formatTime', function (value, format) {
            if (!format) {
                return value;
            }
            return formatTime(value, format);
        });
    }
};

哦,对了,工作用的是vue,于是自然就注册成了vue插件来引入,如果有对vue插件不了解的同学,那就去瞧瞧vue 官网吧,当然如果你用的不是vue也不打紧,直接暴露 formatTime 函数也是一样。

src/main.js

import formatTime from './formatTime';

export default { formatTime };

example 示例改写

example/main.js

// ...
import ttUtils from '~/main.js';

Vue.use(ttUtils.formatTime);
//...

注册组件,所有 vue 文件里都能使用。

example/App.vue

{{ time | formatTime('YYYY-MM-DD') }}
{{ time1 }}
{{ time2 }}
...
<script>
import Vue from 'vue';

export default {
    name: 'app',
    data () {
        return {
            time: new Date(),
            time1: new Date(),
            time2: new Date()
        };
    },
    created() {
        this.time1 = Vue.formatTime(this.time1, 'YYYY-MM-DD');
        this.time2 = this.$formatTime(this.time2, 'YYYY-MM-DD');
    }
}
</script>
...

结论

本人运行后顺利页面出现了三个 2017-11-17,那么函数生效了。

添加完第一个函数的版本在 tag v0.0.2

下一篇:npm包发布篇