美文网首页
vue插件的创建,开发,发布(可自由拖拽,拉伸的面板)

vue插件的创建,开发,发布(可自由拖拽,拉伸的面板)

作者: 我爱喝可乐123 | 来源:发表于2018-08-28 15:31 被阅读0次

    现在以插件名为 vue-drag-infinite为例,具体内容可通过以下方式进行下载
    github查看源代码

    npm install --save vue-drag-infinite
    

    第一步初始化一个项目

    封装vue的插件用webpack-simple很合适,使用命令:vue init webpack-simple vue-gitment 进行项目初始化,项目结构如下图所示:


    初始化项目结构

    1 首先打开清除掉无用的文件 具体清除内容为:

    1.src下的所有文件
    2.根目录下的 index.html 文件

    2 修改根目录下的 package.json 里的内容

    {
      "name": "vue-drag-infinite",// 插件名称 再初始化项目的时候 可以设置 也可以在这里进行修改
      "description": "A Vue.js project",//插件描述
      "version": "1.1.2",//版本号 每次向npm上 publish的时候要修改一下 自增的形式
      "author": "zhaosq <615683167@qq.com>",
      "license": "MIT",//许可证
      "private": false,//默认是true 私人的 需要改为false 
      "main":"dist/vue-drag-infinite.js",//这个超级重要 决定了你 import xxx from “vue-drag-infinite” 它默认就会去找 dist下的vue-drag-infinite 文件
      "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
        "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
      },
      "dependencies": {
        
      },
      "browserslist": [
        "> 1%",
        "last 2 versions",
        "not ie <= 8"
      ],
      "devDependencies": {
        "babel-core": "^6.26.0", // 依赖包名称  以及对应的版本号
        ........ 此处依赖吧不做解释
      }
    }
    

    3.修改根目录下方的 webpack.config.js文件内容

    var path = require('path')
    var webpack = require('webpack')// commonjs 的形式引入webpack
    module.exports = {
      // entry: './src/main.js',
      entry: './src/lib/index.js',//文件入口
      output: {//文件出口配置
        path: path.join(__dirname, './dist'),// 出口路径
        publicPath: '/dist/',//build打包路径
        filename: 'vue-drag-infinite.js',//打包后文件名称  设置为与插件名称一致
        libraryTarget:'umd',//libraryTarget会生成不同umd的代码,可以只是commonjs标准的,也可以是指amd标准的,也可以只是通过script标签引入的。
        library:'VueDragInfinite',//library指定的就是你使用require时的模块名,这里便是require("VueDragInfinite")
        umdNamedDefine:true//会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define。
      },
      module: {.....},//对应 vue文件 js文件 css文件 url文件 sass文件 style行内样式 进行解析
      devtool: '#eval-source-map',//相关选项有几种 不再过多解释,现在要做的是在打包后不再生成.map结尾的文件  将值设为 false
    }
    

    4.进行插件内容的编写 根据vue官网要求 需要使用 install

    先在 src文件下创建 lib文件夹 在lib文件夹下创建一个 index.js 和一个 vue-drag-infinite.vue文件
    index.js文件内容如下

    import vueDragInfinite from './vue-drag-infinite.vue'
    const dragInfinite = {
        install(Vue, options) {
            Vue.component(vueDragInfinite.name, vueDragInfinite) // vuePayKeyboard.name 组件的name属性
            // 类似通过 this.$xxx 方式调用插件的 其实只是挂载到原型上而已
            // Vue.prototype.$xxx  // 最终可以在任何地方通过 this.$xxx 调用
            // 虽然没有明确规定用$开头  但是大家都默认遵守这个规定
        }
    }
    if (typeof window !== 'undefined' && window.Vue) {
        window.Vue.use(dragInfinite);
    }
    export default dragInfinite;
    

    vue-drag-infinite.vue文件内容如下

    <template>
        <div class="contain" ref="dragContain">
            <div class="control" v-drag="contain">
                <div style="line-height:30px;background:#409EFF;cursor:move;color:#fff;text-indent:15px;">
                    控制面板
                </div>
                <div style="padding:7px;" @mousedown="mouseDown($event,false)">
                    <el-form ref="form" size="mini" label-width="70px">
                      <el-form-item label="模板名称">
                        <el-input v-model="name"></el-input>
                      </el-form-item>
                      <el-row  v-if="json.length">
                          <el-form-item>
                            <el-button type="primary" @click="onSave">保存</el-button>
                          </el-form-item>
                          <el-form-item label="宽度">
                            <el-input v-model.lazy="json[divindex].style.width"></el-input>
                          </el-form-item>
                          <el-form-item label="高度">
                            <el-input v-model.lazy="json[divindex].style.height"></el-input>
                          </el-form-item>
                          <el-form-item label="字体大小">
                            <el-select v-model.lazy="json[divindex].style.fontSize" placeholder="请选择字体大小">
                              <el-option label="12px" value="12px"></el-option>
                              <el-option label="14px" value="14px"></el-option>
                              <el-option label="16px" value="16px"></el-option>
                              <el-option label="18px" value="18px"></el-option>
                            </el-select>
                          </el-form-item>
                          <el-row>
                              <el-col :span="12">
                                <el-form-item label="背景颜色">
                                <el-color-picker v-model.lazy="json[divindex].style.backgroundColor" show-alpha></el-color-picker>
                                </el-form-item>
                              </el-col>
                              <el-col :span="12">
                                <el-form-item label="文字颜色">
                                <el-color-picker v-model.lazy="json[divindex].style.color"></el-color-picker>
                                </el-form-item>
                              </el-col>
                          </el-row>
                            
                          <el-form-item label="文字内容">
                            <el-input type="textarea" v-model="json[divindex].text"></el-input>
                          </el-form-item>
                      </el-row>
                        <el-row>
                          <el-button type="primary" size="mini" @click="addDive()">新增div</el-button>
                        </el-row>
                    </el-form>
                </div>
            </div>
            
            <div v-drag="contain" class="drag" :class="{active:index == divindex}" v-if="json.length" v-for="(item,index) in json" @click="moveDiv(index,$event)" :style="item.style">
                {{item.text}}
                <i class="el-icon-menu sacle" v-if="index == divindex" @click="sacle($event)" @mousedown="mouseDown($event,true)"  unselectable="on"></i>
                <el-button type="danger" class="del"  @click="del(index,$event)" v-if="index == divindex" icon="el-icon-delete" circle></el-button>
            </div>
            <div v-if="!json.length">暂时没有内容哦!!期待您的编辑</div>
        </div>
    </template>
    <script >
    export default {
        name:'vue-drag-infinite', // 此处name名称  在index.js 文件中有引用  所以最好跟插件名称一致,避免chux
        props: {
            json: {
                type: Array,
                default: []
            },
            name: {
                type: String,
                default: '小清新'
            },
        },
        data(){
            return {
                //外层容器的宽高 数值不带px单位
                contain:{
                    xx:500,
                    yy:500
                },
                //存放拉伸放大时的  div的原始宽高 带px单位
                movejson:{
                    moveWidth:'',
                    moveHeight:''
                },
                divindex:0,//当前选中div的序号  默认为0
            }
        },
        mounted(){  
            this.contain.xx = this.$refs.dragContain.offsetWidth;
            this.contain.yy = this.$refs.dragContain.offsetHeight;
        },
        methods:{
            // 字符串转json对象
            toJson(str){
              let _str =eval('(' + str + ')');
              return _str;
            },
            //外层div点击选择事件 绑定右上角设置面板
            moveDiv(index,e){
                let jsonNew = this.toJson('{"'+e.target.style.cssText.replace(/\; +/g, "\",\"").replace(/\: +/g, "\":\"").replace(/\;+/g, "").replace(/-\w/g, function ($) {return $.slice(1).toUpperCase();})+'"}');
                //当前选中div的序号
                this.divindex = index;
                // 设置div框的 各种属性
                for (let em in jsonNew) {
                    this.json[index].style[em]= jsonNew[em]; 
                }
                this.json[index].text= e.target.innerText;
            },
            //添加一个div块 默认的
            addDive(){
                let newJson = {
                    style:{
                        width:"80px",
                        height:"50px",
                        fontSize:"14px",
                        color:"#ffffff",
                        backgroundColor:"#333333"
                    },
                    text:'新的div'
                };
                this.json.push(newJson);
            },
            //删除当前div
            del(i,e){
                this.json.splice(i, 1);
                if(i == this.json.length){
                    this.divindex = 0;
                }
                e.stopPropagation();
            },
            onSave(){
                let data = this.json;
                this.$emit('save',data)
            },
            //div上拉伸的阻止冒泡事件
            sacle(e){
                e.stopPropagation();
            },
            //div上拉伸的 放大 缩小div宽高
            mouseDown(e,type){
                if(type){
                    let that = this;
                    let oldX = e.pageX,oldY = e.pageY;
                    that.movejson.moveWidth = that.json[that.divindex].style.width;
                    that.movejson.moveHeight = that.json[that.divindex].style.height;
                    document.onmousemove = function (e){
                        let newX = e.pageX - oldX;
                        let newY = e.pageY - oldY;
                        that.json[that.divindex].style.width = ((newX+ parseInt(that.movejson.moveWidth))>=80?(newX+ parseInt(that.movejson.moveWidth)):'80')+'px';
                        that.json[that.divindex].style.height = ((newY+ parseInt(that.movejson.moveHeight))>=50?(newY+ parseInt(that.movejson.moveHeight)):'50')+'px';
                    }
                    document.onmouseup = function(){
                        document.onmousemove = document.onmouseup = null;
                    }
                }
                e.stopPropagation();
            }
        },
        computed: {
        },
        directives:{
            drag:{
                bind: function (el, binding, vnode) {
                  el.onmousedown = function(e){
                    var disx = e.clientX - el.offsetLeft;
                    var disy = e.clientY - el.offsetTop;
                    document.onmousemove = function (e){
                        let left = e.clientX - disx;
                        let top = e.clientY - disy;
                        if(left<0){
                            left = 0;
                        }
                        if(top<0){
                            top = 0;
                        }
                        if(left>binding.value.xx-el.offsetWidth){
                            left = binding.value.xx-el.offsetWidth;
                        }
                        if(top>binding.value.yy-el.offsetHeight){
                            top = binding.value.yy-el.offsetHeight;
                        }
                        el.style.left = left+'px';
                        el.style.top = top+'px';
                    }
                    document.onmouseup = function(){
                        document.onmousemove = document.onmouseup = null;
                    }
                }
              },
            }
        }
    
    }
    
    </script>
    <style lang='scss' scoped>
        ul,li{margin:0px;list-style:none;padding:0px;}
        .contain{height: 700px;background:#ddd; position: relative;user-select:none;}
        .el-form-item--mini.el-form-item{
            margin-bottom:7px;
        }
        .drag{
                width: 100px;
                height: 100px;
                position: absolute;
                top: 0;
                left: 0;
                cursor:move;
                background-color: red;
                border:1px solid #FFF;
                line-height:1.7;
                box-sizing:border-box;
                color:#fff;
                overflow: hidden;
                padding:5px;
                .sacle{
                    position:absolute;
                    right:0px;
                    bottom:0px;
                    background-color:#909399;
                    cursor: se-resize;
                    font-size:15px;
                }
                .del{
                    position:absolute;
                    top:0px;
                    right:0px;
                    padding:5px;
                    box-shadow:0px 0px 10px rgba(255, 255, 255,0.5);
                }
        }
        .drag.active{
            border-radius:5px;
            border:1px solid #85ce61;
            box-shadow:0px 0px 20px rgba(0,0,0,0.5);
            
        }
        .control{
            width:250px;
            border-radius:5px;
            overflow:hidden;
            background-color:#B3C0D1;
            position:absolute;
            z-index:999;
            right:20px;
            top:15px;
        }
    
    </style>
    

    5.插件打包 build

    npm run build 在dist文件夹中会出现一个vue-drag-infinite.js 文件
    由于在webpack.config.js 中设置了 devtool:false,所以不会出现.map文件

    下一步 npm插件的发布

    首先在npm官网上进行账号的注册,各位自行注册
    下载git工具,在git官网上进行下载 主要有俩个命令

    npm login //登陆
    npm publish //上传
    

    publish后的文件找不到dist文件夹
    原因是我们的忽略文件默认忽略了 dist 文件
    修改根目录下的 .gitignore 去掉忽略dist

    git登陆上传详情
    关于出现各种npm publish 失败的情况 可以观看本人另一篇文章
    点击这里

    最后说一下 关于插件的使用描述 md文件的编写

    详细语法可以自行百度


    代码编写区域
    # h1标签  ## h2标签 ###### h6 标签
    

    以上内容 个人手打与总结,有错误的地方还望各位大神指出

    相关文章

      网友评论

          本文标题:vue插件的创建,开发,发布(可自由拖拽,拉伸的面板)

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