从零开始的VUE项目–01(前期准备和前台vue搭建)
前端:VUE (2.9.6) (编码工具:Visual Studio Code)后台:ASP.NET Web API (编码工具:Visual Studio 2019)数据库:MYSQL (可视化工具:MYSQL-Front)基本框架:Element UI前期准备:①已安装好npm,②已全局安装webpack和vue-cli,③在线arcgis js api(我用的是3.14,这个文件是用ngin
前端:VUE (2.9.6) (编码工具:Visual Studio Code)
后台:ASP.NET Web API (编码工具:Visual Studio 2019)
数据库:MYSQL (可视化工具:MYSQL-Front)
基本框架:Element UI
代码svn地址 (用户名:liu,密码;123)无编辑提交权限
在线系统(用户名:liu,密码;12345)普通用户
一、前期准备:
①已安装好npm,②已全局安装webpack和vue-cli,③在线arcgis js api(我用的是3.14,这个文件是用nginx1.19.1发布的),发布很简单,将链接:https://pan.baidu.com/s/18EewlEIq96tcBQlqx79Thw
提取码:41na
里的文件解压后放到nginx-1.19.1的html文件夹里,然后找到conf文件夹的nginx.conf文件,配置如下:
#user nobody;
#==工作进程数,一般设置为cpu核心数
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
#==最大连接数,一般设置为cpu*2048
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
#==客户端链接超时时间
keepalive_timeout 65;
#gzip on;
#当配置多个server节点时,默认server names的缓存区大小就不够了,需要手动设置大一点
server_names_hash_bucket_size 512;
#server表示虚拟主机可以理解为一个站点,可以配置多个server节点搭建多个站点
#每一个请求进来确定使用哪个server由server_name确定
server {
#站点监听端口
listen 1570;
#站点访问域名
server_name localhost;
#编码格式,避免url参数乱码
charset utf-8;
#access_log logs/host.access.log main;
#location用来匹配同一域名下多个URI的访问规则
#比如动态资源如何跳转,静态资源如何跳转等
#location后面跟着的/代表匹配规则
location / {
#站点根目录,可以是相对路径,也可以使绝对路径
root html;
#默认主页
index arcgis_js_v314_api/arcgis_js_api/library/3.14/3.14/dojo/dojo.js index.html index.htm; #(将vue的dist文件夹(打包后的文件)里的文件放到html文件夹里)
#解决html文件访问本地json文件或本地文件谷歌浏览器跨域问题
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials: true;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content- Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
}
#location / {
# try_files $uri $uri/ /index.html;
#}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
点nginx.exe运行nginx,打开地址
http://localhost:1570/arcgis_js_v314_api/arcgis_js_api/library/3.14/3.14/init.js
出现内容,说明成功发布了
二、创建VUE项目:
1,使用vue-cli创建VUE前端项目
首先找一个地方新建文件夹(我放在D盘下,命名为Project),然后用命令行进入该文件夹目录,输入命令:
(如果不是全局安装vue/cli,则命令为npx @vue/cli create my-project)
vue init webpack test
test就是自定义的项目名,输入命令后,会跳出几个选项自己填一填就好了
构建完成:
现在项目文件夹里就有很多文件了:
用Visual Studio Code打开test文件夹,然后快捷键CTRL+·打开终端(·就是ESC下方的波浪号键),输入下方命令启动项目:
npm run dev
启动成功,打开地址http://localhost:8081(默认为8080,我这里是因为8080端口被另一个程序占用了)。
可以自己改一下端口号,打开config文件夹的index.js文件
host对应的localhost就是指主机名
port对应的8080指的就是端口号
autoOpenBrowser设置为true就可以在启动项目时自动打开浏览器,不用再想上面一样手动输入地址了。
当鼠标光标在终端时,快捷键CTRL+C出现终止批处理操作吗(Y/N)? ,输入y,结束项目
我们再输入:
npm run dev
启动项目,发现项目自动在浏览器打开了
现在项目创建好了,接下来就要开始完善项目了
2,初步做一下主页和菜单,引入Element UI框架样式
像一般的系统一样,我们这个系统应该需要一个主页,主页上面有菜单,菜单功能应该主要由弹窗来承载,好,开始做。
首先在src文件夹的components文件夹里新建Home.vue文件作为主页:
在Home.vue里输入vue
然后回车,一个默认的页面框架就出现了
对了,经常CTRL+S保存一下,防止意外出现代码没保存,
随便在Home.vue上写点东西
下面就要让我们这个Home.vue变成默认的主页
打开src文件夹下router文件夹里的index.js文件,
首先引入我们的Home.vue
import Home from '@/components/Home'
然后在下面的routes里仿照HelloWord配置我们的Home.vue,这里要注意哪个页面的path被设置成 ‘/’,那它就是默认页面了,所以我们把Home.vue的path设置成 ‘/’,委屈HelloWorld.vue,它的path就设置成 ‘/hi’了,反正以后也用不到了。
最后结果:
这时,保存一下代码,发现我们的系统界面变成这样了
图片也用不到,在App.vue里,去掉就行了,下面要搞菜单栏了。
突然发现,好像报错了,代码格式写的不严谨
解决措施(不管了):找到build目录下的webpack.base.conf.js文件,注释掉其中的与有关的eslint规则即可(就是已经注释掉的那句)
然后用上面的命令,关闭,启动,好,没错了
菜单栏生成用的是Element UI的el-menu(NavMenu 导航菜单),所以要引入Element包
npm i element-ui
在src文件夹的components文件夹里新建Menu.vue文件作为菜单栏,
然后把Menu.vue作为组件引入到Home.vue中
最后的Home.vue就是这个样子
而系统界面就变成了这个样子
让我们稍微修改一下Menu.vue文件,这里使用固定的值生成菜单栏,后面再实现从数据读取数据动态生成
<template>
<div>
<el-menu class="el-menu-demo"
background-color="#1f5f9a"
text-color="#fff"
active-text-color="#ffd04b"
mode="horizontal">
<template v-for="item in NavigateItem">
<el-submenu v-if="item.items.length"
:index="item.key"
:key="item.key">
<template slot="title">
{{ item.title }}
</template>
<el-menu-item v-for="(items, key) in item.items"
:key="key"
:index="items.key">
{{ items.title }}
</el-menu-item>
</el-submenu>
<el-menu-item v-else
:index="item.key"
:key="item.key">
{{ item.title }}
</el-menu-item>
</template>
</el-menu>
</div>
</div>
</template>
<script>
export default {
data () {
return {
activeIndex: 1,
menuList: [],
NavigateItem: [],
};
},
created () {
this.getMenuList();
},
methods: {
getMenuList () {
//这就是我们后台传过来的菜单栏信息,是一个字符串,下面我们来对它进行处理
var jsonStr='[{"Id":"1","Name":"地图功能","P_id":"-1","Icon":"map","Url":""},{"Id":"1001","Name":"地图查询","P_id":"1","Icon":"","Url":""},{"Id":"1002","Name":"专题图","P_id":"1","Icon":"","Url":""},{"Id":"2","Name":"数据管理","P_id":"-1","Icon":"data","Url":""},{"Id":"2001","Name":"数据管理","P_id":"2","Icon":"","Url":""},{"Id":"3","Name":"系统维护","P_id":"-1","Icon":"maintenance","Url":""},{"Id":"3001","Name":"业务日志","P_id":"3","Icon":"","Url":""}]'
//将字符串转成数组
var jsonObj = JSON.parse(jsonStr)
var jsonArr = [];
for (var i = 0; i < jsonObj.length; i++) {
jsonArr[i] = jsonObj[i];
}
this.menuList = jsonArr;
//将菜单的父菜单和子菜单分开
this.menuList.forEach((item, index) => {
if (item["P_id"] == -1) {
this.NavigateItem.push({
title: item["Name"],
key: item["Id"],
path: item["Url"],
icon: item["Icon"],
items: [],
})
}
else {
this.NavigateItem[item["P_id"] - 1].items.push({
title: item["Name"],
key: item["Id"],
path: item["Url"],
icon: item["Icon"],
})
}
})
}
},
};
</script>
<style scoped>
.el-row {
width: 200px;
}
</style>
看一下系统界面,好像不太对劲,F12一下,果然,报错了
原来是因为前面的element-ui只是安装了,还没有引用,赶快在src文件夹的main.js文件里引用一下,顺便把element-ui的中文包也引用了
import ElementUI from 'element-ui'
import enLocale from 'element-ui/lib/locale/lang/en' //英文
import zhLocale from 'element-ui/lib/locale/lang/zh-CN' //中文
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(
ElementUI,
{ zhLocale },
)
刷新一下页面,好了
修改一下样式
App.vue的样式改成这样
<style>
html,body,#app{
width:100%;
height:100%;
margin: 0px;
padding: 0;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: hidden;
user-select: none;
}
</style>
Home.vue的样式改成这样
<style scoped>
.home,main{
height: 100%;
}
h1,
h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
div上加个home类
菜单栏父菜单加点图片
链接:https://pan.baidu.com/s/1o8GUxudunhQ9HS8b15nlPw
提取码:m4iz
现在该让点击子菜单弹出弹窗了,直接用别人写好的方法
链接:https://pan.baidu.com/s/1bmLs8Tw5N3Eb0X7P1190dQ
提取码:ed51
将解压好的layer文件夹放到src文件里的components文件夹里,别忘了引用一下,打开src文件夹下的main.js文件,改完之后就变成了这样
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import enLocale from 'element-ui/lib/locale/lang/en' //英文
import zhLocale from 'element-ui/lib/locale/lang/zh-CN' //中文
import 'element-ui/lib/theme-chalk/index.css'
import layer from '../src/components/layer/layer.js'
Vue.config.productionTip = false
Vue.use(
ElementUI,
{ zhLocale },
)
Vue.prototype.$layer=layer(Vue)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
已运行就报错了,分析原因是缺少依赖,那就安装
npm install less less-loader --save-dev
好的,旧错消失了,新错又来了,分析一下是刚才安装的less-loader版本过高(在package.json文件里可以查看所安的模块的版本),只好卸掉重装一个版本低的,
卸掉:
npm uninstall less-loader
安装指定版本:
npm install less-loader@5.0.0
重新运行,可以了
现在我们在src文件夹下新建一个views文件夹用来放置我们的菜单弹窗
在views文件夹里新建4个vue空白文件,我将其命名为MapQuery.vue,ThematicMap.vue,DataManagement.vue,BusinessLog.vue
在Menu.vue里添加select事件(菜单激活回调)
@select="handleSelect"
在Menu.vue里引入这四个页面
import MapQuery from '../views/MapQuery.vue'
import ThematicMap from '../views/ThematicMap.vue'
import DataManagement from '../views/DataManagement.vue'
import BusinessLog from '../views/BusinessLog.vue'
handleSelect方法:
//菜单激活
handleSelect (key) {
switch (key) {
case "1001":
this.$layer.iframe({
content: {
content: MapQuery,
parent: this,
},
area: ["550px", "570px"],
title: "地图查询",
maxmin: true,
shade: false,
shadeClose: false,
resize: true,
cancel: () => {
//关闭事件
this.$layer.close(this.layerid);
},
});
break;
case "1002":
this.$layer.iframe({
content: {
content: ThematicMap,
parent: this,
},
area: ["550px", "570px"],
title: "专题图",
maxmin: true,
shade: false,
shadeClose: false,
resize: true,
cancel: () => {
//关闭事件
this.$layer.close(this.layerid);
},
});
break;
case "2001":
this.$layer.iframe({
content: {
content: DataManagement,
parent: this,
},
area: ["550px", "570px"],
title: "数据管理",
maxmin: true,
shade: false,
shadeClose: false,
resize: true,
cancel: () => {
//关闭事件
this.$layer.close(this.layerid);
},
});
break;
case "3001":
this.$layer.iframe({
content: {
content: BusinessLog,
parent: this,
},
area: ["550px", "570px"],
title: "业务日志",
maxmin: true,
shade: false,
shadeClose: false,
resize: true,
cancel: () => {
//关闭事件
this.$layer.close(this.layerid);
},
});
break;
default:
break;
}
},
刷新一下页面,看看效果
弹窗头部的关闭按钮都看不见了,赶快改改样式,在src文件夹下新建style文件夹,在style文件夹下新建blue.css文件,后面我们要改样式主要就在这里面修改好了,blue.css内容为这
/* 弹窗样式 开始 */
.vl-notify.vl-notify-alert h2.vl-notice-title {
background-color: rgba(8,79,144, 0.9) !important;
height: 32px !important;
line-height: 32px !important;
color: white !important;
}
.vl-notify.vl-notify-main{
border: none !important;
}
/* 放大缩小关闭按钮样式 */
.vlicon-mini:before,
.vlicon-max:before,
.vl-notify.vl-notify-alert h2.vl-notice-title .icon-remove:before,
.el-icon-close:before {
color: white;
}
别忘了在main.js里引用一下
import './style/blue.css'
现在系统的框就初见端倪了
3,esri-loader加载地图
背景空空的,决定放幅地图上去,于是就要引入esri-loader模块了
npm install esri-loader@2.16.0
别忘了在main.js里引用
在config文件夹里新建config.js文件,我们将前面发布的arcgis js api地址放到config.js文件里,
//地图js
window.arcjsUrl = 'http://localhost:1570/arcgis_js_v314_api/arcgis_js_api/library/3.14/3.14/init.js'
//地图css
window.arcCssUrl = "http://localhost:1570/arcgis_js_v314_api/arcgis_js_api/library/3.14/3.14/esri/css/esri.css"
在main.js文件里引用一下
import MAP from '../config/config'
在arcgis js api下引用天地图,Map.vue如下
<template>
<div class="mapContainer">
<!-- 地图 -->
<div ref="viewDiv"
style="width:100%;height:100%">
</div>
</div>
</template>
<script>
import esriLoader from 'esri-loader' //地图加载器
export default {
data () {
return {
};
},
computed: {
},
mounted () {
this.arcgisInit(this.$refs.viewDiv);
},
methods: {
/**
* 初始化地图
*/
arcgisInit (div) {
var that = this;
//arcgis api js文件
const options =
{
url: window.arcjsUrl
};
console.log(window.arcjsUrl)
//arcgis api css文件
esriLoader.loadCss(window.arcCssUrl);
esriLoader
.loadModules(
[
"esri/map",
"esri/layers/TileInfo",
"esri/layers/WebTiledLayer",
"esri/geometry/Point",
"dojo/dom",
"dojo/on",
"dojo/domReady!"
],
options
)
.then(([
Map
]) => {
//创建地图
var mapPoint = new esri.geometry.Point([117.124674, 36.657017], new esri.SpatialReference({ wkid: 4490 }));
var config = {
width: "100%",
logo: false,
zoom: 4,
slider: false,
fadeOnZoom: true,
center: mapPoint
//force3DTransforms: true
};
var map = new esri.Map(div, config); //ersi.Map类是一种容器,其中可以放置图层等。div为显示地图的DIV;config为地图相关参数设置
//通过瓦片形式加载天地图,设定瓦片信息
var tileInfo = new esri.layers.TileInfo({
"rows": 256,//瓦片行编号
"cols": 256,//瓦片列编号
"compressionQuality": 0,
"origin": {
"x": -180,
"y": 90
},
"spatialReference": {
"wkid": 4490
},
"lods": [
{
"level": 2,//level:当前缩放级别,包括两个参数:resolution:比例尺和scale:分辨率
"resolution": 0.3515625,
"scale": 147748796.52937502
},
{
"level": 3,
"resolution": 0.17578125,
"scale": 73874398.264687508
},
{
"level": 4,
"resolution": 0.087890625,
"scale": 36937199.132343754
},
{
"level": 5,
"resolution": 0.0439453125,
"scale": 18468599.566171877
},
{
"level": 6,
"resolution": 0.02197265625,
"scale": 9234299.7830859385
},
{
"level": 7,
"resolution": 0.010986328125,
"scale": 4617149.8915429693
},
{
"level": 8,
"resolution": 0.0054931640625,
"scale": 2308574.9457714846
},
{
"level": 9,
"resolution": 0.00274658203125,
"scale": 1154287.4728857423
},
{
"level": 10,
"resolution": 0.001373291015625,
"scale": 577143.73644287116
},
{
"level": 11,
"resolution": 0.0006866455078125,
"scale": 288571.86822143558
},
{
"level": 12,
"resolution": 0.00034332275390625,
"scale": 144285.93411071779
},
{
"level": 13,
"resolution": 0.000171661376953125,
"scale": 72142.967055358895
},
{
"level": 14,
"resolution": 8.58306884765625e-005,
"scale": 36071.483527679447
},
{
"level": 15,
"resolution": 4.291534423828125e-005,
"scale": 18035.741763839724
},
{
"level": 16,
"resolution": 2.1457672119140625e-005,
"scale": 9017.8708819198619
},
{
"level": 17,
"resolution": 1.0728836059570313e-005,
"scale": 4508.9354409599309
},
{
"level": 18,
"resolution": 5.3644180297851563e-006,
"scale": 2254.4677204799655
}
]
});
//基础地图
// 经纬度矢量地图瓦片的URL: http://t4.tianditu.com/DataServer?T=vec_c&X=27&Y=3&L=5
//,域名中的 t4 部分代表子域字段,X是列编号,Y是行编号 ,L是当前缩放级别。对这几个部分用列表里的参数替换,后面再加上key,就变成了下面的样子
var baseMap = new esri.layers.WebTiledLayer("http://{subDomain}.tianditu.com/DataServer?T=vec_c&X={col}&Y={row}&L={level}&tk=35f5a8d92de539752d6a5c885d978380", {
"copyright": "Tianditu",
"id": "Tianditu",
"subDomains": ["t0", "t1", "t2"],//经查询天地图瓦片分别有t0,t1,t2,t3,t4,t5,t6,t7八个子域
"tileInfo": tileInfo
});
//添加图层
map.addLayer(baseMap);
//标注成
var baseMapMarker = new esri.layers.WebTiledLayer("http://{subDomain}.tianditu.com/DataServer?T=cva_c&X={col}&Y={row}&L={level}&tk=35f5a8d92de539752d6a5c885d978380", {
"copyright": "Tianditu",//版权,Web平铺层提供程序的归属。它显示在网络地图的归属中。将图层添加到Web地图时用户所需的输入。
"id": "Tianditu2",//图层的唯一标识字符串。
"subDomains": ["t0", "t1", "t2"],//子域,如果检测到子域,则必须指定它们。地图查看器通过解析{subDomain}的templateURL值来检测Web Tiled图层是否具有子域。
"tileInfo": tileInfo //包含空间参考和图层的平铺方案。通常从WMTS OGC Web服务检索。如果缺少该图层,则必须使用WGS 1984 Web Mercator(辅助球)拼贴方案。
});
//将图层baseMapMarker添加到地图上
map.addLayer(baseMapMarker);
//地图中心点
map.centerAt(new esri.geometry.Point({
"x": 117.124674,
"y": 36.657017,
"spatialReference": {
"wkid": 4490
}
}), 13);
//地图级别
map.setLevel(13);
//关闭键盘导航
//map.disableKeyboardNavigation()
map.on('extent-change', function () {
});
})
},
},
};
</script>
<style lang="css">
.mapContainer {
width: 100%;
height: 100%;
}
.infoBox {
position: absolute;
bottom: 10px;
right: 10px;
height: 30px;
background-color: #1f5f9a;
opacity: 0.95;
}
.infoBox .positionInfo {
color: white;
font-size: 0.5em;
line-height: 30px;
margin: 0 10px;
}
.infoBox .map-legend {
cursor: pointer;
}
.blurInfo {
display: none;
position: absolute;
top: 10px;
right: 5px;
font-size: 1.25em;
font-family: monospace;
color: #4c4c4c;
width: 240px;
background-color: #ffffff;
padding: 10px;
border: 2px solid #57585a;
border-radius: 20px;
}
.blurInfo p span {
background-color: #ffffff;
padding: 0 5px;
border-radius: 5px;
}
.blurInfo input[type="range"] {
width: 100%;
display: block;
}
</style>
这就看起来好多了
4 ,我们再修饰一下页面
地址栏这#总觉得不太需要,让我们去掉它,
在router文件夹的index.js文件里加上这么一句话就行了
mode:"history"
test,网页名称,让我们另外起一个名字,
在index.html文件将
<title>test</title>
改成
<title>信息管理系统</title>
然后那个小地球明显是一个图标的位置,我们找一张图片,格式改成.ico,将这个文件放到static文件夹里,然后在index.html里加上这么一句
<link rel="icon" href="./static/favicon.ico">
结果:
好的,这一篇内容到这里就结束了了,下一篇中,我们将实现构建后台,从数据库读取数据生成菜单栏和登录登出功能
更多推荐
所有评论(0)