美文网首页
封装组件/插件至npm

封装组件/插件至npm

作者: 懿小诺 | 来源:发表于2020-02-12 16:38 被阅读0次

在说封装上传至npm之前,先了解一下,组件和插件的区别。
借鉴:https://blog.csdn.net/chengQunBin/article/details/82318861

组件封装

首先,要创建项目,封装vue的组件/插件

1.新建一个文件夹smile-test
2.命令行进入文件夹下
3.执行npm init会产生一个package.json文件
4.创建如下目录结构的空文件夹即可

下面我们看一下项目目录结构:


image.png

接下来,
1、在src/component文件夹下创建本例一个组件的文件夹,本例为smileTest2,并在smileTest2文件夹内创建组件文件:本例为smileTest2.vue

2、在该文件中写入要发布的组件内容
下图写一个最简单的组件


image.png

代码如下:

<template>
  <div>
    <h1 class="smile">
      smile 的第一个组件
    </h1>
  </div>
</template>

<script>
  export default {
    name: 'smileTest2',
  };
</script>

<style scoped>
.smile{
  color: aqua
}
</style>

3、在index.js文件里导出组件


image.png

代码如下:

import SmileTest2 from './src/components/smileTest2/smileTest2.vue'
export { SmileTest2 } 

这里要注意export和 export default的区别
https://www.cnblogs.com/sherrycat/p/11152994.html

4、配置发布文件啦!
若没有npm账号,可以先去npm官网https://www.npmjs.com/package/npm注册一下,需要在邮箱内激活才可发布,若没激活,执行npm publish发布会报错,到时候百度也能查到是不是这个原因

注意:上传至npm的组件名称(下图第一个标注name字段)要唯一,不能与npm现有的组件名冲突,会报错
如下:


image.png

5、在终端执行npm publish

上传成功之后,打开npm官网,登录成功后,点击头像-->packages即可看到本账号发布的组件,选择要下载的组件,单击进入详情,如下图:


image.png

点击右侧即可复制 下载使用

使用

1.在需要使用该组件的项目中下载组件包
2.引用组件包
在需要调用本组件的页面引入组件并使用,代码如下:

<template>
  <div>
    <SmileTest2 />
  </div>
</template>

<script>
import { SmileTest2 } from 'smile-test2'
export default {
  name: 'HelloWorld', 
  components:{ SmileTest2 },
  data () {
    return {
      
    }
  }
}
</script>

<style scoped>

</style>

组件封装上传至npm就完成啦!


image.png

插件封装

1.创建项目同组件封装,本例为封装两个弹窗插件,一个输入弹窗,一个提示弹窗
项目目录结构如下:

image.png

2.分别在confirm文件夹下写提示弹窗组件,在confirmInput文件夹下写输入弹窗
为了方便起见,本例就先写提示弹窗:在confirm文件夹下新建confirm.vue文件,和index.js文件
confirm.vue代码如下

<template>
    <div v-if="show_flag">
      <div class="alert-bg"></div>
        <transition name="confirm-bounce">
            <div class="alert-content-cxt" v-show="show_flag">
                <div class="alert-content">
                    <div class="alert-text-content" v-html="confirm_text"></div>
                    <div class="alert-btn-operate">
                        <div v-if="type === 1" class="aler-sure-btnA" @click="confirm()">{{confirm_btn_text}}</div>
                        <div v-if="type === 2">
                            <div class="aler-del-btn" @click="cancel()" >{{cancel_btn_text}}</div>
                            <div class="aler-btn-verticalLine"></div>
                            <div class="aler-sure-btnB" @click="confirm()">{{confirm_btn_text}}</div>
                        </div> 
                    </div>
                </div>
            </div>
        </transition>
    </div>
</template>

<script>
  export default {
    data(){
        return {
            show_flag: 0,
            confirm_text:'我是一个弹框',
            confirm_btn_text:'确定',
            cancel_btn_text:'取消',
            type:1
        }
    },
    created(){

    },
    methods:{
        confirm(){
            console.log('我是点击确认按钮')
        },
        cancel(){
            console.log('我是点击确认按钮')
        }
    },
    mounted(){

    }
  }
</script>

<style scoped>
 /* 弹框和输入弹框的独立样式start*/
.alert-bg {
    width: 100%;
    height: 200%;
    background-color: #000;
    position: fixed;
    top: 0;
    left: 0;
    opacity: 0.7;
    z-index: 9999;
}
.alert-content-cxt {
    text-align: center;
    position: fixed;
    z-index: 10000;
    transform: translate(-50%, -50%) scale(1);
    -webkit-transform: translate(-50%, -50%) scale(1);
    -ms-transform: translate(-50%, -50%) scale(1);
    -moz-transform: translate(-50%, -50%) scale(1);
    top: 40%;
    left: 50%;
    animation: confirm-zoom 0.3s
}

