接着前面的文章继续
5.vue3.0下使用 iconfonts
这个直接去https://www.iconfont.cn/下载一个整理好的图标库
下载好直接放到工程里
main.js里直接引入css
import '@/assets/iconfonts/iconfont.css';
vue页面中直接就可以引用了
<i class="iconfont icon-menu></i>
但是在配合antd使用的过程中发现a-menu菜单组件如果用iconfont这种图标方式,在收起菜单后文字不能正常隐藏
我这里是在菜单收起后加一个样式来控制隐藏文字的
<style>
.menu-mini .ant-menu-item span{
display: none;
}
</style>
修改前后对比
6.vue3.0下使用 axios (这里只做了封装,暂时没有试访问真实的服务)
直接封装
request.js
import axios from 'axios'
import constantName from '@/utils/constant'
// 创建axios实例
const service = axios.create({
/*headers: {'content-type': 'application/json'},
headers: {'Authorization': Cookies.get("Authorization")},*/
baseURL: process.env.NODE_ENV === "production" ? constantName.prod_service_url : constantName.local_service_url , // api的base_url
timeout: 5000 // 请求超时时间
})
// request拦截器
service.interceptors.request.use(config => {
config.headers.Authorization = 'admin'
return config
}, error => {
return Promise.reject(error)
})
service.interceptors.response.use(
response => {
const res = response.data;
if (res.code !== 200) {
return Promise.reject('error');
} else {
return res.data;
}
},
error => {
console.log('err' + error)// for debug
return Promise.reject(error)
})
export default service
api里这样调用
import request from "../utils/request"
import constantName from '../utils/constant'
// getMenus
export const getMenus = () => {
return request({
url: constantName.api_user + "/getMenus",
method: "get",
})
}
vue 或者 store中这么用
import { getMenus } from '@/api/menu'
getMenus().then(res => {
//xxx
}).catch(error => {
// xx
})
7.vue3.0下使用 mockjs
mock/index.js
// 首先引入Mock
const Mock = require('mockjs');
// 设置拦截ajax请求的相应时间
Mock.setup({
timeout: '200-600'
});
let configArray = [];
// 使用webpack的require.context()遍历所有mock文件
const files = require.context('.', true, /\.js$/);
files.keys().forEach((key) => {
if (key === './index.js') return;
configArray = configArray.concat(files(key).default);
});
// 注册所有的mock服务
configArray.forEach((item) => {
for (let [path, target] of Object.entries(item)) {
let protocol = path.split('|');
Mock.mock(new RegExp(protocol[1]), protocol[0], target);
}
});
/* eslint-disable no-dupe-keys */
let user_info = {
code: 200,
message: 'success',
'data|1-10': [{
// 属性 RegisterNo 是一个自增数,起始值为 1,每次增 1
'RegisterNo|+1': 1,
// 随机数字1-100
'reading|1-100': 100,
'ElectricityQuantity|1-100': 100,
'name': '@cname', // 中文名称
'date': '@date("yyyy-MM-dd")', // 日期
'city': '@city(true)', // 中国城市
'color': '@color', // 16进制颜色
'isMale|1': true, // 布尔值
'isFat|1-2': true, // true的概率是1/3
'brother|1': ['jack', 'jim'], // 随机选取 1 个元素
}]
};
// noinspection JSDuplicatedDeclaration
let list = {
'get|/user/getInfo': user_info,
// eslint-disable-next-line no-unused-vars
"get|/user/getMenus": (option) => {
return {
code: 200,
message: 'success',
data: []
};
}
};
export default list
main.js中直接引入
require('./mock');
8.vue3.0下使用 bus总线(mitt替代)
bus.js
import mitt from 'mitt'
const bus = {}
const emitter = mitt()
bus.$on = emitter.on
bus.$off = emitter.off
bus.$emit = emitter.emit
export default bus
main.js中直接引入
import Bus from '@/common/bus.js'/// mitt 总线程引入
/* 代替 Vue.prototype */
App.config.globalProperties.$bus = Bus;
组件中使用
// 监听
this.$bus.$on("do-switch-menus", (item) => {
console.log("do-switch-menus", item)
this.menuList = item.children
});
// 发布
this.$bus.$emit('do-switch-menus', item)
9.vue3.0下使用 echarts、dataV
main.js
import { createApp } from 'vue'
import app from './App.vue'
import dataV from '@jiaminghi/data-view'
// 适配flex
import '@/common/flexible.js';
//引入echart
import echarts from 'echarts'
const App = createApp(app,{});
App.use(dataV);
App.config.globalProperties.$echarts = echarts
App.mount('#app');
使用可以直接用this.$echarts
也可以像我这样封装一下
<template>
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import tdTheme from './theme.json' // 引入默认主题
import echartMixins from "@/utils/resizeMixins";
export default {
name: 'echart',
mixins: [echartMixins],
props: {
className: {
type: String,
default: 'chart'
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '2.5rem'
},
options: {
type: Object,
default: ()=>({})
}
},
data () {
return {
chart: null
}
},
watch: {
options: {
handler (options) {
// 设置true清空echart缓存
this.chart.setOption(options, true)
},
deep: true
}
},
mounted () {
this.$echarts.registerTheme('tdTheme', tdTheme); // 覆盖默认主题
this.initChart();
},
methods: {
initChart () {
// 初始化echart
this.chart = this.$echarts.init(this.$el, 'tdTheme')
this.chart.setOption(this.options, true)
}
}
}
</script>
<style>
</style>
dataV的直接按照官网的文档使用就行,比较简单,只是第一次运行时有个组件会报一个错,好像是v-for 没有key ,直接改了他的源码加一个key就行
9.vue3.0下使用 百度地图API3.0
百度地图3.0可以支持自定义样式
效果这样
index.html下引入
<script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=xxx"></script>
<script type="text/javascript" src="http://api.map.baidu.com/library/InfoBox/1.2/src/InfoBox_min.js" ></script>
<script type="text/javascript" src="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.js" ></script>
vue.config.js中直接加入代码段(完整版参考上一篇文章)
configureWebpack: {
externals: {
"BMap": "BMap",
'BMapLib': 'BMapLib'
}
},
vue中就可以直接使用了
import BMap from 'BMap'
this.map = new BMap.Map("map")
<template>
<div id="map" ref="map">
</div>
</template>
<script>
import BMap from 'BMap'
import mapImgMeter from '../../assets/img/water_meter.png';
const deviceSize = new BMap.Size(32,32);
const mapIconMeter = new BMap.Icon(mapImgMeter, deviceSize, { //会以base64的方式传参iconCar
imageSize: deviceSize
});
export default {
name: "baidumap",
data () {
return {
map:null,
zoomOverlay: null,
}
},
mounted () {
this.createMap()
},
methods: {
createMap () {
/* eslint-disable */
// 创建Map实例
this.map = new BMap.Map("map")
this.$refs.map.style.background = '';
// 初始化地图,设置中心点坐标和地图级别
this.map.centerAndZoom(new BMap.Point(117.05126, 39.3893), 13)
//添加地图类型控件
/*this.map.addControl(new BMap.MapTypeControl({
mapTypes:[BMAP_NORMAL_MAP, BMAP_HYBRID_MAP]
}))*/
// this.map.setMapStyle({style: 'midnight'});
// 设置地图显示的城市 此项是必须设置的
this.map.setCurrentCity("天津市武清区")
//开启鼠标滚轮缩放
this.map.enableScrollWheelZoom(true)
let styleJson = [
{
'featureType': 'land',
'elementType': 'geometry',
'stylers': {
'visibility': 'on',
'color': '#ffffffff'
}
}, {
'featureType': 'water',
'elementType': 'geometry',
'stylers': {
'visibility': 'on',
'color': '#ff5400ff'
}
}, {
'featureType': 'green',
'elementType': 'geometry',
'stylers': {
'visibility': 'on',
'color': '#ff54006e'
}
}
];
//this.map.setMapStyleV2({styleJson:styleJson});
this.map.setMapStyleV2({styleId:'48096cea362f37db8287e3f6368011b9'});
let _this = this
// 地图点击
this.map.addEventListener('click', function (e) {
console.log('点击位置经纬度:' , e.point);
});
// 地图加载完成
this.map.addEventListener('tilesloaded', function () {
_this.addBoundary()
_this.initData()
});
},
addBoundary () {
let bdary = new BMap.Boundary();
let _this = this
if (this.zoomOverlay == null) {
this.zoomOverlay = []
} else {
for (let i = 0;i < this.zoomOverlay.length;i++) {
_this.map.removeOverlay(this.zoomOverlay[i]);
}
this.zoomOverlay = []
}
bdary.get("天津市武清区", function(rs){ // 获取行政区域
let count = rs.boundaries.length; // 行政区域的点有多少个
for(let i = 0; i < count; i++){
let ply = new BMap.Polygon(rs.boundaries[i], {strokeWeight: 3, strokeColor: '#38e2f0AA', strokeOpacity: 1, fillColor:'#08304a02',fillColorOpacity: 1}); //建立多边形覆盖物
_this.zoomOverlay.push(ply)
_this.map.addOverlay(ply); // 添加覆盖物
}
})
},
initData () {
let points =[
{lat: 39.38394, lng: 117.010297,icon: mapIconMeter , name: '数据1', addr: '数据1'},
{lat: 39.3893, lng: 117.05126,icon: mapIconMeter , name: '数据2', addr: '数据1'},
{lat: 39.359514, lng: 117.072172,icon: mapIconMeter , name: '数据3', addr: '数据1'},
{lat: 39.422529, lng: 117.0190647,icon: mapIconMeter , name: '数据4', addr: '数据1'},
{lat: 39.38885, lng: 117.064195,icon: mapIconMeter , name: '数据5', addr: '数据1'}
];
let markers = [];
let pt = null;
for (let i = 0; i < points.length; i++) {
pt = new BMap.Point(points[i].lng, points[i].lat)
let marker = new BMap.Marker(pt, {icon: points[i].icon})
marker.customData = points[i]
markers.push(marker);
marker.addEventListener("click",this.showInfo)
this.map.addOverlay(marker)
}
},
showInfo (e) {
console.log('showInfo:' , e);
let infoWindow = this.createInfoWindow(e.currentTarget.customData);
infoWindow.open(e.currentTarget);
},
//创建InfoWindow
createInfoWindow(info){
let opts = {
boxStyle: {
width: '300px',
height: '200px'
// margin: '30px 0',
},
closeIconWidth: '20px',
closeIconMargin: '10px 10px 0 0',
closeIconUrl: require('../../assets/icon/close.png'),
enableAutoPan: false,
align: INFOBOX_AT_TOP
}
let html = "<div class='infoBoxContent '><h3>设备信息</h3><hr /><div>" +
"<p>设备名称:"+info.name+"</p>" +
"<p>设备状态:"+info.name+"</p>" +
"<p>设备电量:"+info.name+"</p>" +
"<p>设备地址:"+info.addr+"</p>" +
"<div align=\"center\"><button>巡检</button></div></div></div>";
let iw = new BMapLib.InfoBox(this.map,html,opts);
return iw;
}
}
}
</script>
<style scoped>
#map{
min-height: 200px;
width: 100%;
height: 100%;
background: transparent;
}
</style>
<style>
.BMap_cpyCtrl
{
display:none;
}
.anchorBL{display:none;}
#map .BMap_pop .BMap_center{
background: #2c8ef0;
border-left: 1px solid #38e2f0;
border-right: 1px solid #38e2f0;
}
.infoBox{
background: #2c8ef07a;
border-radius: 10px;
border: 1px solid #2c8ef0;
}
.infoBoxContent{
margin:10px;
max-height: 230px;
}
.infoBoxContent button{
background-color: #008CBA;
border: none;
color: white;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
border-radius: 16px;
width: 120px;
}
.infoBoxContent h3{
color: white;
margin: 5px;
}
.infoBoxContent hr{
border: 1px solid #fff;
}
.infoBoxContent p{
color:white;
margin: 8px;
}
.infoBoxContent:before {
content: '';
width: 0;
height: 0;
border: 20px solid transparent;
border-top-color: #2c8ef0;
position: absolute;
left: 50%;
top: 100%;
margin-left: -20px;
}
</style>
源码
https://gitee.com/shi2015/st-admin-web
https://gitee.com/shi2015/st-server