美文网首页
封装组件/插件至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

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

    相关文章

      网友评论

          本文标题:封装组件/插件至npm

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