NPM-在npm上发布模块

前言

入行前端也不少时间了,之前一直都在使用npm install别人的模块/组件,那么作为一名有追求的前端肯定不会满足一直在用别人的轮子。
今天给大家分享一下如何在npm上发布自己的模块或者组件。

第一章 登录npm

npm adduser //创建用户
or
npm login //登录用户

可以使用

npm whoami

检测用户是否登录上了npm

第二章 发布模块

1.首先安装npm publish

npm i -g publish

2.创建自己的npm模块

创建空文件夹 fm_lindaidai_first

并且在命令行输入

npm init
一路回车

此时会出现package.json

{
  "name": "fm_lindaidai_first",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "lindaidai",
  "license": "ISC"
}

在package.json同级目录下编写date.js

// date.js
(function(global) {
  "use strict";
  var datachange = (function() {
    return function(date) {
      var date = date || new Date();
      if (!date instanceof Date) {
        data = new Date(date);
      }

      if (isNaN(data)) {
        throw TypeError("Invalid date");
      }
      let enDate =
        date.getFullYear() + "." + (date.getMonth() + 1) + "." + date.getDate();
      return enDate;
    };
  })();

  if (typeof define === "function" && define.amd) {
    define(function() {
      return datechange;
    });
  } else if (typeof exports === "object") {
    module.exports = datechange;
  } else {
    global.datechange = datechange;
  }
})(this);

上面的date.js是添加简单的日期转换格式插件

由于命名的是date.js,因此记得将package.json中的“main”修改为date.js

否则别人使用的时候就会报错

3.在npm上发布自己的模块

1.确保自己是登录了npm的

2.确保自己的npm的邮箱被激活了

3.命名不能太简单,最后要有自己的标志,太简单可能是别人已经用过的名字你就不能发布成功,也不要有数字

4.如果是要再次推送同一个项目记得修改该项目版本号。

fm_lindaidai_first的命令行中输入指令

npm publish

成功之后会提示

+ fm_lindaidai_first@1.0.0

若是你编写的模块是第一次发布的,则直接使用指令npm publish就可以了
若是第二次,则需要在package.json中修改一下version,如修改为1.0.1,然后再次执行npm publish就OK。

4.使用自己的模块

可以直接就在项目中使用指令

npm i --save-dev fm_lindaidai_first

接下来可以在项目中使用

var datechange = require('fm_lindaidai_first');
var now = new Date();
var timeStamp = datechange(now);

第三章 创建vue组件并发布

上面介绍发布的模块是一个比较简单的时间格式转换插件,当然你也可以针对某个框架来发布特定的组件。

说一下我要实现的效果:
1.构建一个基于elementUI的表单生成器组件
2.在npm上发布它并使用

3.1 表单构造器组件

想要实现一个表单生成器,我们希望通过prop传入其中,就能构造想要的表单组件
如下:

<template>
  <div>
    <form-generator :schema="schema" v-model="formData"></form-generator>
  </div>
</template>
<script>
export default {
  data() {
    return {
      formData: {
        firstName: "Lin",
        lastName: "DaiDai"
      },
      schema: [
        {
          fieldType: "SelectList",
          name: "food",
          multi: false,
          label: "food",
          options: [
            {
              value: "黄金糕",
              label: "黄金糕"
            },
            {
              value: "双皮奶",
              label: "双皮奶"
            },
            {
              value: "蚵仔煎",
              label: "蚵仔煎"
            },
            {
              value: "龙须面",
              label: "龙须面"
            },
            {
              value: "北京烤鸭",
              label: "北京烤鸭"
            }
          ]
        },
        {
          fieldType: "TextInput",
          placeholder: "First Name",
          label: "First Name",
          name: "firstName"
        },
        {
          fieldType: "TextInput",
          placeholder: "Last Name",
          label: "Last Name",
          name: "lastName"
        },
        {
          fieldType: "NumberInput",
          placeholder: "Age",
          name: "age",
          label: "Age",
          minValue: 0
        }
      ]
    };
  }
};
</script>

