插件通常用来为 Vue 添加全局功能
使用插件
通过 Vue 的全局方法 Vue.use() 使用,
当然,在使用这个方法之前,你的 Vue 实例 必须已经初始化完成
// 引入自定义chooseCity 提示框 import chooseCity from './plugin/chooseCity/index' Vue.use(chooseCity)
实际案例:
返回数据格式:
{"data":[{"name":"北京","type":"leafNode","value":110000},{"name":"上海","type":"leafNode","value":310000},{"name":"天津","type":"leafNode","value":120000},{"name":"重庆","type":"leafNode","value":500000},{"name":"安徽","type":"next","value":340000},{"name":"福建","type":"next","value":350000},{"name":"甘肃","type":"next","value":620000},{"name":"广东","type":"next","value":440000},{"name":"广西","type":"next","value":450000},{"name":"贵州","type":"next","value":520000},{"name":"海南","type":"next","value":460000},{"name":"河北","type":"next","value":130000},{"name":"河南","type":"next","value":410000},{"name":"黑龙江","type":"next","value":230000},{"name":"湖北","type":"next","value":420000},{"name":"湖南","type":"next","value":430000},{"name":"吉林","type":"next","value":220000},{"name":"江苏","type":"next","value":320000},{"name":"江西","type":"next","value":360000},{"name":"辽宁","type":"next","value":210000},{"name":"内蒙古","type":"next","value":150000},{"name":"宁夏","type":"next","value":640000},{"name":"青海","type":"next","value":630000},{"name":"山东","type":"next","value":370000},{"name":"山西","type":"next","value":140000},{"name":"陕西","type":"next","value":610000},{"name":"四川","type":"next","value":510000},{"name":"西藏","type":"next","value":540000},{"name":"新疆","type":"next","value":650000},{"name":"云南","type":"next","value":530000},{"name":"浙江","type":"next","value":330000},{"name":"港澳台","type":"next","value":800000},{"name":"海外","type":"next","value":810000},{"name":"其它","type":"leafNode","value":999999}],"state":0,"status":"SUCCESS","statusCode":0}
模板部分
<template> <div class="chooseCity_warp" @click="closeCallBack(false,chooseCity)" id="chooseCity" v-if="show" > <div class="count el-dialog__header" @click.stop="" @mousedown="dowMos" @mouseup="upMos" @mousemove="move" > <div class="count_body"> <!-- 头部展示区域 --> <div class="body_header" > <div class="header_tip">{{config.title}}</div> <div class="header_close"><span @click="closeCallBack(false,chooseCity)" class="close"></span></div> </div> <!-- 选中区域显示 --> <div class="body_cont"> <!-- 选中文案显示部分 --> <div class="choose_cont"> <div class="title">已选择:</div> <div class="choose_msg"> <div class="item" v-for="(item,index) in chooseCity" :key="index"><span class="text">{{item.name}}</span><span @click="clearCity(item)" class="delete"></span></div> </div> </div> <!-- 选择省、市部分 --> <div class="choose_list_header"> <div class="header_item">省份/直辖市</div> <div class="header_item">城市</div> </div> <div class="choose_list"> <div class="choose_provinceList"> <div class="provinceList_item city_item" v-for="(itemPro,indexPro) in provinceList" :key="indexPro+'pro'" @click="choosePro(itemPro)"> <div :class="{'proItem':itemPro.type != 'next','cityItem':itemPro.type == 'next','chooseActiveCity':chooseIds.includes(itemPro.value),'chooseActivePro':chooseProIds.includes(itemPro.value)}">{{itemPro.name}}</div> </div> </div> <div class="cityList"> <div class="cityList_item city_item" v-for="(itemCit,indexCit) in cityList" :key="indexCit+'cit'" @click="chooseCit(itemCit)"> <div :class="{'proItem':itemCit.type != 'next','chooseActiveCity':chooseIds.includes(itemCit.value)}">{{itemCit.name}}</div> </div> </div> </div> </div> <!-- 底部按钮区域 --> <div class="body_bot"> <span class="sure" v-if="config.r_btn && config.r_btn!=''" @click="sureCallBack(true,config)">{{config.r_btn}}</span> <span class="close" v-if="config.l_btn && config.l_btn!=''" @click="closeCallBack(false)">{{config.l_btn}}</span> </div> <!-- <div v-if="config.title !=''" class="confirm_header"> <slot name="confirm_header">{{config.title}}</slot> </div> <div class="confirm_body"> <div v-if="config.vnode && config.vnode!=''" v-html="config.vnode" > </div> <span v-else>{{config.content}}</span> </div> <div class="confirm_footer"> <span class="sure" v-if="config.r_btn && config.r_btn!=''" @click="sureCallBack(true)">{{config.r_btn}}</span> <span class="close" v-if="config.l_btn && config.l_btn!=''" @click="closeCallBack(false)">{{config.l_btn}}</span> </div> --> </div> </div> </div> </template> <script> export default { name: '', data() { return { show: false, // 请求参数 0代表请求省级别 初始化 请求 一次 cityParams:{ parentId:'0' }, chooseNum:1, proFlag:false, // 选中城市id集合 chooseIds:[], // 选中省id集合 chooseProIds:[], // 选中城市集合 chooseCity:[], // 省集合 provinceList:[], // 市集合 cityList:[] } }, props: { confirmOption:{ type:Object, default:()=>{ return { // 'title':'', // 'content':'', // 'r_btn':'继续', // 'l_btn':'取消', } } } }, components:{ }, mounted() { // console.log('this.config') // console.log(this.config) }, methods:{ }, } </script> <style scoped> .chooseCity_warp{background-color: rgba(255, 255, 255, 0.5);position: fixed;top: 0px;left: 0px;width: 100%;height: 100%;z-index: 1111;} .chooseCity_warp .count{min-width: 560px;position: absolute;top: 50%;left: 50%;transform: translateX(-50%) translateY(-50%);background-color: #ffffff;border-radius: 4px; border-radius: 10px;background-color: rgba(102,102,102,0.2);padding: 10px;} .chooseCity_warp .count .count_body{background-color: #ffffff;} .chooseCity_warp .count .count_body .body_header{background-color: #555b65;color: #fff;border-radius: 3px 3px 0 0;height: 27px;display: flex;align-items: center;padding-left: 10px;} .chooseCity_warp .count .count_body .body_header .header_tip{flex: 4;} .chooseCity_warp .count .count_body .body_header .header_close{flex: 1;} .chooseCity_warp .count .count_body .body_header .header_close .close{ background: transparent url('../../assets/dialog_close.png') left top no-repeat; width: 19px; height: 19px; text-indent: -9999px; float: right; cursor: pointer; margin: 4px; overflow: hidden; } .chooseCity_warp .count .count_body .body_header .header_close .close:hover{ background: transparent url('../../assets/dialog_close.png') left bottom no-repeat; } .chooseCity_warp .count .count_body .body_cont{padding: 15px;padding-bottom: 0px;} .chooseCity_warp .count .count_body .body_cont .choose_cont{padding: 6px 0px;display: flex;align-items: center;} .chooseCity_warp .count .count_body .body_cont .choose_cont .title{} .chooseCity_warp .count .count_body .body_cont .choose_cont .choose_msg{display: flex;align-items: center;} .chooseCity_warp .count .count_body .body_cont .choose_cont .choose_msg .item{ background: transparent url('../../assets/pickpad.gif') no-repeat scroll left top; cursor: default; float: left; height: 20px; line-height: 20px; margin: 4px 2px; padding-left: 8px; padding-right: 20px; white-space: nowrap; color: #333; } .chooseCity_warp .count .count_body .body_cont .choose_cont .choose_msg .item .delete { background: url('../../assets/pickpad.gif') no-repeat scroll right top transparent; cursor: pointer; display: inline-block; height: 20px; margin-left: 6px; margin-right: -20px; text-indent: -99999px; width: 20px; } .chooseCity_warp .count .count_body .body_cont .choose_cont .choose_msg .item .delete:hover{ background: url('../../assets/pickpad.gif') no-repeat scroll right bottom transparent; } .chooseCity_warp .count .count_body .body_cont .choose_cont .choose_msg .item .text{vertical-align: super;} .chooseCity_warp .count .count_body .body_cont .choose_list {display: flex;border: 1px solid #d9d9d9;} .chooseCity_warp .count .count_body .body_cont .choose_list_header {display: flex;border: 1px solid #d9d9d9;border-bottom: 0px solid #d9d9d9;border-right: 0px solid #d9d9d9;} .chooseCity_warp .count .count_body .body_cont .choose_list_header .header_item {flex: 1; text-align: center; color: #999999; background: #f5f5f5; line-height: 34px;border-right: 1px solid #d9d9d9;} .chooseCity_warp .count .count_body .body_cont .choose_list .choose_provinceList {flex: 1;height: 340px;overflow-y: scroll;} .chooseCity_warp .count .count_body .body_cont .choose_list .cityList {flex: 1;height: 340px;overflow-y: scroll;} .chooseCity_warp .count .count_body .body_cont .choose_list .city_item{ line-height: 34px;border-bottom: 1px solid #d9d9d9;} .chooseCity_warp .count .count_body .body_cont .choose_list .proItem { padding: 0px 10px 0px 20px; background-image: url("data:image/IFf;base64,R0lGODlhFQAIAIABAP///wAAACH5BAEAAAEALAAAAAAVAAgAAAIXjH8AyJ3qolFLBviqpRPbTmkfKI6deRQAOw=="); } .chooseCity_warp .count .count_body .body_cont .choose_list .proItem:hover { background: #e4f7f9 right center no-repeat; background-image: url("data:image/IFf;base64,R0lGODlhFQAIAIABAA+puwAAACH5BAEAAAEALAAAAAAVAAgAAAIXjH8AyJ3qolFLBviqpRPbTmkfKI6deRQAOw=="); } .chooseCity_warp .count .count_body .body_cont .choose_list .cityItem{ padding: 0px 10px 0px 20px; background-image: url("data:image/IFf;base64,R0lGODlhFQAIAIABAP///wAAACH5BAEAAAEALAAAAAAVAAgAAAIXjH8AyJ3qolFLBviqpRPbTmkfKI6deRQAOw=="); } .chooseCity_warp .count .count_body .body_cont .choose_list .cityItem:hover { background: #e4f7f9 right center no-repeat; background-image: url("data:image/IFf;base64,R0lGODlhFAALAIABAA+puwAAACH5BAEAAAEALAAAAAAUAAsAAAIVRI6pauvbngxxumpZhlt3hG1hNmYFADs="); } .chooseCity_warp .count .count_body .body_cont .choose_list .chooseActiveCity{ color: #fff; background: #0fa9bb right center no-repeat; background-image: url("data:image/IFf;base64,R0lGODlhFQAIAIABAP///wAAACH5BAEAAAEALAAAAAAVAAgAAAIXjH8AyJ3qolFLBviqpRPbTmkfKI6deRQAOw==") } .chooseCity_warp .count .count_body .body_cont .choose_list .chooseActiveCity:hover{ color: #fff; background: #0fa9bb right center no-repeat; background-image: url("data:image/IFf;base64,R0lGODlhFQAIAIABAP///wAAACH5BAEAAAEALAAAAAAVAAgAAAIXjH8AyJ3qolFLBviqpRPbTmkfKI6deRQAOw==") } .chooseCity_warp .count .count_body .body_cont .choose_list .chooseActivePro{ color: #fff; background: #0fa9bb right center no-repeat; background-image: url("data:image/IFf;base64,R0lGODlhFAALAIABAP///wAAACH5BAEAAAEALAAAAAAUAAsAAAIVRI6pauvbngxxumpZhlt3hG1hNmYFADs=") } .chooseCity_warp .count .count_body .body_cont .choose_list .chooseActivePro:hover{ color: #fff; background: #0fa9bb right center no-repeat; background-image: url("data:image/IFf;base64,R0lGODlhFAALAIABAP///wAAACH5BAEAAAEALAAAAAAUAAsAAAIVRI6pauvbngxxumpZhlt3hG1hNmYFADs=") } .chooseCity_warp .count .count_body .body_bot {background-color: #f6f6f6;padding: 8px 20px 8px 0;text-align: right;} .chooseCity_warp .count .count_body .body_bot .sure{color: #333;line-height: 26px;display: inline-block;height: 26px;padding: 2px 20px;border-radius: 4px;margin-right: 10px;background-color: #fee579;border: 1px solid #c6c6c6;cursor: pointer;} .chooseCity_warp .count .count_body .body_bot .close{color: #333;line-height: 26px;display: inline-block;height: 26px;padding: 2px 20px;border-radius: 4px;background-color: #f8f8f8;border: 1px solid #c6c6c6;cursor: pointer;} /* .chooseCity_warp .count .count_body .body_bot .close{color: #333;} */ /* .confirm_warp .count .confirm_header{text-align: center;} .confirm_warp .count .confirm_body{padding: 20px;min-height: 40px;} .confirm_warp .count .confirm_footer{padding: 20px;min-height: 40px;text-align: center;} .confirm_warp .count .confirm_footer span{display: inline-block;font-size: 14px;padding: 4px 25px;cursor: pointer;border-radius: 2px;} .confirm_warp .count .confirm_footer .sure{background-color: #E62679;color: #ffffff;} .confirm_warp .count .confirm_footer .close{background-color: #ffffff;color: #E62679;border: 1px solid #E62679;padding: 3px 25px;margin-left: 20px;} */ </style>
逻辑部分
import chooseCity from './index.vue' import { cityList } from '../../api/accountaudit/talentManagement' import Vue from 'vue' // import { isVNode } from 'element-ui/src/utils/vdom'; /* * this.$lstchooseCity({ title:'这是什么东西~',//标题 chooseNum:1,//选中城市数量 draco:false,//是否允许拖动 proFlag: false,// 是否允许获取省级别 chooseCity:[ { name: "上海", type: "leafNode", value: 310000 } ],// 选中城市 默认选中 r_btn:'确定',//左侧按钮 l_btn:'取消',//右侧按钮 vnode:'<span>饿哦是内容区域</span>',//内容自定义部分 content:"我也不知道这是什么东西啊!!!"//内容文本 }).then(res=>{ console.log(res)//点击按钮回调函数 }) */ let chooseCityIndex = {}; chooseCityIndex.install = function (Vue,options) { const confirmIndexConstructor = Vue.extend(chooseCity); // 生成一个该之类的实例 const instance = new confirmIndexConstructor(); // $_getCitylist(){ // cityList(this.cityParams).then((res) => { // }) // } Vue.prototype.$lstchooseCity = (config) => { // 这里 return 一个 Promise // 在项目中使用的时候,就可以进行链式调用了~ return new Promise((resolve,reject) => { instance.config = config; instance.chooseNum = config.chooseNum || 1; instance.draco = config.draco || true; instance.proFlag = config.proFlag || false; instance.chooseCity = [ ...config.chooseCityArrs ] || []; //instance.chooseCity = config.chooseCityArrs || []; instance.show = true; instance.moseMove = false; instance.mosX = 0; instance.mosY = 0; let chooseCitArr = [] // console.log(config) // 拖动 instance.dowMos = (e) => { instance.moseMove = true; instance.mosX = e.clientX; instance.mosY = e.clientY; } instance.upMos = () => {instance.moseMove = false;} instance.move = (e) => { // console.log(e.target) if(!instance.draco){ return false; } if(!instance.moseMove){ return false; } // let odiv = e.target; //获取目标元素 const odiv = document.querySelector('.el-dialog__header') //获取目标元素 // console.log(odiv) //算出鼠标相对元素的位置 let disX = e.clientX - odiv.offsetLeft; let disY = e.clientY - odiv.offsetTop; // 计算出 移动的距离 let mosx = e.clientX - instance.mosX; let mosy = e.clientY - instance.mosY; document.onmousemove = (e)=>{ //鼠标按下并移动的事件 //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置 // let left = e.clientX - disX; // let top = e.clientY - disY; let left = odiv.offsetLeft + mosx; let top = odiv.offsetTop + mosy; //绑定元素位置到positionX和positionY上面 instance.mosX = e.clientX; instance.mosY = e.clientY; //移动当前元素 odiv.style.left = left + 'px'; odiv.style.top = top + 'px'; }; document.onmouseup = (e) => { document.onmousemove = null; document.onmouseup = null; }; // } } instance.getCity = () => { instance.cityList = [] cityList(instance.cityParams).then((res) => { if(instance.cityParams.parentId == 0){ instance.provinceList = res.data; }else{ instance.cityList = res.data; } }) } // 获取当前选中城市 id集合 instance.getCityIds = () => { instance.chooseIds = []; instance.chooseCity.forEach((ele) => { instance.chooseIds.push(ele.value) }) } // 初始化 获取城市 省级别获取后再次打开不在请求接口 if(instance.provinceList.length == 0){ instance.getCity(); } // 初始化 获取已经选中的 // 获取当前选中城市 id集合 instance.getCityIds(); // 选择省级别 instance.choosePro = (val)=>{ instance.cityParams.parentId = val.value if(val.type == 'next'){ instance.getCity(); instance.chooseProIds = [] instance.chooseProIds.push(val.value) // 判断是否获取升级别数据 if(instance.proFlag){ instance.clearCity(val) if(instance.chooseCity.length > instance.chooseNum){ instance.chooseCity = instance.chooseCity.splice(1,instance.chooseNum); } } }else{ instance.chooseProIds = [] instance.cityList = []; instance.chooseIds.push(val.value); instance.clearCity(val) if(instance.chooseCity.length > instance.chooseNum){ instance.chooseCity = instance.chooseCity.splice(1,instance.chooseNum); } // 获取当前选中城市 id集合 instance.getCityIds(); } } // 选择市级别 instance.chooseCit = (val)=>{ // console.log(val) instance.chooseIds = []; instance.chooseIds.push(val.value) instance.clearCity(val) if(instance.chooseCity.length > instance.chooseNum){ instance.chooseCity = instance.chooseCity.splice(1,instance.chooseNum); } // 获取当前选中城市 id集合 instance.getCityIds(); } // 双击取消当前选中的城市 instance.clearCity = (val) => { // console.log(111) let flag = true; instance.chooseCity.forEach((ele,index) => { if(ele.value == val.value){ flag = false; instance.chooseCity.splice(index,1); return false; } }); if(flag){ instance.chooseCity.push(val) } chooseCitArr = instance.chooseCity // 获取当前选中城市 id集合 instance.getCityIds(); } instance.sureCallBack = () => { instance.show = false; let params = { type :true, data:instance.chooseCity } resolve(params); } instance.closeCallBack = () => { instance.show = false; let params = { type :false, // data:instance.chooseCity } resolve(params); // resolve(false) } }) } // 将这个实例挂载在我创建的div上 // 并将此div加入全局挂载点内部 instance.$mount(document.createElement('div')) document.body.appendChild(instance.$el) } export default chooseCityIndex;
效果截图展示
使用方式
this.$lstchooseCity({ title:'这是什么东西~',//标题 chooseNum:1,//选中城市数量 draco:false,//是否允许拖动 proFlag: false,// 是否允许获取省级别 chooseCity:[ { name: "上海", type: "leafNode", value: 310000 } ],// 选中城市 默认选中 r_btn:'确定',//左侧按钮 l_btn:'取消',//右侧按钮 vnode:'<span>饿哦是内容区域</span>',//内容自定义部分 content:"我也不知道这是什么东西啊!!!"//内容文本 }).then(res=>{ console.log(res)//点击按钮回调函数 })