封装组件/插件至npm

在说封装上传至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

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

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

推荐阅读更多精彩内容

  • 基于Vue的一些资料 内容 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 element★...
    尝了又尝阅读 1,124评论 0 1
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    小姜先森o0O阅读 9,230评论 0 72
  • Vue2.0+组件库总结 UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基...
    szch阅读 1,867评论 1 52
  • 唐晶是贺涵教出来的,贺涵了解唐晶,他说她是他最满意的作品。在我看来,可以说是师徒,是非常有成就感的一件事。 说男女...
    梁自由阅读 145评论 0 0
  • 剥落的墙纸 破碎的瓦片 腐烂的窗门 清新的空气 数不清的身影 爱过的人总是在夜晚出现 在早晨消失 浮华世界快乐是拥...
    黄秀海阅读 88评论 0 0