.alert-head-bg {
    width: 25%;
    position: relative;
    top: 15px;
}

.alert-content {
    width: 280px;
    min-height: 100px;
    height: auto;
    background-image: linear-gradient(-78deg, #FFF, #F9F9F9);
    background-image: -moz-linear-gradient(-78deg, #FFF, #F9F9F9);
    background-image: -webkit-linear-gradient(-78deg, #FFF, #F9F9F9);
    border-radius: 5px;
}

.alert-text-content {
    width: 260px;
    height: 50px;
    font-size: 15px;
    line-height: 24px;
    color: #242424;
    text-align: center;
    text-overflow: ellipsis;
    padding: 16px 10px;
    vertical-align: middle;
    display: table-cell;
    box-sizing: content-box;
}
/* 弹框和输入弹框的独立样式end */

/* 弹框和输入弹框的公用样式start */
.alert-btn-operate {
    width: 100%;
    height: 42px;
    border-top: 1px solid #eee;
    line-height: 41px;
    text-align: center;
    font-size: 16px;
}

.aler-sure-btnB,.aler-del-btn {
    width: 48%;
}

.aler-sure-btnB {
    float: right;
    color: #eb5e3b;
}

.aler-sure-btnA {
    width: 100%;
    color: #eb5e3b;
}

.aler-del-btn {
    float: left;
    color: #9E9E9E;
}

.aler-btn-verticalLine {
    width: 1px;
    height: 41px;
    float: left;
    background-color: #eee;
}
/* 弹框和输入弹框的公用样式end */
  .confirm-bounce-enter {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(0.7);
  }
  .confirm-bounce-leave-active {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(0.9);
  }
</style>

index.js

import Vue from 'vue'
import confirm from'./confirm.vue'
const ConfirmConstructor = Vue.extend(confirm);
let instance;
export default{
    ConfirmOpen(options = {}){
        if (!instance) {
            instance = new ConfirmConstructor().$mount(document.createElement('div'));
        }   
        instance.show_flag = 1;
        instance.type = options.type || 1;
        instance.confirm_text = typeof options === 'string' ? options:(options.confirmText || '我是一个弹框');
        instance.confirm_btn_text = options.rightText || '确定';
        instance.cancel_btn_text = options.leftText || '取消';
        document.body.appendChild(instance.$el);
        instance.confirm = () => {        
            if(typeof options.confirmFn !== 'undefined' && typeof options.confirmFn === "function"){
                options.confirmFn();
            }else{
                console.log('弹框确认按钮没有回调按钮');
            }
            document.body.removeChild(instance.$el);
        }
        instance.cancel = () => {        
            if(typeof options.cancelFn !== 'undefined' && typeof options.cancelFn === "function"){
                options.cancelFn();
            }else{
                console.log('弹框取消按钮没有回调按钮');
            }
            document.body.removeChild(instance.$el);
        }
    },
    ConfirmClose(){
        if(instance){
            instance.show_flag = 0;
        }
    }
};

3.插件定义好之后,在项目index.js文件里导出插件
代码如下:

'use strict'
import Confirm from './src/components/confirm/index' // 提示弹窗
import ConfirmInput from './src/components/confirmInput/index' // 输入弹窗
export default {
    install: (Vue, Option) => {
        Vue.$confirm = Vue.prototype.$confirm = Confirm.ConfirmOpen;
        Vue.$confirmInput = Vue.prototype.$confirmInput = ConfirmInput.ConfirmOpen;
    }
}

4.配置发布文件package.json
同组件配置文件

{
  "name": "log56-dialog",
  "description": "smile log56-dialog",
  "version": "1.0.8",
  "author": "smile",
  "license": "MIT",
  "private": false,
  "main": "dist/index.js",
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  },
  "dependencies": {
    "vue": "^2.5.11"
  },
  "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",
    "node-sass": "^4.5.3",
    "sass-loader": "^6.0.6",
    "vue-loader": "^13.0.5",
    "vue-template-compiler": "^2.4.4",
    "webpack": "^3.6.0",
    "webpack-dev-server": "^2.9.1"
  }
}

5.执行npm pubish发布到npm
同样到npm个人packages中,复制指令在终端执行使用

使用

在终端执行完install语句之后,在main.js入口文件中引用


image.png

在需要调用窗口的方法中调用即可。


image.png

至此,插件可以正常使用啦!


image.png

最喜欢这种一运行就正常的页面啦!我在这块踩了好多坑,后期会挨个整理出来。

相关文章