向名为from-generator的组件中传递一个数组,就能构建出以下表单列表:


image.png
3.1.1 vue-cli创建vue简单项目
vue init webpack-simple form-lin

我创建的项目名为form-lin

3.1.2 安装elementUI
npm i element-ui -S

可以看到我上面的表单类型是有select、input、numberInput、button这几种,所以我没有引入ele的全部组件,只是按需引入了,按需引入还需要借助 babel-plugin-component

npm install babel-plugin-component -D

然后,将 .babelrc 修改为:

{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

在main.js中引入部分组件

import { Button, Select, Input, Option, InputNumber } from 'element-ui';
Vue.component(Button.name, Button);
Vue.component(Select.name, Select);
Vue.component(Option.name, Option);
Vue.component(Input.name, Input);
Vue.component(InputNumber.name, InputNumber);

通过以上步骤你已经可以在你的这个项目中使用elementUI的部分组件了。

3.1.3 逐个创建表单组件

结合上面的效果图,可以发现此项目创建的表单类型只有下拉框、输入框、数字输入框这三种,所以可以分别创建3种不同的组件

在components文件夹下创建文件夹v5,并在其中分别创建以下三个组件

  • TextInput.vue
  • SelectList.vue
  • NumberInput.vue

TextInput.vue

<template>
  <div class="v5-template">
    <label>{{label}}</label>

    <!-- <input type="text"
           :name="name"
           :value="value"
           @input="$emit('input',$event.target.value)"
           :placeholder="placeholder
           "> -->
    <el-input style="width: 135px;" :name="name"
           :value="value"
           @input="TextInput"
           :placeholder="placeholder" clearable></el-input>
  </div>
           <!-- @input="$emit('input',$event.target.value)" -->
</template>
<script>
import { Input } from 'element-ui';
export default {
  name: 'TextInput',
  props: ['placeholder', 'label', 'name', 'value'],
  methods: {
    TextInput(value) {
      this.$emit('input', value);
    }
  }
}
</script>

注释部分为原生的input标签

SelectList.vue

<template>
  <div class="v5-template">
    <label>{{label}}</label>
    <el-select  :multiple="multi"
                :value="value"
                @change="SelectVal"
                placeholder="请选择">
      <el-option v-for="option in options"
                :key="option.value"
                :label="option.label"
                :value="option.value">
      </el-option>
    </el-select>
  </div>
</template>
<script>
import { Select } from 'element-ui';
import { Option } from 'element-ui';

export default {
  name: 'SelectList',
  props: ['multi', 'options', 'name', 'label', 'value'],
  methods: {
    SelectVal(value) {
      this.$emit('input', value);
    }
  }
}
</script>

NumberInput.vue

<template>
  <div class="v5-template">
    <label>{{label}}</label>
    <!-- <input type="number"
           :name="name"
           :value="value"
           @input="$emit('input',
           $event.target.value)"
    :placeholder="placeholder">-->
    <el-input-number
      :name="name"
      :value="value"
      @change="InputNumber"
      :placeholder="placeholder"
      controls-position="right"
      :min="1"
      :max="10"
    ></el-input-number>
  </div>
</template>
<script>
import { InputNumber } from "element-ui";

export default {
  name: "NumberInput",
  props: ["placeholder", "label", "name", "value"],
  methods: {
    InputNumber(value) {
      this.$emit("input", value);
    }
  }
};
</script>

完成以上步骤,我们创建了三种不同的表单组件
接下来我们需要用一个生成器来将这三种表单组件联系起来

3.1.4 表单生成器

上面所创建的三种不同的组件,其实都可以用component标签来进行引入,只需要改变component标签的:is属性就可以了。

<!--输入框组件-->
<component :is="TextInput"></component>

