目录结构
这是《基于nuxt和iview搭建OM后台管理系统实践》这一个系列文章的目录,大致思路如下:
- 简要介绍OM后台管理系统,以及开发环境
- 自行封装的公共组件,富文本quill[已完成]、地图、上传组件(阿里oss、七牛上传组件已经完成)的封装过程
- 项目上线流程,自动化打包(Jenkins)
- 项目总结,总结开发过程中的坑点,避免以后再掉坑
前言
上几篇记录了几个功能比较简单的组件,本篇的高德地图封装遇到了蛮多坑,在此记录一下,避免后面再踩坑。
说到地图组件,其实是其他项目组需要地图数据展示,然后我被借调到其他项目组,最终翻阅高德地图众多api后终于完成了。
核心代码
// 文件componets/amap-weather.vue<template><div><Form :model="searchForm" :label-width="190" inline><FormItem label="地区"><Select v-model="searchForm.crop" style="width:300px" @on-change="changeImage"><Option v-for="item in crops" :value="item.title" :key="item.id">{{item.title}}</Option></Select></FormItem></Form><div :id="id" :style="{'width':width,'height':height}"></div></div>
</template><script>// import VeAmap from 'v-charts/lib/amap';import axios from "../plugins/axios";export default {name: "VAmap",data() {return {weaherData: [],weatherVoList: [],arr: [],polygons: [],searchForm: {crop: ''},crops: [],latID: 124.298158,lngID: 43.223817};},props: {id: {default: "container"},width: {default: "100%"},zoom: {default: 15},height: {default: "800px"},getlandRequestURL: {default: ""},getgeoJsonURL: {default: ""},getWeatherJsonURL: {default: ""},getAreaData: {default: ""}},head() {return {script: [{src: "http://webapi.amap.com/maps?v=1.4.5&key=key自行去高德地图开发者中心申请&&plugin=AMap.ToolBar"}]};},created: function () {},mounted() {var _this = this;if (process.browser) {_this.initMap();_this.getData();}},methods: {getData() {var _this = thisaxios.get(_this.getAreaData).then(res => {this.crops = res.data.area}).catch(error => {console.log(error);});},changeImage(e) {var _this = this;this.polygons = [];axios.get(_this.getAreaData).then(res => {var changeData = res.data.areachangeData.forEach(el => {if (el.title == e) {this.latID = el.point.lat;this.lngID = el.point.lngvar _this = this;this.initMap()}})}).catch(error => {console.log(error);});},initMap() {//地图初始化var _this = this;var googleLayer = new AMap.TileLayer({getTileUrl: "http://mt{1,2,3,0}.google.cn/vt/lyrs=s&hl=zh-CN&gl=cn&x=[x]&y=[y]&z=[z]&s=Galile"}); //定义谷歌卫星切片图层var roadNetLayer = new AMap.TileLayer.RoadNet(); //定义一个路网图层var map = new AMap.Map(this.id, {resizeEnable: true,center: [_this.latID, _this.lngID],zoom: _this.zoom,layers: [googleLayer, roadNetLayer] //设置图层});var toolBar = new AMap.ToolBar({visible: true});map.addControl(toolBar);// debugger;// 初始化var bounds = map.getBounds();var northeast = bounds.Kb.lng + ',' + bounds.Kb.lat;var northwest = bounds.Nb.lng + "," + bounds.Kb.lat;var southwest = bounds.Nb.lng + ',' + bounds.Nb.lat;var southeast = bounds.Kb.lng + ',' + bounds.Nb.lat;var area = northeast + ";" + northwest + ";" + southwest + ";" + southeast + ";" + northeast_this.loadLandData(area, map); //加载可视范围内的地块map.on("moveend", function (e) {//监听页面变化//获取可视区域的经纬度var getBounds = map.getBounds()var bounds = map.getBounds();var northeast = bounds.Kb.lng + ',' + bounds.Kb.lat;var northwest = bounds.Nb.lng + "," + bounds.Kb.lat;var southwest = bounds.Nb.lng + ',' + bounds.Nb.lat;var southeast = bounds.Kb.lng + ',' + bounds.Nb.lat;var area = northeast + ";" + northwest + ";" + southwest + ";" + southeast + ";" + northeast_this.loadLandData(area, map); //加载可视范围内的地块});},loadLandData(area, map) {//根据当前区域经纬度获取地图区域的地块let _this = this;axios// .get(_this.getlandRequestURL+"?area[]="+area).get(_this.getlandRequestURL + "?area[]=" + area).then(res => {let list = res.data.data;list.forEach(els => {let obj = [];let points = els.geometry.coordinates[0].points; //重新组装接口来的数据points.forEach(el => {obj.push(el.coordinates);});_this.polygonShow(els.id, map, obj); //遍历经纬度并渲染到地图上});}).catch(error => {console.log(error);});},polygonShow(id, map, obj) {//渲染多边形和网格 判断地块是否是重新加载的if (!this.polygons.find(p => p.toString() === id.toString())) {//渲染多边形和网格let polygonOpt = {path: obj, //设置多边形边界路径strokeColor: "#FF33FF", //线颜色strokeOpacity: 0.2, //线透明度strokeWeight: 3, //线宽fillColor: "red", //填充色fillOpacity: 0.4, //填充透明度id: id,points: obj};let polygon = new AMap.Polygon(polygonOpt);polygon.setMap(map);this.polygons.push(id);this.polygonClick(map, polygon);}},polygonClick(map, polygon) {//点击地块获得格点数据var _this = this;polygon.on("click", function (e) {let list = e.target.Ch.points;let areas = "";list.forEach(el => {areas += el + ";";});_this.gridPolygonData(map, _this.removeLastCode(areas)); //加载geoJson});},gridPolygonData(map, areas) {//加载网格的数据并添加上点击事件var _this = this;axios.get(_this.getWeatherJsonURL + "?point[]=" + areas).then(res => {_this.weaherData = res.data.data;//获取所有天气信息let list = res.data.data;let obj = [];list.forEach(els => {let points = els.gridPolygon.points; //重新组装接口来的数据points.forEach(el => {obj.push(el.coordinates);});_this.gridPolygonShow(els.id, map, obj); //遍历经纬度并渲染到地图上});}).catch(error => {console.log(error);});},// 地图上加载天气轨迹gridPolygonShow(id, map, obj) {var polygon = new AMap.Polygon({path: obj, //设置多边形边界路径strokeColor: "#FF33FF", //线颜色strokeOpacity: 0.2, //线透明度strokeWeight: 3, //线宽fillColor: "#ccc", //填充色fillOpacity: 0.2, //填充透明度id: id,points: obj});polygon.setMap(map);//绘制地图map.setZoomAndCenter(this.zoom, obj[0]); //重新设置地图中心点this.gridPolygonClick(polygon);},// 点击地块触发的事件gridPolygonClick(polygon) {var _this = this;polygon.on("click", function (e) {_this.loadWeatherData(e.target.Ch.id); //通过id得到当前的数据}); },loadWeatherData(id) {// 点击格点获取天气数据// alert(id);var _this = this;let weatherVoList = [];let weaherData2 =[];weaherData2.push(_this.weaherData[0]);weaherData2.forEach(els => {if (els.id == id) {weatherVoList=els.weatherForecastVoList;} });_this.$emit('loadWeather',weatherVoList);//把得到的天气数据暴露给父组件引用// _this.dataEmpty = false;},removeLastCode(str) {//去掉字符串最后一位if (str == null || str == "" || str.length < 1) {return str;}return str.substring(0, str.length - 1);}}};
</script><style scoped>.v-charts-data-empty {position: absolute;top: 0;left: 40%;font-size: 16px;top: 10%;}
</style>复制代码
使用方法:按照vue标准引用局部组件的方式引入即可,分别传入getlandRequestURL,getgeoJsonURL,getWeatherJsonURL,getAreaData地址。
<template><div class="body"><amap-weathergetlandRequestURL="/data/getLand.json"getgeoJsonURL="/data/getLand.json"getWeatherJsonURL="/data/getweatherforgeo.json"getAreaData="/data/area.json"></amap-weather></div>
</template><script>
import amapWeather from '../../components/amap-weather';
export default {layout:'nav',components: {amapWeather},head() {return {title: "高德地图插件"};},
}
</script><style></style>复制代码
总结
- 在封装高德地图组件过程中遇到最大的一个坑:nuxt路由跳转到地图页面报错,最终的解决方案是在left-nav.vue跳转方法里做判断,如果路由路径为map就刷新页面,同时利用:active-name="menuName"属性展开左侧菜单;
- 另外一个坑就是服务端渲染带来的问题,最终在mounted生命周期函数中根据process做判断是浏览器端还是服务端并做相应的处理,如代码所示
mounted() {var _this = this;if (process.browser) {_this.initMap();_this.getData();}
}
复制代码
- 另外对于组件命名也不规范,官方推荐用amap-weather.vue这种,在做这一块的总结的时候可以看到上面的代码改过来了;
系列文章链接
以下为本系列的文章合集,在此列出便于查阅:
- 基于nuxt和iview搭建OM后台管理平台实践(1)-项目基本介绍
- 基于nuxt和iview搭建OM后台管理系统实践(2)-富文本组件的封装
- 基于nuxt和iview搭建OM后台管理系统实践(3)-阿里oss上传组件的封装
- 基于nuxt和iview搭建OM后台管理系统实践(4)-七牛上传组件的封装