从零开始,构建电子地图网站:0_12_创建工程VUE2脚手架+element布局+router路由
前端框架很多,vue相对来说上手快点,所以这里选用vue。
地图js api也很多,百度、高德、腾讯、天地图都有,都是基于其自身的地图地图封装的,我们这里选择一个更经典、更原生的leaflet,这样就可以不囿于地图底图限制,且leaflet是瓦片加载,性能更好些。
写程序,不管是后端,还是前端,跟造房子有点像,都需要先有框架,再往里面填塞。
我们的前端程序,大致是这么个步骤。
1.先用vue搭建个工程出来。
2.用element做个布局。
3.用leaflef加载个地图。
4.axios跟后端交互个数据。
5.webpack打包,整合进后端。
闲话少叙,进入环境搭载。
一、安装nodejs
下载个吻合电脑版本号的安装程序:http://nodejs.cn/download/。
一直安装下去即可。
然后配置一下系统和环境变量。
安装与配置方法参见:
https://www.cnblogs.com/liuqiyun/p/8133904.html
先运行一下:npm i -g npm,把版本升级至最新版,这个注意下,因为不升级,安装模块的时候,容易报错。
随便安装个模块试一试。
运行:npm i express -g。
i其实就是install的简写。
二、搭建VUE2脚手架
以管理员身份打开cmd。
- 切换路径
切换到D:\gismap\git路径下,我把前端工程放在这里。
d:
cd gismap
cd git
- 全局安装webpack
Webpack是一个打包工具,webpack和webpack-cli两个都全局安装一下吧。
npm install webpack -g
npm install webpack-cli -g
查看webpack版本:
webpack -v
- 全局安装脚手架vue-cli
为了避免安装过程中出现错误,安装程序一直下载不下来,我们清除一下缓存,并更新一下源。
清缓存:
npm cache clean –force
换源:
npm config set registry http://registry.cnpmjs.org
查看npm源:
npm config get registry
查看vue版本
vue -V
安装脚手架:
npm install --global vue-cli
- 用vue-cli新建项目
就在git这个文件夹下面新建项目。
vue init webpack vue-gismap
出现? Project name (vue-gismap),直接回车,我的工程就是这个名字。
出现?Project description (A Vue.js project),直接回车,我的工程描述就是这个。
出现?Author……,直接回车,工程建立者就是我。
出现?Vue build(User arrow keys),直接回车,默认推荐的Runtime+Compiler。
出现?Install vue-router? (Y/n),敲y,安装路由。
出现?Use ESLint to lint your code? (Y/n),敲n,不安装ESlint管理代码,这个对初学者不太友好,不允许有一点点代码不规范。
出现?Setup unit tests with Karma + Mocha? (Y/n),敲n,不安装单元测试。
出现?Setup e2e tests with Nightwatch(Y/n)?敲n,不要这个,要不然写程序的时候,会经常出现警告。
出现?Should we run ‘npm install’ for you after the project has been created?,直接回车,选默认的yes,user NPM。以后都用npm安装模块。
等待安装就可以了。
出现提示:
To get started:
cd vue-gismap
npm run dev
照着做就行。
运行完,提示Your application is running here: http://localhost:8080
打开网页,长这样。说明工程搭建成功。
- 安装element
Ctrl+C,退出dev界面。
安装element,就不用自己设计界面了。
应用可参见官方文档:https://element.eleme.cn/#/zh-CN/component/quickstart
npm i element-ui -S
安装vue-awesom,各种icon都在这里。
npm i vue-awesome -S
安装normalize.css
npm install –save normalize.css
- 配置sublime
用管理员权限打开sublime,用这个IDE编写前端。
Shift+ctrl+p,输入install package control,安装,最下面深灰色进度条,注意一下有93%这样的进度,等几分钟会跳出提示框,提示安装成功,重启sublime。
别重启,输入install package,安装。
再安装下vue syntax hightlight,代码颜色提示。
再安装下color highlight,颜色提示,例如#fff上面就是白色,#000上面就是黑色。
再安装下HTML-CSS-JS Prettify,代码规范化插件,ctrl+A,右键——HTML/CSS/JS Prettify——Prettify Code。
重启sublime。
打开sublime,File——open folder,打开vue-gismap文件夹。
三、布局
- 样式效果
一样一样来,先做一下页面布局。
大概长这个样子:顶部三个tab标签,历史地图、专题地图、帮助文档;左侧一栏树状复选框,用以选择朝代,中间部分是地图,右侧是一个可隐藏的表,用以显示属性。
布局采用了layout+container,路由用的是router,左侧的树状结构是tree控件,右侧点击“打开嵌套表格的drawer”,弹出的是drawer控件,内嵌table控件。
- 文件结构
文件结构如下图所示,src文件夹下有components、js、router三个文件夹。
安装完vue脚手架,在src文件夹下会生成一些默认的文件夹和组件,不需要的直接删掉就可以,右键——new file/new folder,新建需要的文件和文件夹即可。
3.main.js
这个文件,主要是把用到的一些依赖导入,这些依赖都在文件夹node_modules下。
// 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 ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import NormailizeCss from 'normalize.css'
import 'vue-awesome/icons'
import Icon from 'vue-awesome/components/Icon'
import router from './router'
Vue.config.productionTip = false
Vue.use(ElementUI)
Vue.component('icon', Icon)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
4.App.vue
首页组件,vue组件的结构都是:
<template></ template >
<script></script>
<style></style>
这个样子的,其他组件通过import来引入。
更改全局样式在App.vue的<style>中,因为浏览器自带的滚动条太丑,所以在这里更改了全局的滚动条。
<router-view></router-view>引入的是路由视图。
<template>
<div id="app">
<el-container>
<el-header class="header">
<vheader />
</el-header>
<el-container>
<el-main class="el-main">
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import Header from '@/components/Header'
export default {
name: 'app',
components: {
'vheader': Header
}
}
</script>
<style>
.header {
background-color: #c00000;
color: #fff;
line-height: 60px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
line-height: 160px;
height: 500px;
}
/*更改全局的滚动条样式*/
::-webkit-scrollbar {
width: 8px;
height: 8px;
background-color: #fff;
}
::-webkit-scrollbar-thumb {
// border-radius:5px;
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
background-color: rgba(0, 0, 0, .1)
}
</style>
5.Header.vue
这个就是主页面砖红色的菜单栏,历史地图、专题地图、帮助文档。
<el-row><el_col>用layout进行了一个布局。
<el-menu>引入菜单。
<router-link>引入路由,点击跳转页面。
<template>
<el-row :gutter="20">
<el-col :span="4">中国历史地图</div></el-col>
<el-col :span="16">
<el-menu class="el-menu-demo" mode="horizontal"
background-color="#c00000"
text-color="#fff"
active-text-color="#000">
<el-menu-item index="1">
<span><router-link to="/">历史地理</router-link></span>
</el-menu-item>
<el-menu-item index="2">
<span><router-link to="/specialmap">专题地图</router-link></span>
</el-menu-item>
<el-menu-item index="3">
<span><router-link to="/helperdocument">帮助文档</router-link></span>
</el-menu-item>
</el-menu>
</el-col>
</el-row>
</template>
<style>
.el-row {
/* margin-top:10px;
*/ margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
.el-col {
border-radius: 4px;
}
.bg-purple {
background: #d3dce6;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
</style>
6.router/index.js
路由信息放在这个文件中。
Path是url路径,是一个相对路径,component是组件页面。
例如点击Header.vue中的帮助文档,就会跳转到HelperDocument.vue页面,url: http://localhost:8080/#/helperdocument。
import Vue from 'vue'
import Router from 'vue-router'
import HistoryMap from '@/components/HistoryMap'
import SpecialMap from '@/components/SpecialMap'
import HelperDocument from '@/components/HelperDocument'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'historymap',
component: HistoryMap
},{
path: '/specialmap',
name: 'specialmap',
component: SpecialMap
},{
path:'/helperdocument',
name:'helperdocument',
component:HelperDocument
}
]
})
7. HistoryMap.vue
这里主要两个控件,一个是<el-tree>,它的数据单独放在了js/treedata.js中了。一个是<el-drawer>,数据在<script>的gridData中。
methods 中有一个方法changecheck(e,data),e是当前选中的eltree节点,这个方法的用处是,对于复选框状态来说,父节点直接影响子节点。
<template>
<div>
<div style="background-color: #fff; height: 75vh;width: 200px;float:left;">
<el-scrollbar style="height: 100%;">
<el-tree :data="treedata" show-checkbox node-key="id" :props="defaultProps" @check="changecheck">
</el-tree>
</el-scrollbar>
</div>
<el-drawer title="属性" :visible.sync="table" direction="rtl" size="20%">
<el-table :data="gridData" height=85vh border>
<el-table-column property="field" label="字段" width="100"></el-table-column>
<el-table-column property="value" label="值" width="200"></el-table-column>
</el-table>
</el-drawer>
<el-button type="text" @click="table = true">打开嵌套表格的 Drawer</el-button>
</div>
</template>
<script>
import { treedata } from '../js/treedata.js'
export default {
data() {
return {
treedata: treedata,
defaultProps: {
children: 'children',
label: 'label'
},
table: false,
gridData: [{
field: 'name_py',
value: 'Baode Zhou'
}, {
field: 'name_ch',
value: '保德州'
}, {
field: 'name_ft',
value: '保德州'
}, {
field: 'pres_loc',
value: '山西保德县城西侧'
}, {
field: 'type_ch',
value: '州'
}, {
field: 'lev_rank',
value: '6'
}, {
field: 'beg_yr',
value: 1376
}, {
field: 'beg_rule',
value: '4'
}, {
field: 'end_yr',
value: 1911
}, {
field: 'geo_src',
value: 'FROM_AC'
}, {
field: 'compiler',
value: ''
}, {
field: 'gecomplr',
value: ''
}, {
field: 'checker',
value: ''
}, {
field: 'ent_date',
value: ''
}, {
field: 'beg_chg_ty',
value: '更名'
}, {
field: 'end_chg_ty',
value: '数据下限'
}]
};
},
methods: {
changecheck(e, data) {
if (e['level'] === 1) {
e['ischeck'] = !e['ischeck'];
for (var i = 0; i < e['children'].length; i++) {
e['children'][i]['ischeck'] = e['ischeck'];
for (var j = 0; j < e['children'][i]['children'].length; j++) {
e['children'][i]['children'][j] = e['ischeck'];
}
}
} else if (e['level'] === 2) {
e['ischeck'] = !e['ischeck'];
e['children'][0]['ischeck']=e['ischeck'];
e['children'][1]['ischeck']=e['ischeck'];
e['children'][2]['ischeck']=e['ischeck'];
} else {
e['ischeck'] = !e['ischeck'];
}
console.log(e);
}
}
};
</script>
<style>
</style>
8. treedata.js
eltree的数据放在这里了。
export const treedata = [{
id: 0,
label: '全部内容',
ischeck: false,
level: 1,
timerange: [-5000, 1840],
children: [{
id: 1,
label: '商周',
ischeck: false,
level: 2,
timerange: [-5000, -221],
children: [{
id: 2,
label: 'cnty点',
ischeck: false,
level: 3,
timerange: [-5000, -221]
}, {
id: 3,
label: 'pref点',
ischeck: false,
level: 3,
timerange: [-5000, -221]
}, {
id: 4,
label: 'pref面',
ischeck: false,
level: 3,
timerange: [-5000, -221]
}]
}, {
id: 5,
label: '秦',
ischeck: false,
level: 2,
timerange: [-220, -202],
children: [{
id: 6,
label: 'cnty点',
ischeck: false,
level: 3,
timerange: [-220, -202]
}, {
id: 7,
label: 'pref点',
ischeck: false,
level: 3,
timerange: [-220, -202]
}, {
id: 8,
label: 'pref面',
ischeck: false,
level: 3,
timerange: [-220, -202]
}]
}, {
id: 9,
label: '汉',
ischeck: false,
level: 2,
timerange: [-201, 220],
children: [{
id: 10,
label: 'cnty点',
ischeck: false,
level: 3,
timerange: [-201, 220],
}, {
id: 11,
label: 'pref点',
ischeck: false,
level: 3,
timerange: [-201, 220],
}, {
id: 12,
label: 'pref面',
ischeck: false,
level: 3,
timerange: [-201, 220],
}]
}, {
id: 13,
label: '晋三国',
ischeck: false,
level: 2,
timerange: [221, 589],
children: [{
id: 14,
label: 'cnty点',
ischeck: false,
level: 3,
timerange: [221, 589],
}, {
id: 15,
label: 'pref点',
ischeck: false,
level: 3,
timerange: [221, 589],
}, {
id: 16,
label: 'pref面',
ischeck: false,
level: 3,
timerange: [221, 589],
}]
}, {
id: 17,
label: '隋唐',
ischeck: false,
level: 2,
timerange: [590, 907],
children: [{
id: 18,
label: 'cnty点',
ischeck: false,
level: 3,
timerange: [590, 907],
}, {
id: 19,
label: 'pref点',
ischeck: false,
level: 3,
timerange: [590, 907],
}, {
id: 20,
label: 'pref面',
ischeck: false,
level: 3,
timerange: [590, 907]
}]
}, {
id: 21,
label: '五代十国',
ischeck: false,
level: 2,
timerange: [908, 960],
children: [{
id: 22,
label: 'cnty点',
ischeck: false,
level: 3,
timerange: [908, 960],
}, {
id: 23,
label: 'pref点',
ischeck: false,
level: 3,
timerange: [908, 960],
}, {
id: 24,
label: 'pref面',
ischeck: false,
level: 3,
timerange: [908, 960]
}]
}, {
id: 25,
label: '宋',
ischeck: false,
level: 2,
timerange: [961, 1276],
children: [{
id: 26,
label: 'cnty点',
ischeck: false,
level: 3,
timerange: [961, 1276],
}, {
id: 27,
label: 'pref点',
ischeck: false,
level: 3,
timerange: [961, 1276],
}, {
id: 28,
label: 'pref面',
ischeck: false,
level: 3,
timerange: [961, 1276]
}]
}, {
id: 29,
label: '元',
ischeck: false,
level: 2,
timerange: [1277, 1368],
children: [{
id: 30,
label: 'cnty点',
ischeck: false,
level: 3,
timerange: [1277, 1368],
}, {
id: 31,
label: 'pref点',
ischeck: false,
level: 3,
timerange: [1277, 1368],
}, {
id: 32,
label: 'pref面',
ischeck: false,
level: 3,
timerange: [1277, 1368]
}]
}, {
id: 33,
label: '明',
ischeck: false,
level: 2,
timerange: [1369, 1644],
children: [{
id: 34,
label: 'cnty点',
ischeck: false,
level: 3,
timerange: [1369, 1644],
}, {
id: 35,
label: 'pref点',
ischeck: false,
level: 3,
timerange: [1369, 1644],
}, {
id: 36,
label: 'pref面',
ischeck: false,
level: 3,
timerange: [1369, 1644]
}]
}, {
id: 37,
label: '清',
ischeck: false,
level: 2,
timerange: [1645, 1840],
children: [{
id: 38,
label: 'cnty点',
ischeck: false,
level: 3,
timerange: [1645, 1840],
}, {
id: 39,
label: 'pref点',
ischeck: false,
level: 3,
timerange: [1645, 1840],
}, {
id: 40,
label: 'pref面',
ischeck: false,
level: 3,
timerange: [1645, 1840]
}]
}]
}]
9. SpecialMap和HelperDocument
SpecialMap.vue
<template>
<div>
专题地图
</div>
</template>
HelperDocument.vue
<template>
<div>
帮助文档
</div>
</template>
这两个预留,可能以后会用专题地图这个页面做一个三维的地图。
四、git
https://github.com/yimengyao13/vue-gismap.git
element分支。
查看效果运行npm run dev。