<!--下拉框组件-->
<component :is="SelectList"></component>

那么我们就可以通过v-for来循环创建不同的表单组件,仅仅只需要改变:is的值就行了

接下来 还是在v5文件夹下,创建文件FormGenerator.vue

FormGenerator.vue

<template>
  <div>
    <component
      v-for="(field, index) in schema"
      :key="index"
      :is="field.fieldType"
      :value="formData[field.name]"
      @input="updateForm(field.name, $event)"
      v-bind="field"
    ></component>
  </div>
</template>

<script>
import NumberInput from "./NumberInput";
import SelectList from "./SelectList";
import TextInput from "./TextInput";
export default {
  name: "FormGenerator",
  components: { NumberInput, SelectList, TextInput },
  props: ["schema", "value"],
  data() {
    return {
      formData: this.value || {}
    };
  },
  methods: {
    updateForm(fieldName, value) {
      this.$set(this.formData, fieldName, value);
      this.$emit("input", this.formData);
    }
  }
};
</script>

v-for不用多说,schema就是我们在引用这个组件时外部传递进来表单数组
:is就是表单组件的类型
@input在使用component标签时,默认的事件名就是为input,值为value

3.1.5 调用表单构造器

完成以上步骤,我们可以在这个项目中本地调用以下这个组件
APP.vue中引用

<template>
  <div>
    <form-generator :schema="schema" v-model="formData"></form-generator>
    <p>Hello {{formData.title}} {{formData.firstName}} {{formData.lastName}}, I hear you are {{formData.age}} years old.</p>
  </div>
</template>
<script>
import FormGenerator from "./components/v5/FormGenerator";
export default {
  name: "formlin",
  components: {
    FormGenerator
  },
  methods: {},
  data() {
    return {
      formData: {
        firstName: "Lin",
        lastName: "DaiDai"
      },
      schema: [
        {
          fieldType: "SelectList",
          name: "food",
          multi: false,
          label: "food",
          options: [
            {
              value: "黄金糕",
              label: "黄金糕"
            },
            {
              value: "双皮奶",
              label: "双皮奶"
            },
            {
              value: "蚵仔煎",
              label: "蚵仔煎"
            },
            {
              value: "龙须面",
              label: "龙须面"
            },
            {
              value: "北京烤鸭",
              label: "北京烤鸭"
            }
          ]
        },
        {
          fieldType: "TextInput",
          placeholder: "First Name",
          label: "First Name",
          name: "firstName"
        },
        {
          fieldType: "TextInput",
          placeholder: "Last Name",
          label: "Last Name",
          name: "lastName"
        },
        {
          fieldType: "NumberInput",
          placeholder: "Age",
          name: "age",
          label: "Age",
          minValue: 0
        }
      ]
    };
  }
};
</script>
<style>
</style>

使用npm run dev打开项目,是可以在页面中看到效果的,此时整个项目目录如下:


style文件夹是我个人创建的公用样式
DemoFive.vue和HellowWorld.vue可以忽略
src/index.js在后面会讲到。

3.2 将整个vue项目发布至npm

要想将vue项目发布至npm上,需要做一些配置

  • 修改package.json

    1. 修改"private": false
      npm默认创建的项目是私有的,如果要发布至npm必须将其公开

    2. 添加"main": "dist/build.js"
      通过import formlin from 'form-lin'引用该组件时,项目会自动找到node_modules/load-ling-zi/dist/build.js

  • 在src加入组件代码App.vue, 并创建我们的导出文件index.js。 在index.js中添加:

import formlin from './App.vue'

export default formlin;

//global 情况下 自动安装
if (typeof window !== 'undefined' && window.Vue) {
    window.Vue.component('formlin', formlin);
}
  • APP.vue中做一些修改
