美文网首页
vue 封装通用组件 并发布npm Verdaccio

vue 封装通用组件 并发布npm Verdaccio

作者: HeadSoldier | 来源:发表于2019-07-26 14:57 被阅读0次

    网上看了一些文章,一般都是把封装好的.vue格式的文件发布到npm,感觉不太像一般组件的封装形式,故特意书写此文,希望能帮助到各位码友。
    本文以封装一个分页组件为例,把它build生成目标js文件,pack生成压缩包测试,并发布到npm。

    项目初始化

    封装vue的插件用webpack-simple很合适,vue init webpack-simple vue-gitment 此命令创建我们的项目的目录,创建文件夹和文件,最后结构是这样的

    lib目录是我们的插件目录,其他的默认就好。

    组件内容

    Pagination.vue 的内容如下:

    <template>
        <div class="clearfix box_pagination">
          <div class="laypage_l">
            <label>第&nbsp;</label>
            <label>{{ current }}</label><label>/{{ pagegroup }}&nbsp;页,共{{ total }}条,每页显示{{ display }}条</label>
          </div>
          <div class="laypage_r">
            <ul class="pagination">
              <li :class="{'disabled': current == 1}" v-show="isShowFirst"><a href="javascript:;" class="single" @click="setCurrent(1)"> 首页 </a></li>
              <li :class="{'disabled': current == 1}" v-show="isShowPrev"><a href="javascript:;" class="prev" @click="setCurrent(current - 1)"> 上一页 </a></li>
              <li v-for="p in showPages" :class="{'active': current == p.val}">
                <a href="javascript:;" @click="setCurrent(p.val)" v-if="p.text==='...'" class="noBorder">{{ p.text }}</a>
                <a href="javascript:;" @click="setCurrent(p.val)" v-else> {{ p.text }} </a>
              </li>
              <li :class="{'disabled': current == page}" v-show="isShowNext"><a href="javascript:;" class="next" @click="setCurrent(current + 1)"> 下一页 </a></li>
              <li :class="{'disabled': current == page}" v-show="isShowLast"><a href="javascript:;" class="single" @click="setCurrent(page)"> 尾页 </a></li>
            </ul>
          </div>
        </div>
    </template>
    
    <script>
      export default{
        data(){
          return {
            current: this.currentPage,
            showPages: [],
            isShowFirst: false,
            isShowPrev: false,
            isShowNext: true,
            isShowLast: true
          }
        },
        props: {
          total: {// 数据总条数
            type: Number,
            default: 0
          },
          display: {// 每页显示条数
            type: Number,
            default: 10
          },
          currentPage: {// 当前页码
            type: Number,
            default: 1
          },
          pagegroup: {// 分页条数
            type: Number,
            default: 1,
            coerce: function (v) {
              v = v > 0 ? v : 5;
              return v % 2 === 1 ? v : v + 1;
            }
          }
        },
        computed: {
          page: function () { // 总页数
            return Math.ceil(this.total / this.display);
          }
        },
        methods: {
          getPagesList() {
            let self= this;
            let len = self.page, temp = [];
            if(len <= 5) {  // 当页数小于5
              while (len--) {
                temp.push({text: self.page - len, val: self.page - len});
              }
            } else {
              for(let i=0;i<5;i++) {
                len--;
                temp.push({text: self.page - len, val: self.page - len});
              }
              temp.push({text: '...', val: 6});
            }
            self.showPages = temp;
          },
          setCurrent: function (idx) {
            let self = this;
            if(self.current != idx && idx > 0 && idx < self.page + 1) {
              self.current = idx;
              if(idx === 1) {
                self.isShowFirst = false;
                self.isShowPrev = false;
                self.isShowNext = true;
                self.isShowLast = true;
              } else if (idx == self.page) {
                self.isShowFirst = true;
                self.isShowPrev = true;
                self.isShowNext = false;
                self.isShowLast = false;
              } else {
                self.isShowFirst = true;
                self.isShowPrev = true;
                self.isShowNext = true;
                self.isShowLast = true;
              }
              if(idx > 5) {
                let temp_arry = [], start = idx - 2, end = idx + 2;
                if(end>=self.page) {
                  start = idx - (5 - (self.page-idx) - 1);
                  end = self.page;
                }
                temp_arry.push({text: '...', val: idx - 3});
                for(let i=start;i<=end;i++) {
                  temp_arry.push({text: i, val: i});
                }
                if(idx < (self.page-5/2)) {
                  temp_arry.push({text: '...', val: idx + 3});
                }
                self.showPages = temp_arry;
              } else {
                let temp_arry = [];
                for(let i=1;i<=idx;i++) {
                  temp_arry.push({text: i, val: i});
                }
                if(idx === 5) {
                  temp_arry.push({text: '...', val: idx + 1});
                }
                self.showPages = temp_arry;
              }
              this.$emit('pagechange', this.current);
            }
          }
        },
        mounted() {
          this.getPagesList();
        },
      }
    </script>
    <style>
      .box_pagination {
        padding: 20px 0px;
      }
      .laypage_l {
        float: left;
        width: 30%;
      }
      .laypage_l label {
        color: #999;
      }
      .laypage_r {
        float: right;
        width: 70%;
      }
      .pagination {
        overflow: hidden;
        margin: 0 auto;
        height: 50px;
        text-align: right;
      }
      .pagination li {
        display: inline-block;
        height: 34px;
        margin: 0px 3px;
        color: #666;
      }
      .pagination li .noBorder {
        border: none;
      }
      .pagination li:hover {
      }
      .pagination li:hover a {
        color: #25aae1;
        background: #ebfaff;
      }
      .pagination li a {
        display: block;
        width: 34px;
        height: 34px;
        color: #333;
        text-align: center;
        line-height: 32px;
        font-size: 14px;
        text-decoration: none;
        border: 2px solid #ddd;
        background-color: #f9fbfc;
      }
      .pagination li a.single {
        width: 54px;
      }
      .pagination li a.prev {
        width: 68px;
      }
      .pagination li a.next {
        width: 68px;
      }
      .pagination .active a {
        color: #25aae1;
        background: #ebfaff;
        border: 2px solid #b8dbea;
      }
    </style>
    

    index.js 用来安装组件,内容如下:

    import Pagination from './Pagination.vue'
    
    const pagination={
      install:function (Vue) {
        Vue.component('vPagination',Pagination)
      }
    };
    // 这里的判断很重要
    if (typeof window !== 'undefined' && window.Vue) {
      window.Vue.use(pagination)
    }
    export default pagination
    

    配置文件

    package.json 内容如下:

    {
      "name": "pagination",
      "description": "A Vue.js project",
      "version": "1.0.0",
      "author": "author",
      "license": "MIT",
      "private": false,
      "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
        "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
      },
      "directories": {
        "dist": "dist"
      },
      "dependencies": {
        "vue": "^2.4.4"
      },
      "browserslist": [
        "> 1%",
        "last 2 versions",
        "not ie <= 8"
      ],
      "devDependencies": {
        "babel-core": "^6.26.0",
        "babel-loader": "^7.1.2",
        "babel-preset-env": "^1.6.0",
        "babel-preset-stage-3": "^6.24.1",
        "cross-env": "^5.0.5",
        "css-loader": "^0.28.7",
        "file-loader": "^1.1.4",
        "vue-loader": "^13.0.5",
        "vue-template-compiler": "^2.4.4",
        "webpack": "^3.6.0",
        "webpack-dev-server": "^2.9.1"
      }
    }
    

    webpack.config.js 内容如下:

    module.exports = {
      entry: './src/lib/index.js',
      output: {
        path: path.resolve(__dirname, './dist/js'),
        publicPath: '/dist/',
        filename: 'pagination.js',
        library: 'pagination',
        libraryTarget: 'umd',
        umdNamedDefine: true
      },
      ...... // 其余默认就好 
    };
    

    entry:修改打包的入口文件。
    output:修改输出文件到 dist/js下,生成文件名为pagination.js。
    library:指定的就是你使用require时的模块名,这里便是require("pagination")。
    libraryTarget:会生成不同umd的代码,可以只是commonjs标准的,也可以是指amd标准的,也可以只是通过script标签引入的。
    umdNamedDefine:会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define。

    build

    控制台输入 npm run build,会生成下列文件:


    pack打包生成压缩包

    修改package.json 内容如下:

    {
      "name": "pagination",
      "description": "A vue.js 2.0 project on asynchronous paging ",
      "version": "0.1.0",
      "author": "y",
      "license": "MIT",
      "private": false,
      "main": "dist/js/pagination.js",
      "directories": {
        "dist": "dist"
      },
      "files": [
        "dist",
        "src"
      ],
      "scripts": {
        "dev": "node build/dev-server.js",
        "start": "node build/dev-server.js",
        "build": "node build/build.js"
      },
      "repository": {
        "type": "git",
        "url": "git+https://github.com/yanzilingyan/vue.git"
      },
      "keywords": [
        "vue",
        "pagination",
        "ajax pagination"
      ],
      "dependencies": {
        "vue": "^2.4.4"
      },
      "browserslist": [
        "> 1%",
        "last 2 versions",
        "not ie <= 8"
      ],
      "devDependencies": {
        "babel-core": "^6.26.0",
        "babel-loader": "^7.1.2",
        "babel-preset-env": "^1.6.0",
        "babel-preset-stage-3": "^6.24.1",
        "cross-env": "^5.0.5",
        "css-loader": "^0.28.7",
        "file-loader": "^1.1.4",
        "vue-loader": "^13.0.5",
        "vue-template-compiler": "^2.4.4",
        "webpack": "^3.6.0",
        "webpack-dev-server": "^2.9.1"
      }
    }
    

    控制台输入 npm pack,会看到在当前工程目录下生成了一个文件 pagination-0.1.0.tgz


    项目测试引入

    另外新建一个工程项目,vue init webpack vue-ptest 此命令创建我们的项目的目录,创建文件夹和文件,类似如下结构:



    把刚才打包好的 pagination-0.1.0.tgz 这个压缩包放到E盘目录下(当然哪个位置都行,这里个人只是觉得方便些)。在当前 vue-ptest 这个工程目录下,打开控制台,输入 npm install --save-dev E:pagination-0.1.0.tgz , 安装刚才打包好的文件包。

    修改main.js文件,引入此包,内容如下:

    import Vue from 'vue'
    import App from './App'
    import router from './router'
    import vPagination from 'pagination'
    
    Vue.config.productionTip = false;
    Vue.use(vPagination);
    
    new Vue({
      el: '#app',
      router,
      template: '<App/>',
      components: { App }
    });
    

    修改HelloWorld.vue文件,引入分页组件,内容如下:

    <template>
      <div class="hello">
        <h1>{{ msg }}</h1>
        <h2>Essential Links</h2>
        <vPagination :total="total" :current-page='current' :pagegroup="pagegroup" @pagechange="pagechange" v-if="isShowPagination"></vPagination>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
      data () {
        return {
          msg: 'Welcome to Your Vue.js App',
          total: 1,
          current: 1,
          pagegroup: 10,
          isShowPagination: true
        }
      },
      methods: {
        pagechange(currentPage) {
          console.log('currentPage=',currentPage);
        }
      }
    }
    </script>
    
    <style scoped>
    h1, h2 {
      font-weight: normal;
    }
    ul {
      list-style-type: none;
      padding: 0;
    }
    li {
      display: inline-block;
      margin: 0 10px;
    }
    a {
      color: #42b983;
    }
    </style>
    

    打开控制台,输入 npm run dev ,启动。
    看到界面如下显示:



    OK,分页组件显示正常。

    使用Verdaccio搭建私有npm仓库

    安装nrm 用来切换npm的源。 安装方法:npm install -g nrm

    在控制台输入verdaccio 就可以启动

    修改配置文件

    打开 /***/verdaccio/config.yaml 在文档的末尾加上(已有的修改): listen:XX.XX.XX.XX:4873
    (XX.XX.XX.XX 这个ip尽量能做到在正式环境、测试环境、开发环境都可以访问到的。) 修改后 重新启动 verdaccio

    新建npm 源 nrm add (名) http:XX.XX.XX.XX:4873

    切换npm源 nrm use (名)

    新建用户 npm adduser 根据提示创建用户名、密码 email

    发布私有包的过程

    1.切换npm 源 确定是在内网源上例如((名) http:XX.XX.XX.XX:4873)

    2.npm publish 在自己要发布的包中路径下打这个命令

    3.进入 http:XX.XX.XX.XX:4873 是否成功

    4.成功的话在你的项目里 npm install -seve-dev (vue-gitment项目名)

    安装包

    5.确定是在私有源下(如果需要安装私有包的时候)

    🙏 我姐
    内容原: vuejs2.0 封装通用组件,build生成js,并发布到npm

    相关文章

      网友评论

          本文标题:vue 封装通用组件 并发布npm Verdaccio

          本文链接:https://www.haomeiwen.com/subject/nwtdrctx.html