<template>
  <div>
    <h1>Form Generator</h1>
    <form-generator :schema="schema" v-model="formData"></form-generator>
    <el-button @click="outPut">提交</el-button>
    <p>Hello {{formData.title}} {{formData.firstName}} {{formData.lastName}}, I hear you are {{formData.age}} years old.</p>
    <demo-five></demo-five>
  </div>
</template>

<script>
import DemoFive from './components/DemoFive.vue';
import FormGenerator from "./components/v5/FormGenerator";

import { Button } from 'element-ui';
export default {
    name: 'formlin',
    components: {
        DemoFive,
        FormGenerator 
    },
    methods: {
        outPut() {
            this.$emit('submit', this.formData);
        }
    },
    data() {
        return {
            formData: {
                firstName: "Lin",
                lastName: "DaiDai"
            },
            schema: [{...}]
        }
    }
}
</script>

<style>
@import "./style/common.css";
</style>

el-button标签中添加一个click事件,用于输出formData
再将name修改为你要模块的名字,如我这里修改为formlin

  • 因为最后我们是打包成一个js文件,所以需要修改一下配置文件webpack.config.js

因为不是所有使用你组件的人都是通过npm下载和import导入的,很多人是通过<script>直接引入的,我们要将libraryTarget改为umd,以及修改入口文件与设置导出文件目录以及名称。

// webpack.config.js
module.export = {
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "./dist"),
    publicPath: "/dist/",
    filename: "build.js",
    library: "formlin",
    libraryTarget: "umd",
    umdNamedDefine: true
  }
}
  • 最后需要把.gitignore文件里面的/dist删除掉要不然上传时会忽略掉dist打包的文件。

完成上述步骤之后,我们就可以开始正式发布了,首先要将整个项目进行打包
使用指令

npm run build

如果报错,请检查你是否安装了相关的依赖
执行完毕之后,目录下会出现dist文件夹,里面存放的就是压缩的js文件
继续执行指令

npm publish

提示

+ form-lin@1.0.0

则表示发布成功。

3.3 使用vue组件

我们将自己的vue模块已经发布到了npm上面,那么怎样使用它呢。

首先我还是先创建一个vue-cli项目,然后等会再用

npm i form-lin -D

看是否能够使用它。

  • 创建use-form-lin项目
vue init webpack use-form-lin

再使用指令

npm install element-ui -S
npm install form-lin babel-plugin-component -D

需要配置以下

// main.js
import { Button, Select, Input, Option, InputNumber } from 'element-ui';
Vue.config.productionTip = false;
Vue.component(Button.name, Button);
Vue.component(Select.name, Select);
Vue.component(Option.name, Option);
Vue.component(Input.name, Input);
Vue.component(InputNumber.name, InputNumber);

// .babelrc
{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

组件依赖于elementUI 以上步骤是配置elementUI 当然也可以参考elementUI官网全局引用ele组件
传送门elementUI

  • 在APP.vue中使用
<template>
  <div id="app">
    <h3>use form-lin</h3>
    <formlin @submit="submitForm"></formlin>
  </div>
</template>

<script>
import formlin from 'form-lin'
export default {
  name: 'App',
  components: {
    formlin: formlin
  },
  methods: {
    submitForm($event) {
      console.log($event);
    }
  }
}
</script>

使用npm run dev打开页面可以看到效果:

image.png

后语

实现的功能很简单而且也很low ,甚至还要依赖于其他的UI组件,比较创建的这个vue组件里面的表单内容是写死的,你也可以多加一个prop值将内容传进去
最后想说的是 每个人在学习一样新东西的时候肯定都会碰到各种意想不到的情况,有时候你甚至和参考来的代码一模一样都不能实现相同的效果
但希望你能够坚持 在一个胡同了转太久了总是弄不出来一个东西时 你可以选择休息以下或者第二天再弄 总之不要放弃就OK

上面vue组件的源码已经上传只git 有兴趣的小伙可以给个小心心
https://github.com/LinDaiDai/vue/tree/master/form-lin

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容