Vue3+vite+Echarts案例大屏可视化--千峰(推荐)
https://www.bilibili.com/video/BV14u411D7qK?p=33&spm_id_from=pageDriver&vd_source=e2cfe74d93fb5b3f60bd7487ede60218
主题展示
Vue3.2中
<template> <!-- 为 ECharts 准备一个定义了宽高的 DOM --> <!--vue3中 id=‘’ 变更 ref=--> <div ref="chart" style="width:100%;height:200px;"></div> </template> <script setup > import {onMounted, reactive, ref} from "vue"; // 局部引入echarts核心模块 import * as echarts from 'echarts' // const props = defineProps({ // 宏接收:父传参 // 结构优化 const {chartType,chartData}= defineProps({ // 宏接收:父传参 chartType:{ type: String }, chartData: { type: Array } }) const chart =ref(); // 创建DOM引用 // 第二种方法:初始化方法 const option = reactive({ // 指定图表的配置项和数据 title: { // 标题 // left: 'center', // 居中 text: 'ECharts 入门示例', left: 'center', textStyle: { color: '#f60', fontSize: 20, } }, color: '#f00', // 系列柱的颜色 tooltip: {}, // 提示 legend: { // 图例 data: ['销量'], top: '5%', left: 'right', textStyle: { // 文字样式 color: '#f68', } }, xAxis: { // x轴 data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'], axisLine: { // 设置轴 lineStyle: { // 样式 color:'#000' // 颜色 } }, axisLabel:{ interval: 0, formatter: value => value.split('').join('\n') //报红:取消lang='ts' } }, yAxis: { // y轴 axisLine: { // 设置轴 lineStyle: { // 样式 color:'#000' // 颜色 } }, axisLabel:{ // formatter: '{value} 件' formatter: function(value,index){ // 报红:取消lang='ts' return value %2 == 0 ? value + '件' : value // 可写各种逻辑判断: 奇偶数 } } }, series: [ // data数据 { name: '销量', // type: 'bar', // 图样类型 // type: props.chartType, // 父传参:自定义 type:chartType, // 结构优化 // data: [5, 20, 36, 10, 10, 20], // 图标数据 // data: props.chartData, data: chartData, label: { show: true, position: 'top' }, } ] }) // 使用生命钩子 onMounted(() => { // 基于准备好的dom,初始化echarts实例 // var myChart = echarts.init(document.getElementById('main')); // Vue3中: 需要引入 var myChart = echarts.init(chart.value) // init(); // vue3.2没有this // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); // 单图表响应式: 跟随浏览器大小改变 window.addEventListener('resize',()=>{ myChart.resize() }) }) </script> <style scoped> </style>
自定义主题


在About.vue组件中引用assets/index.js文件

地图展示


Json.api地址拷贝后,浏览器地址栏打开

数据拷贝文档中起名 XXX.js
1.引用XXX.js地图数据
import {XXX} from "../assets/XXX.js"
// 引入echarts核心模块 import * as echarts from 'echarts' // 还需引入地图文件 import chinaMap from '../../assets/china1.json'
2.注册地图:Vue3.2
// 使用生命钩子 onMounted(() => { // 基于准备好的dom,初始化echarts实例 // var myChart = echarts.init(document.getElementById('main')); // Vue3中: 需要引入 var myChart = echarts.init(chart.value) // 注册可用的地图 echarts.registerMap('china',chinaMap); // init(); // vue3.2没有this // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option);
3.地图中的设定
如何获取地图经纬度:百度地图开放平台
map.baidu.com


点击后右上方

const option = reactive({// 指定图表的配置项和数据 geo: { // 地理坐标组件 type:"map", map: "china", roam:true, // 地图可拖拽、平移 zoom: 5, // 缩放大小 center: [116.387803,39.940361], // 地图中心点:经纬度 },
省份地图展示和优化
1.阿里云DataV.GeoAtlas地理小工具系列 (aliyun.com),获取地图省份信息
2.特效展示
option中 geo 和 series 功能相同,需注意处理:注意:echarts绘制地图提示框不出现。echarts绘制地图有两种方式,一种是geo对象,一种是series数组,geo对象生成的地图没有提示框,只有series数组生成的地图有提示框
地图标记设置与效果
option中series:常用重要属性设置
series: [{ // 地图不需XY轴
type: 'map', // 图表类型:散点图scatter:用到坐标系设置
map: 'china', // 地图类型
roam: true, // 地图可拖拽、平移
data: mapData, // 使用动态Api接口文档数据
/*[ // 展示数据项的名字,经纬度,数据量
{name:'河南省',value:32300,4000},
{name: '山东省',value: 21203},
{name: '四川省',value: 41203},
{name: '青海省',value: 31203},
],*/
coordinateSystem: "geo", // 当前坐标系设置:经纬度定位
完整代码
<template> <!-- 为 ECharts 准备一个定义了宽高的 DOM --> <!--vue3中 id=‘’ 变更 ref=--> <div ref="chart" style="width:650px;height:650px;"></div> </template> <script setup > import {onMounted, reactive, ref} from "vue"; // 引入echarts核心模块 import * as echarts from 'echarts' // 还需引入地图文件 import chinaMap from '../../assets/china1.json' // 引入动态数据axios,二次封装 import axios from "../../http/request"; // const mapData = await fetch(`/api/post/1`).then(r => r.json()) // 根据接口文档:实际参数获取数据 const mapData = await axios.get('student_location').then(res => res.data.result) const chart =ref(); // 创建DOM引用 // 第二种方法:初始化方法 const option = reactive({// 指定图表的配置项和数据 geo: { // 地理坐标组件,series type:"map", map: "china", roam:true, // 地图可拖拽、平移 zoom: 5, // 缩放大小 center: [116.387803,39.940361], // 地图中心点:经纬度 label: { show: true, // // 标签:地图中的标签、文字 color: "" } }, // option中 geo 和 series 功能相同, // 需注意处理:注意:echarts绘制地图提示框不出现。 // echarts绘制地图有两种方式,一种是geo对象,一种是series数组, // geo对象生成的地图没有提示框,只有series数组生成的地图有提示框 series: [{ // 地图不需XY轴 type: 'map', // 图表类型:散点图scatter:用到坐标系设置 map: 'china', // 地图类型 roam: true, // 地图可拖拽、平移 // data: mapData, // 使用动态Api接口文档数据 /*[ // 展示数据项的名字,经纬度,数据量 {name:'河南省',value:[32300,4000]}, {name: '山东省',value: 21203}, {name: '四川省',value: 41203}, {name: '青海省',value: 31203}, ],*/ data: [// 展示数据项的名字,经纬度,数据量 { name:'河南省',value:[32300,4000] }, ], coordinateSystem: "geo", // 当前坐标系设置:经纬度定位 symbolSize: 30, // 大小 label: { // 标签:地图中的标签、文字 show: true, // 开启地图中的标签、文字等,(必须开启) color: '#fff', fontSize:11, }, itemStyle:{ // 修改地图区域标签样式 areaColor: '#219edb', // 区域颜色 borderColor: '#fff', // 区域边框价格 }, emphasis: { // 地图高亮状态的多边形和标签样式 label:{ color: '#000', fontSize: 12, }, itemStyle: { areaColor: '#f60', borderColor: '#329edb' } }, }, { type: "effectScatter", // 涟漪(lianyi)效果 coordinateSystem: "geo", data: [ { name: "郑州", value:[ 108.95, 34.26 ] } ] } ], // 设置涟漪效果的相关配置 rippleEffect: { number: 2, // 波纹数量 scale: 4, // 波纹大小 }, itemStyle: { color: "red", } visualMap: { min: 800, max: 50000, text: ['High', 'Low'], realtime: false, calculable: true, inRange: { color: ['lightskyblue', 'yellow', 'orangered'] }, textStyle: { color:'#000' } }, }) // 使用生命钩子 onMounted(() => { // 基于准备好的dom,初始化echarts实例 // var myChart = echarts.init(document.getElementById('main')); // Vue3中: 需要引入init() Vue3.2没有this var myChart = echarts.init(chart.value) // 注册可用的地图 echarts.registerMap('china',chinaMap); // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); // 单图表响应式: 跟随浏览器大小改变 window.addEventListener('resize',()=>{ myChart.resize() }) }) </script> <style scoped> </style>
图表自适应大小
页面加载完后,监听页面大小的改变
// 单图表响应式: 跟随浏览器大小改变 window.addEventListener('resize',()=>{ myChart.resize() })
加载动画效果
加载等待效果
1. 全局下载:数据模拟数据 json-server
npm install -g json-server
2. 新建Src/Mock文件夹存放模拟数据,新建data.js文件
将data[ ]数组中的数据,拷贝出来,data,js中建立一个对象
// 拷贝数据:注意key要加双引号 “ ” // 创建一个 key "one":[ ]数组 { "one":[ { "value": 67, "name": "美食", "itemStyle":{ "normal": { "color": "rgb(1,175,80)" } } }, { "value": 85, "name": "日化", "itemStyle":{ "normal": { "color": "rgb(255.175.80)" } } }, { "value": 45, "name": "数码", "itemStyle":{ "normal": { "color": "rgb(1,0,80)" } } }, { "value": 98, "name": "家电", "itemStyle":{ "normal": { "color": "rgb(30,50,70)" } } } ] }
3.启动json-server
注意点 : 启动目录 Mock路径下

// 运行 监听 json文件 端口 json-server --watch data.json --port 8888

地址栏:输入查看请求数据
axios安装
npm install --save axios

axios:Url:localhost:9999对应着 json-server启动时的IP端口
Vue3.2写法
// 引入echarts核心模块 import * as echarts from 'echarts' // 还需引入地图文件 import chinaMap from '../../assets/china1.json' // 引入动态数据axios,二次封装 import axios from "../../http/request"; // const mapData = await fetch(`/api/post/1`).then(r => r.json()) // 根据接口文档:实际参数获取数据 const mapData = await axios.get('http://localhost:9999').then(res => res.data.result)
案列完整代码:
<template> <div ref="myChart" id="myChart"></div> </template> <script> import * as echarts from "echarts"; import axios from "axios"; // import {mapData} from "../assets/mapData.js" export default { data() { return { echartsData: {}, }; }, methods: { // 获取json-server数据 async linkData() { let mapnum = await axios({ url: "http://localhost:3000/one" }); console.log(mapnum.data); this.echartsData = mapnum.data; }, }, mounted() { // 1.初始化 let myChart = echarts.init(this.$refs.myChart); // 设置开始等待 myChart.showLoading(); // 调用数据请求方法 this.linkData().then(() => { myChart.hideLoading(); // 2.设置echarts数据 let option = { title: { text: "饼状图", subtext: "基本设置", left: "center", //设置位置居中 }, tooltip: { trigger: "item", //触发类型item数据项图形触发 }, 千锋大前端教研院 39.图表动画配置 legend: { orient: "vertical", //图例列表的布局朝向vertical纵向 left: "left", }, series: [ { name: "销售量", type: "pie", // 设置环形图 radius: ["40%", "70%"], //饼图的半径。数组的第一项是内半径,第二项是外半径。 // 设置环形图 label: { //饼图图形上的文本标签 show: true, position: "inside", //outside饼图扇区外侧inside饼图扇区内部center在饼图 中心位置 color: "yellow", }, labelLine: { //标签的视觉引导线配置 show: false, }, roseType: "area", //是否展示成南丁格尔图,通过半径区分数据大小 itemStyle: { //设置内容样式 color: "#c23531", shadowBlur: 200, shadowColor: "rgba(0, 0, 0, 0.5)", }, data: this.echartsData, }, ], }; // 4.设置图表绘制图表 myChart.setOption(option); }); }, }; </script> <style> #myChart { width: 500px; height: 500px; border: 1px solid red; } </style>
千锋Echarts+Vue3.0数据可视化项目
1.电脑上安装node.js
2.全局下载项目脚手架
vue-cli这个构建工具大大降低了webpack的使用难度,支持热更新,有webpack-dev-server的支持,相当于启动了一个请求服务器,给你搭建了一个测试环境,只关注开发就OK。
一.安装vue-cli
1、 使用npm(需要安装node环境)全局安装webpack,打开命令行工具输入:npm install webpack -g或者(npm install -g webpack),安装完成之后输入 webpack -v,如下图,如果出现相应的版本号,则说明安装成功。
注意:webpack 4.X 开始,需要安装 webpack-cli 依赖 ,所以使用这条命令 npm install webpack webpack-cli -g
2、 全局安装vue-cli,在cmd中输入命令:npm install --global vue-cli
3、安装完成之后输入 vue -V(注意这里是大写的“V”),如下图,如果出现相应的版本号,则说明安装成功。
npm install -g @vue/cli
npm install -g @vue/cli
# OR
yarn global add @vue/cli
建项目

把cmd的路径切换到指定路径下
vue create 项目名
输入命令后,会跳出几个选项让你回答:
-Project name (baoge): -----项目名称,直接回车,按照括号中默认名字(注意这里的名字不能有大写字母,如果有会报错_Sorry, name can no longer contain capital letters_),
Project description (A Vue.js project): ----项目描述,也可直接点击回车,使用默认名字
Author (): ----作者,输入你的大名
接下来会让用户选择:
Runtime + Compiler: recommended for most users 运行加编译,既然已经说了推荐,就选它了
Runtime-only: about 6KB lighter min+gzip, but templates (or any
Vue-specificHTML) are ONLY allowed in .vue files - render functions
are required elsewhere 仅运行时,已经有推荐了就选择第一个了
Install vue-router (Y/n) 是否安装vue-router,这是官方的路由,大多数情况下都使用,这里就输入“y”后回车即可。
_Use ESLint to lint your code (Y/n)
是否使用ESLint管理代码,ESLint是个代码风格管理工具,是用来统一代码风格的,一般项目中都会使用。 接下来也是选择题_Pick an
ESLint preset (Use arrow keys) 选择一个ESLint预设,编写vue项目时的代码风格,直接y回车
Setup unit tests with Karma + Mocha (Y/n) 是否安装单元测试,我选择安装y回车
Setup e2e tests with Nightwatch(Y/n) 是否安装e2e测试 ,我选择安装y回车
回答完毕后上图就开始构建项目了。
2、配置完成后,可以看到目录下多出了一个项目文件夹baoge,然后cd进入这个文件夹:
安装依赖:npm install
一、vite环境搭建,构建vite-vue-ts项目
1、快捷建立Vite+Vue3
npm init vite@latest
# npm 6.x npm create vite@latest my-vue-app --template vue # npm 7+, extra double-dash is needed: npm create vite@latest myapp -- --template vue # yarn yarn create vite my-vue-app --template vue # pnpm pnpm create vite my-vue-app --template vue
2:更改http://localhost:3000/到8080与Network路由访问
在vite.config.ts里面加入:(server对象为新增,其他均是原有代码)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server:{
host:'0.0.0.0',//解决vite use--host to expose
port:8080,
open:true
}
})
3:配置vite别名(npm install @types/node --save-dev)
在vite.config.ts里面加入:(resolve对象为新增)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server:{
host:'0.0.0.0',//解决vite use--host to expose
port:8080,
open:true
},
resolve:{
alias:[
{
find:'@',
replacement:resolve(__dirname,'src') // 优化: '@': resolve(__dirname,'src')
}
]
}
})
4:路由(npm install vue-router@4)
src下新建目录router→index.ts
import {createRouter,createMemoryHistory,RouteRecordRaw} from 'vue-router'
import Layout from '@/components/HelloWorld.vue' // 路径报红: @ 变更 。。
const routes:Array<RouteRecordRaw> =[
{
path:'/',
name:'home',
component:Layout
}
]
// 创建
const router = createRouter({
history:createMemoryHistory(),
routes
})
// 暴露接口
export default router
在main.ts下 import router from './router/index' 引入路由
在main.ts下 app.use(router)注册路由
5:vuex(npm install vuex@next --save)或者Pinia(npm install pinia@next --save)
Pinia和Vuex一样都是是vue的全局状态管理器。其实Pinia就是Vuex5
https://pinia.web3doc.top/getting-started.html#%E5%AE%89%E8%A3%85
yarn add pinia
# 或者使用 npm
npm install pinia
设置为全局对象,在main.js中引用
import { createPinia } from "pinia";// 创建pinia实例const pinia = createPinia()app.use(pinia)
创建
pinia创建
// stores/todo.js import { defineStore } from 'pinia' export const useTodoStore = defineStore({ id: 'todo', state: () => ({ count: 0, title: "Cook noodles", done:false }) })
src下新建目录store→index.ts
打开vuex官网(Vuex 是什么? | Vuex)找到TypeScript支持下的“简化 useStore 用法”直接复制所有代码就可以
在App.vue下<router-view></router-view>
import { InjectionKey } from 'vue'
import { createStore, useStore as baseUseStore, Store } from 'vuex'
export interface State {
count: number
}
export const key: InjectionKey<Store<State>> = Symbol()
export const store = createStore<State>({
state: {
count: 0
},
mutations:{
setCount(state:State,i:number){
state.count = i
}
},
getters:{
getCount(state:State){
return state.count
}
}
})
// 定义自己的 `useStore` 组合式函数
export function useStore () {
return baseUseStore(key)
}
在main.ts下 import {store,key} from './store/index' 引入vuex
在main.ts下 app.use(store,key)注册路由
(如有疑问可参考官网TypeScript支持下的“useStore 组合式函数类型声明”)
pinia在vue3中的写法和用法
store/index.ts共享组件
import {ref} from 'vue'
// 共享组件
import {defineStore} from "pinia";
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})
// store.js import { defineStore } from "pinia" // defineStore 调用后返回一个函数,调用该函数获得 Store 实体
export const GlobalStore = defineStore({ // id: 必须的,在所有 Store 中唯一 id: "myGlobalState", // state: 返回对象的函数 state: () => ({ a: 1, }), getters: {}, actions: { setXXX(number) { this.a = number; }, }, });
// 在vue3中使用 <template> <div> {{number}} <button @click="clickHandle">按钮</button> </div> </template>
<script> import {GlobalStore} from "@/store/store.js" export default { setup(){ let store = GlobalStore(); //如果直接取state的值必须使用computed才能实现数据的响应式 如果直接取 store.state.a 则不会监听到数据的变化,或者使用getter,就可以不使用computed (这边和vuex是一样的) let number = computed(()=>store.a) const clickHandle = () => { store.setXXX("100") } return{number,clickHandle} }
} </script>
6:Eslint(可选)(npm install --save-dev eslint eslint-plugin-vue)
根目录新建文件.eslintrc.js
module.exports = { root: true, parserOptions: { sourceType: 'module' }, parser: 'vue-eslint-parser', extends: ['plugin:vue/vue3-essential', 'plugin:vue/vue3-strongly- recommended', 'plugin:vue/ vue3-recommended'], env: { browser: true, node: true, es6: true }, rules: { 'no-console': 'off', 'comma-dangle': [2, 'never'] //禁止使用拖尾逗号 } } } }
7:less/sass(可选)(npm install -D sass sass-loader)
二.项目初始化?
<template> <div> 我是页面 </div> </template> <script> export default { name: "homePage" } </script> <style scoped> </style>
import {createRouter, createMemoryHistory, RouteRecordRaw,} from "vue-router";
const routes:Array<RouteRecordRaw> = [
{
path:'/page',
name:'page',
component: () => import('@/views/homePage.vue')
},
{ // 路由重定向配置:注意点
path:"/",
redirect:"/page",
}
]
// 创建
const router = createRouter({
history:createMemoryHistory(),
routes
})
// 暴露接口
export default router
<template> <!--router/index已设定路由--> <router-view/> </template> <script setup lang="ts"> </script> <style scoped> * { /* 清除样式 */ margin:0px; padding: 0px; box-sizing: border-box; /*盒子大小:包含border-box*/ } </style>
三、项目分辨率响应式分析与实施
项目基本结构
下框内分为:左中右

技术栈
6.Element-plus :npm install element-plus --save
四.项目分辨率响应式创建
npm i -S lib-flexible
import { createApp } from 'vue'
// import './style.css'
import App from './App.vue'
import router from "./router/index";
// import store from "vuex";
// 引入element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 引用
import 'lib-flexible/flexible.js'
createApp(App).use(ElementPlus).use(router).mount('#app')
function refreshRem(){ var width = docEl.getBoundingClientRect().width; // 元数据:大小 /*if (width / dpr > 540) { width = 540 * dpr; } var rem = width / 10;*/ // 修改:最小400px,最大适配2560px if (width / dpr < 400) { width = 400 * dpr; }else if (width / dpr > 2560){ width = 2560 * dpr } // 设置成24份,1920Px设计稿 1rem 就是80px (1920/24=80) var rem = width / 24; // 原10 docEl.style.fontSize = rem + 'px'; flexible.rem = win.rem = rem; }
cssrem插件
配置方式
测试与使用
五.项目顶部信息条创建
body { background: url("./assets/xinguan.jpg") no-repeat fixed center; background-size: cover; }
<template>
<!--上部:标题-->
<el-row class="top">
<el-col :span="24" >
<div class="grid-content ep-bg-purple-dark" >
<h1>大数据座舱</h1>
</div>
</el-col>
</el-row>
<!--下部:左中右-->
<el-row class="main">
<el-col :span="8" class="itemLeft">
<div class="grid-content ep-bg-purple" >Aside</div>
</el-col>
<el-col :span="8">
<div class="grid-content ep-bg-purple-light" >Main</div>
</el-col>
<el-col :span="8">
<div class="grid-content ep-bg-purple-light" >Aside</div>
</el-col>
</el-row>
</template>
<script setup>
</script>
<style lang="scss">
.el-row {
margin-bottom: 20px;
}
.el-row:last-child {
margin-bottom: 0;
}
.el-col {
border-radius: 4px;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.top {
height: 1rem; // 1rem=80px
width: 100%;
background-color: rgba(0,0,255,0.1); // 色度 0.2透明度
// 标题的文字样式
h1{
font-size: 0.375rem;
color: #fff;
text-align: center; // 居中方式
line-height: 1rem; // 1rem=80px
}
}
</style>
六.页面主体创建
<!--下部:左中右-->
<el-row class="main">
<el-col :span="8" class="itemLeft">
<div class="grid-content ep-bg-purple" >Aside</div>
</el-col>
<el-col :span="8">
<div class="grid-content ep-bg-purple-light" >Main</div>
</el-col>
<el-col :span="8">
<div class="grid-content ep-bg-purple-light" >Aside</div>
</el-col>
</el-row>

创建容器样式
<style lang="less"> header{ height: 1rem; width: 100%; /* 设置一个半透明淡蓝色 */ background-color: rgba(0, 0, 255, .2); /* 把标题文字样式设置 */ h1{ font-size: .375rem; color:#fff; text-align: center; line-height: 1rem; } } // 主体容器样式 .container{ // 这里就不需要设置使用rem了 使用rem那么页面就会根据html根结点大小改变而改变了 min-width: 1200px; max-width: 2048px; margin: 0 auto; // 盒子上10px 左右10px 下0的外边距 padding: .125rem .125rem 0; // 测试完成看到样式就删除掉 height: 500px; background-color: gray; } </style
左右图表展示区块容器样式
<!--共享容器组件--> <template> <div class="item "> <!--设置插槽--> <slot></slot> </div> </template> <script setup> </script> <style scoped lang="less"> .item { height: 5.125rem; border: 1px solid blue; //外边距20px margin:.25rem; background-color: rgba(13,130,255,0.851); } </style>
<template> <!--上部:标题--> <el-row class="top"> <el-col :span="24" > <div class="grid-content ep-bg-purple-dark" > <h1>蓝尔海--大数据座舱</h1> </div> </el-col> </el-row> <!--下部:左中右,justify 属性来定义子元素的排版方式,其取值为start、center、end、space-between、space-around或space-evenly。--> <el-row class="row-bg" justify="space-evenly"> <el-col :span="6" class="itemLeft"> <div class="grid-content ep-bg-purple" > <ItemPage> <ItemOne> </ItemOne> </ItemPage> <ItemPage> <ItemTwo> </ItemTwo> </ItemPage> </div> </el-col> <el-col :span="12" class="itemCenter"> <div class="grid-content ep-bg-purple-light" > <h2>地图展示</h2> </div> </el-col> <el-col :span="6"> <div class="grid-content ep-bg-purple" > <ItemPage> <ItemTree> </ItemTree> </ItemPage> <ItemPage> <ItemFour> </ItemFour> </ItemPage> </div> </el-col> </el-row> </template> <script setup> // 引入组件 import ItemPage from "../components/itemPage.vue" import ItemOne from "../components/itemOne.vue" import ItemTwo from "../components/itemTwo.vue" import ItemTree from "../components/itemThree.vue" import ItemFour from "../components/itemFour.vue" </script> <style lang="scss"> .el-row { margin-bottom: 20px; } .el-row:last-child { margin-bottom: 0; } .el-col { border-radius: 4px; // 边框圆角° margin: 0 auto; } .grid-content { border-radius: 4px; min-height: 36px; } .top { height: 1rem; // 1rem=80px width: 100%; background-color: rgba(0,0,255,0.1); // 色度 0.2透明度 // 标题的文字样式 h1{ font-size: 0.375rem; color: #fff; text-align: center; // 居中方式 line-height: 1rem; // 1rem=80px } } // 大容器的样式 /*.container { // 最大最小的宽度 !*min-width: 1200px; max-width: 2048px;*! !*margin: 0 auto; // 上容器边距 padding: .125rem 0.125rem 0; // 上下右边距*! !*height: 500px; background-color: gray;*! }*/ .itemCenter{ border: 1px solid blue; border-radius: 4px; } </style>
<template> <div> <h2>图表1</h2> <div class="chart"> 图表的容器 </div> </div> </template> <script setup> </script> <style scoped> </style>
<template> <!--上部:标题--> <el-row class="top"> <el-col :span="24" > <div class="grid-content ep-bg-purple-dark" > <h1>蓝尔海--大数据座舱</h1> </div> </el-col> </el-row> <!--下部:左中右,justify 属性来定义子元素的排版方式,其取值为start、center、end、space-between、space-around或space-evenly。--> <el-row class="row-bg" justify="space-evenly"> <el-col :span="6" class="itemLeft"> <div class="grid-content ep-bg-purple" > <ItemPage> <ItemOne> </ItemOne> </ItemPage> <ItemPage> <ItemTwo> </ItemTwo> </ItemPage> </div> </el-col> <el-col :span="12" class="itemCenter"> <div class="grid-content ep-bg-purple-light" > <h2>地图展示</h2> </div> </el-col> <el-col :span="6"> <div class="grid-content ep-bg-purple" > <ItemPage> <ItemTree> </ItemTree> </ItemPage> <ItemPage> <ItemFour> </ItemFour> </ItemPage> </div> </el-col> </el-row> </template> <script setup> // 引入组件 import ItemPage from "../components/itemPage.vue" import ItemOne from "../components/itemOne.vue" import ItemTwo from "../components/itemTwo.vue" import ItemTree from "../components/itemThree.vue" import ItemFour from "../components/itemFour.vue" </script> <style lang="scss"> .el-row { margin-bottom: 20px; } .el-row:last-child { margin-bottom: 0; } .el-col { border-radius: 4px; // 边框圆角° margin: 0 auto; } .grid-content { border-radius: 4px; min-height: 36px; } .top { height: 1rem; // 1rem=80px width: 100%; background-color: rgba(0,0,255,0.1); // 色度 0.2透明度 // 标题的文字样式 h1{ font-size: 0.375rem; color: #fff; text-align: center; // 居中方式 line-height: 1rem; // 1rem=80px } } // 大容器的样式 /*.container { // 最大最小的宽度 !*min-width: 1200px; max-width: 2048px;*! !*margin: 0 auto; // 上容器边距 padding: .125rem 0.125rem 0; // 上下右边距*! !*height: 500px; background-color: gray;*! }*/ .itemCenter{ border: 1px solid blue; border-radius: 4px; } </style>
<template> <!--上部:标题--> <el-row class="top"> <el-col :span="24" > <div class="grid-content ep-bg-purple-dark" > <h1>蓝尔海--大数据座舱</h1> </div> </el-col> </el-row> <!--下部:左中右,justify 属性来定义子元素的排版方式,其取值为start、center、end、space-between、space-around或space-evenly。--> <el-row class="row-bg" justify="space-evenly"> <el-col :span="6" class="itemLeft"> <div class="grid-content ep-bg-purple" > <ItemPage> <ItemOne> </ItemOne> </ItemPage> <ItemPage> <ItemTwo> </ItemTwo> </ItemPage> </div> </el-col> <el-col :span="12" class="itemCenter"> <div class="grid-content ep-bg-purple-light" > <h2>地图展示</h2> </div> </el-col> <el-col :span="6"> <div class="grid-content ep-bg-purple" > <ItemPage> <ItemTree> </ItemTree> </ItemPage> <ItemPage> <ItemFour> </ItemFour> </ItemPage> </div> </el-col> </el-row> </template> <script setup> // 引入组件 import ItemPage from "../components/itemPage.vue" import ItemOne from "../components/itemOne.vue" import ItemTwo from "../components/itemTwo.vue" import ItemTree from "../components/itemThree.vue" import ItemFour from "../components/itemFour.vue" </script> <style lang="scss"> .el-row { margin-bottom: 20px; } .el-row:last-child { margin-bottom: 0; } .el-col { border-radius: 4px; // 边框圆角° margin: 0 auto; } .grid-content { border-radius: 4px; min-height: 36px; } .top { height: 1rem; // 1rem=80px width: 100%; background-color: rgba(0,0,255,0.1); // 色度 0.2透明度 // 标题的文字样式 h1{ font-size: 0.375rem; color: #fff; text-align: center; // 居中方式 line-height: 1rem; // 1rem=80px } } // 大容器的样式 /*.container { // 最大最小的宽度 !*min-width: 1200px; max-width: 2048px;*! !*margin: 0 auto; // 上容器边距 padding: .125rem 0.125rem 0; // 上下右边距*! !*height: 500px; background-color: gray;*! }*/ .itemCenter{ border: 1px solid blue; border-radius: 4px; } </style>
.itemCenter{
// 高度840px
height: 10.5rem;
border: 1px solid blue;
// 内边距10px
padding: 0.125rem;
// 外边距20px
margin: 0.25rem;
}
七.图表前期准备
全局设置Echarts与axios
Charts 全局引用
npm install --save echarts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// 引用
import 'lib-flexible/flexible.js'
// 引用echarts
import * as echarts from "echarts"
Vue.prototype.$echarts=echarts;
createApp(App).use(store).use(router).mount('#app')
<script> // 1.引用proivde import {provide} from "vue" // 2.引用echarts import * as echarts from "echarts" export default { setup() { provide("echarts",echarts)//第一个参数是名字 第二个参数是你传递的内容 }, } </script>
// 引用inject import {inject} from 'vue' export default { components:{ ItemPage,itemOne,itemTwo,itemThree,itemFour }, setup(){ // 测试使用echarts let $echarts= inject("echarts") console.log($echarts) } }
axios全局引用
<script> // 1.引用proivde import {provide} from "vue" // 2.引用echarts import * as echarts from "echarts" // 引用axios import axios from 'axios' export default { setup() { provide("echarts",echarts)//第一个参数是名字 第二个参数是你传递的内容 provide("axios",axios)//第一个参数是名字 第二个参数是你传递的内容 }, } </script>
// 引用inject import {inject} from 'vue' export default { components:{ ItemPage,itemOne,itemTwo,itemThree,itemFour }, setup(){ // 测试使用echarts let $echarts= inject("echarts") let $http= inject("axios") console.log($echarts) console.log($http) } }
Vue3.2中homePage.vue 完整代码:
<template> <!--上部:标题--> <el-row class="top"> <el-col :span="24" > <div class="grid-content ep-bg-purple-dark" > <h1>豫教云网卫士--大数据座舱</h1> </div> </el-col> </el-row> <!--下部:左中右,justify 属性来定义子元素的排版方式,其取值为start、center、end、space-between、space-around或space-evenly。--> <el-row class="row-bg" justify="space-evenly"> <el-col :span="6" class="itemLeft"> <div class="grid-content ep-bg-purple" > <ItemPage> <ItemOne> </ItemOne> </ItemPage> <ItemPage> <ItemTwo> </ItemTwo> </ItemPage> </div> </el-col> <el-col :span="12" class="itemCenter"> <!-- 为 ECharts 准备一个定义了宽高的 DOM --> <!--vue3.2中 id=‘’ 变更 ref=--> <div class="grid-content ep-bg-purple-light" ref="chart" style="width:100%;height:700px;"> <h2>地图展示</h2> </div> </el-col> <el-col :span="6"> <div class="grid-content ep-bg-purple" > <ItemPage> <ItemTree> </ItemTree> </ItemPage> <ItemPage> <ItemFour> </ItemFour> </ItemPage> </div> </el-col> </el-row> </template> <script setup > import {ref,reactive,onMounted} from 'vue' // 引入组件 import ItemPage from "../components/itemPage.vue" import ItemOne from "../components/itemOne.vue" import ItemTwo from "../components/itemTwo.vue" import ItemTree from "../components/itemThree.vue" import ItemFour from "../components/itemFour.vue" // 引入echarts核心模块 import * as echarts from 'echarts' // 还需引入地图文件 import chinaMap from '../assets/china1.json' // 引入动态数据axios,二次封装 import axios from "../../http/request"; const chart =ref(); // 创建DOM引用 // 第二种方法:初始化方法 const option = reactive({// 指定图表的配置项和数据 series: [{ // 地图不需XY轴 type: 'map', // 图表类型:散点图scatter:用到坐标系设置 map: 'china', // 地图类型 roam: true, // 地图可拖拽、平移 // data: mapData, // 使用动态Api接口文档数据 /*[ // 展示数据项的名字,经纬度,数据量 {name:'河南省',value:[32300,4000]}, {name: '山东省',value: 21203}, {name: '四川省',value: 41203}, {name: '青海省',value: 31203}, ],*/ data: [// 展示数据项的名字,经纬度,数据量 {name: '河南省', value: [32300, 4000],}, {name: '山东省', value: 21203}, {name: '四川省', value: 41203}, {name: '青海省', value: 31203}, ], label: { // 标签:地图中的标签、文字 show: true, // 开启地图中的标签、文字等,(必须开启) color: '#fff', fontSize: 11, }, itemStyle: { // 修改地图区域标签样式 areaColor: '#219edb', // 区域颜色 borderColor: '#fff', // 区域边框价格 }, emphasis: { // 地图高亮状态的多边形和标签样式 label: { color: '#000', fontSize: 12, }, itemStyle: { areaColor: '#f60', borderColor: '#329edb' }, }, }], coordinateSystem: "geo", // 当前坐标系设置:经纬度定位 symbolSize: 30, // 大小 }) // 使用生命钩子 onMounted(() => { // 基于准备好的dom,初始化echarts实例 // var myChart = echarts.init(document.getElementById('main')); // Vue3中: 需要引入 var myChart = echarts.init(chart.value) // 注册可用的地图 echarts.registerMap('china',chinaMap); // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); // 单图表响应式: 跟随浏览器大小改变 window.addEventListener('resize',()=>{ myChart.resize() }) }) </script> <style lang="scss"> .el-row { margin-bottom: 20px; } .el-row:last-child { margin-bottom: 0; } .el-col { border-radius: 4px; // 边框圆角° margin: 0 auto; } .grid-content { border-radius: 4px; min-height: 36px; } .top { height: 1rem; // 1rem=80px width: 100%; background-color: rgba(0,0,255,0.1); // 色度 0.2透明度 // 标题的文字样式 h1{ font-size: 0.375rem; color: #fff; text-align: center; // 居中方式 line-height: 1rem; // 1rem=80px } } // 大容器的样式 /*.container { // 最大最小的宽度 !*min-width: 1200px; max-width: 2048px;*! !*margin: 0 auto; // 上容器边距 padding: .125rem 0.125rem 0; // 上下右边距*! !*height: 500px; background-color: gray;*! }*/ /*.itemCenter{ border: 1px solid blue; border-radius: 4px; }*/ </style>
八.后台接口创建express介绍
node.js平台Web开发框架安装:Express - 基于 Node.js 平台的 web 应用开发框架 - Express 中文文档 | Express 中文网 (expressjs.com.cn)
npm install express --save
九.后台路由创建
// 路由:4个图表需要获取后台数据 // 定义引入express let express = require("express") // 定义路由 let router = express.Router() // 设置当前路由:get('路由名',回调函数(请求request,响应response) router.get("/data",(req,res)=>{ // 响应内容 res.send({mag:"One的地址"}) }) // 暴露路由接口 module .exports=router // vue3.0 // export default router // vue3.2
var express=require("express"); var app=express(); // 引用路由文件 var chartOne=require("./router/one.js"); var chartTwo=require("./router/two.js"); var chartThree=require("./router/three.js"); var chartFour=require("./router/four.js"); // 中间件中使用路由 app.use("/one",chartOne) app.use("/two",chartTwo) app.use("/three",chartThree) app.use("/four",chartFour) // 请求是localhost:3000/user/路由文件中的地址 app.listen(3000)
// 合并4个图表路由 // import {Express, Request, Response, Router} from "express"; // {类型} //引用express let express=require("express") // vue3.0 // import express,{Express} from "express"; // vue3.2 // axios import axios from "axios"; // 接口函数: 前端交互 let app = express(); // 引用路由文件 let chartOne = require("./router/one"); let chartTwo = require("./router/two"); let chartTree = require("./router/three"); let chartFour = require("./router/four"); // 使用中间件来配置路由 app.use('/one',chartOne) app.use('/two',chartTwo) app.use('/three',chartTree) app.use('/four',chartFour) /*// 解决vite-demo中跨域问题 app.use('*',(req,res,next) =>{// 允许跨域 res.header('Access-Control-Allow-Origin','*'); // '*‘可以指定IP next(); })*/ /*// 路由去分模块,避免所有路由都写在入口文件中 const router:Router = express.Router() // 中间件注册,路由注册 app.use('/api',router) // 路由请求:req接收前端,resp响应返给前端 router.get('/list', async (req:Request,res:Response)=>{ const result = await axios.post('https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=statisGradeCityDetail,diseaseh5Shelf') res.json({ // 响应返给前端 ...result.data.data }) })*/ // 开启服务: 端口3333,接收回调 app.listen(3333,()=>{ console.log('success server http://localhost:3333') })
十.api接口数据创建
var express=require("express"); var router=express.Router() // 引用数据 let data=require("../mock/one.json") router.get("/data",function(req,res){ // 数据返回给前台 res.send({msg:"第1个接口",data}) }) module.exports=router
router/ One.js\two.js\three.js\four.js
// 路由:4个图表需要获取后台数据 // 定义引入express let express = require("express") // 定义路由 let router = express.Router() // 引用json let oneData = require('../Mock/one.json') // 设置当前路由:get('路由名',回调函数(请求request,响应response) router.get("/data",(req,res)=>{ // 响应内容:返回oneData.json数据 res.send({mag:"One的地址",chartOne:oneData}) }) // 暴露路由接口 module .exports=router // vue3.0 // export default router // vue3.2
10-1.解决跨域
var express=require("express"); var app=express(); app.use(function(req,res,next){ res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Content-Type,Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild'); res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE,OPTIONS'); // 千万不要网%%¥¥¥### // 千万不要网 // 千万不要网 next(); })
Vue3.2中完整代码写法
node/index.ts
// 合并4个图表路由 // import {Express, Request, Response, Router} from "express"; // {类型} //引用express let express=require("express") // vue3.0 // import express,{Express} from "express"; // vue3.2 // axios import axios from "axios"; // 接口函数: 前端交互 let app = express(); // 引用路由文件 let chartOne = require("./router/one"); let chartTwo = require("./router/two"); let chartThree = require("./router/three"); let chartFour = require("./router/four"); // 使用中间件来配置路由 app.use('/one',chartOne) app.use('/two',chartTwo) app.use('/three',chartThree) app.use('/four',chartFour) // 解决vite-demo中跨域问题 app.use('*',(req:any,res:any,next:any) =>{// 允许跨域 res.header('Access-Control-Allow-Origin','*'); // '*‘可以指定IP res.header('Access-Control-Allow-Headers', 'Content-Type,Content-Length,Authorization, Accept, X-Requested-With , yourHeaderFeild'); res.header('Access-Control-Allow-Methods', 'PUT, POST, GET,DELETE,OPTIONS'); next(); }) /*// 路由去分模块,避免所有路由都写在入口文件中 const router:Router = express.Router() // 中间件注册,路由注册 app.use('/api',router) // 路由请求:req接收前端,resp响应返给前端 router.get('/list', async (req:Request,res:Response)=>{ const result = await axios.post('https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=statisGradeCityDetail,diseaseh5Shelf') res.json({ // 响应返给前端 ...result.data.data }) })*/ // 开启服务: 端口3333,接收回调 app.listen(3333,()=>{ console.log('success server http://localhost:3333') })
11.图表1基本设置销售总量
<template> <div ref="chart"> <h2>图表1</h2> <div > 图表的容器 </div> </div> </template> <script setup> // 引用echarts核心模块 import * as echarts from 'echarts' import {onMounted, ref} from "vue"; import axios from "axios"; const chart =ref(); // 创建DOM引用 // 函数:异步 async function getState(){ // 对应node服务器中端口:get请求 // 需要后端解决跨域问题:node/index.ts中可以理解为:/api等于https://127.0.0.1:3333 const oneData = await axios({url:"/api/one/data"}) console.log(oneData) } onMounted(()=>{ // 调用函数请求 getState(); // 基于准备好的dom,初始化echarts实例 // var myChart = echarts.init(document.getElementById('main')); // Vue3中: 需要引入 var myChart = echarts.init(chart.value) // 使用刚指定的配置项和数据显示图表。 // 第三种写法: 钩子内 myChart.setOption({ xAxis: { type: "value", }, yAxis: { type: "category" }, series: [ { type:"bar", } ] }); // 单图表响应式: 跟随浏览器大小改变 window.addEventListener("resize",()=>{ myChart.resize() }) }) </script> <style scoped> </style>
解决跨域问题点
vite.config.ts中

express服务器端node/index.ts中
// 解决vite-demo中跨域问题 app.use('*', function(req:any, res:any, next:any) { res.header("Access-Control-Allow-Origin", "*"); /*res.header("Access-Control-Allow-Headers", "X-Requested-With"); res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"); res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild'); res.header("X-Powered-By",' 3.2.1') res.header("Content-Type", "application/json;charset=utf-8");*/ next(); });
express node/index.ts解决跨域
下面是vite的代理
server: {
proxy: {
'/api': {
target: 'https://baidu.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
配置后/api就是代理了target配置的地址( http://127.0.0.1:3333)后端服务器IP和端口
可以理解为: /api 等于https://127.0.0.1:3333
所以不需要配置axios的baseUrl了,切记。
2.验证接口
axios.get("/api/one/data").then(res => {
console.log("one====>",res);
});
// const mapData = await fetch(`/api/post/1`).then(r => r.json())
// 根据接口文档:实际参数获取数据
const mapData = await axios.get('/api/one/data').then(res => res.data.chartData)
此时,get请求路径不在是https://localhost:5173而是/api/one/data
到此就可以跨域了。
验证:




11.图表1基本设置销售总量
<template> <div > <div ref="chart" class="oneChart"> 图表的容器 </div> </div> </template> <script setup> // 引用echarts核心模块 import * as echarts from 'echarts' import {onMounted, reactive, ref} from "vue"; import axios from "axios"; // var chartDom = document.getElementsById('main') // vue3创建Dom const chart =ref(); // Vue3.2创建DOM引用 let oneData = reactive({}); let xData = reactive([]); let yData = reactive([]); // 2.处理异步请求过来的数据 function setData(){// 将oneData请求来的数据处理:数组对象 // 将数组map()获取title赋值给xData xData = oneData.data.chartOne.chartData.map(v => v.title); yData = oneData.data.chartOne.chartData.map(v => v.num); console.log("xData",xData) console.log('yData',yData) } // 1.函数:异步请求 async function getState(){ // 对应node服务器中端口:get请求 // 需要后端解决跨域问题:node/index.ts中可以理解为:/api等于https://127.0.0.1:3333 oneData = await axios({url:"/api/one/data"}) // console.log(oneData.data.chartOne.chartData) } onMounted(()=>{ // 基于准备好的dom,初始化echarts实例 // var myChart = echarts.init(document.getElementById('main')); // Vue3中: 需要引入 var myChart = echarts.init(chart.value) // 调用函数请求 // getState(); //3.使用then(()=>{})回调函数进行数据处理 getState().then(()=>{ setData() // 使用刚指定的配置项和数据显示图表。 // 第三种写法: 钩子内 myChart.setOption({ title: { // 标题 text: '地区销售', textStyle: { color: '#fff', fontSize: 18, },
top: 20px, // 上边距 left: 'center', // 标题居中 }, tooltip:{ trigger: 'axis', axisPointer: { type:'shadow' } }, legend: {// 图例 data: ['销量'], top: '5%', left: 'right', textStyle: { // 文字样式 color: '#f68', } }, // 调整图标:位置 grid: { // 上下左右 // top: '3%', left: '3%', // right: '6%', bottom:'15%', containLabel: true, // 包含坐标轴文字 }, xAxis: { type: "value", // boundaryGap: [0,0.01], axisLine:{// x轴线的颜色以及宽度 lineStyle: { color: '#fff', /*width: 0, type: 'solid',*/ } }, axisLabel: { // x轴文字的配置 show:true, textStyle: { color: '#fff', }, /*splitLine: { // 分割线配置 show:false, lineStyle: { color: '#fff', }, }*/ } }, yAxis: { type: "category", data: xData, inverse: true, // Y 轴从下往上是从小到大的排列 axisLine:{// x轴线的颜色以及宽度 lineStyle: { color: '#fff' } } }, series: [ { name: '地区', type:"bar", data: yData, realtimeSort: true, // 动态排序 itemStyle: { // 样式 normal: { // 数据圆角:[左上,右上,右下,左下] BorderRadius: [0,20,20,0], // 修改线性渐变色方式 :(0,0,0,0,[{数组对象:每个阶段相关颜色}]) color: new echarts.graphic.LinearGradient(0,0,1,0,[ { // 0 起始颜色 offset: 0, color: '#005eaa', }, { // 0.5 中间颜色 offset: 0.5, color: '#339ca8', }, { // 1 结束颜色 offset: 1, color: '#cda819' } ]) } } } ] }); }) // 单图表响应式: 跟随浏览器大小改变 window.addEventListener("resize",()=>{ myChart.resize() }) }) </script> <style scoped> .oneChart{ height: 360px; } </style>
问题:出现图表无法自适应
itemPage.vue中

14.图表2 地图展示
地图数据来自阿里dataV可视化平台:DataV.GeoAtlas地理小工具系列 (aliyun.com)
<template> <!--上部:标题--> <el-row class="top"> <el-col :span="24" > <div class="grid-content ep-bg-purple-dark" > <h1>豫教云网卫士--大数据座舱</h1> </div> </el-col> </el-row> <!--下部:左中右,justify 属性来定义子元素的排版方式,其取值为start、center、end、space-between、space-around或space-evenly。--> <el-row class="row-bg" justify="space-evenly"> <el-col :span="6" class="itemLeft"> <div class="grid-content ep-bg-purple" > <ItemPage> <ItemOne> </ItemOne> </ItemPage> <ItemPage> <ItemTwo> </ItemTwo> </ItemPage> </div> </el-col> <el-col :span="12" class="itemCenter"> <!-- 为 ECharts 准备一个定义了宽高的 DOM --> <!--vue3.2中 id=‘’ 变更 ref=--> <div class="grid-content ep-bg-purple-light" ref="chart" style="width:100%;height:100%;"> <!--<h2>地图展示</h2>--> <MapPage/> </div> </el-col> <el-col :span="6"> <div class="grid-content ep-bg-purple" > <ItemPage> <ItemTree> </ItemTree> </ItemPage> <ItemPage> <ItemFour> </ItemFour> </ItemPage> </div> </el-col> </el-row> </template> <script setup > // 引入组件 import ItemPage from "../components/itemPage.vue" import ItemOne from "../components/itemOne.vue" import ItemTwo from "../components/itemTwo.vue" import ItemTree from "../components/itemThree.vue" import ItemFour from "../components/itemFour.vue" import MapPage from "../components/mapPage.vue" </script> <style lang="scss"> .el-row { margin-bottom: 20px; } .el-row:last-child { margin-bottom: 0; } .el-col { border-radius: 4px; // 边框圆角° margin: 0 auto; } .grid-content { border-radius: 4px; min-height: 36px; } .top { height: 1rem; // 1rem=80px width: 100%; background-color: rgba(0,0,255,0.1); // 色度 0.2透明度 // 标题的文字样式 h1{ font-size: 28px; color: #fff; text-align: center; // 居中方式 line-height: 80px; // 1rem=80px } } // 大容器的样式 /*.container { // 最大最小的宽度 !*min-width: 1200px; max-width: 2048px;*! !*margin: 0 auto; // 上容器边距 padding: .125rem 0.125rem 0; // 上下右边距*! !*height: 500px; background-color: gray;*! }*/ /*.itemCenter{ border: 1px solid blue; border-radius: 4px; }*/ </style>
mapPage.vue完整代码
<template> <!-- 为 ECharts 准备一个定义了宽高的 DOM --> <!--vue3.2中 id=‘’ 变更 ref=--> <div class="grid-content ep-bg-purple-light" ref="chart" style="width:100%;height:100%;"> </div> </template> <script setup> import {ref,reactive,onMounted} from 'vue' // 引入echarts核心模块 import * as echarts from 'echarts' // 还需引入本地地图文件 import chinaMap from '../assets/china1.json' // 引入动态数据axios,二次封装 // import axios from 'axios' const chart =ref(); // 创建DOM引用 // 第二种方法:初始化方法 const option = reactive({// 指定图表的配置项和数据 tooltip: { // 提示框组件 trigger: "item", }, title: { text: '城市销量', left: 'center', // 距离位置 textStyle: { // 文字设置 color: "#fff", fontSize:20, textShadowBlur: 20, // 阴影 textShadowColor:"#33ffff", //阴影颜色 } }, geo: { // 地理坐标系 tooltip: { show: true }, map: 'china', // 地图类型 itemStyle: { // 修改地图区域标签样式 areaColor: '#219edb', // 区域颜色 borderColor: '#00ffff', // 区域边框颜色 shadowColor: 'rgba(230,130,70,0.5)', // 阴影颜色 shadowBlur: 30, // 阴影模糊度 }, label: { // 标签:地图中的标签、文字 show: true, // 开启地图中的标签、文字等,(必须开启) color: '#fff', fontSize: 11, }, emphasis: { // 地图高亮状态的多边形和标签样式 // focus:'self', // 当前高亮,其他淡出 label: { color: '#000', fontSize: 12, }, itemStyle: { areaColor: '#f60', borderColor: '#329edb' }, }, roam: true, // 地图可拖拽、平移 }, visualMap: { // 视觉映射效果:热度点、热度柱 type: 'continuous', // 必要设置:连续类型 min: 100, // 必要设置:最小 max: 10000, // 必要设置:最大 text: ['High', 'Low'], realtime: false, calculable: true, // 滑动效果 inRange: { // 热度过渡:颜色设置 color: ['lightskyblue', 'yellow', 'orangered'] }, textStyle: { color: '#fff' }, }, series: [{ // 系列:地图不需XY轴 type: 'effectScatter', // 图表类型:散点图scatter:用到坐标系设置 coordinateSystem: 'geo', geoIndex: 0, symbolSize:function (params){ // 气泡点特效 return (params[2] / 1000) * 1 + 5; // 1000越大越小,+5越大越大 }, itemStyle: { color:"#b02a02", }, encode: { tooltip: 2, }, data: [ // 展示数据项的名字,经纬度,数据量 {name: '北京', value: [116.46,39.92,4367]}, {name: '上海', value: [121.48,31.22,8675]}, {name: '深圳', value: [114.07,22.62,2461]}, {name: '广州', value: [113.23,23.16,187]}, {name: '西安', value: [108.45,34,375]}, ], /*[ // 展示数据项的名字,经纬度,数据量 {name:'河南省',value:[32300,4000]}, {name: '山东省',value: 21203}, {name: '四川省',value: 41203}, {name: '青海省',value: 31203}, ],*/ }, ] /*coordinateSystem: "geo", // 当前坐标系设置:经纬度定位 symbolSize: 30, // 大小*/ }) // 使用生命钩子 onMounted(() => { // 基于准备好的dom,初始化echarts实例 // var myChart = echarts.init(document.getElementById('main')); // Vue3中: 需要引入 var myChart = echarts.init(chart.value) // 注册可用的地图 echarts.registerMap('china',chinaMap); // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); // 单图表响应式: 跟随浏览器大小改变 window.addEventListener('resize',()=>{ myChart.resize() }) }) </script> <style scoped> </style>
15.图表3 产品统计分析图



完整代码:
<template> <div> <!--<h2>图表3</h2>--> <div ref="chart" style="height: 340px;"> </div> </div> </template> <script setup> import {onMounted, reactive, ref} from "vue" import * as echarts from 'echarts' import axios from "axios"; let chart = ref();// 创建Mod引用 let threeData = reactive({}) // 优化Vue3.2 // 使用顶级await:父组件必须使用<suspense>包裹组件 async function getState(){ threeData = await axios.get("/api/three/data") } onMounted(()=>{ // 调用函数请求 // getState(); //3.使用then(()=>{})回调函数进行数据处理 getState().then(()=>{ console.log("饼状图",threeData) // 基于加载完后的DOM,初始化echarts实例 // var myChart = echarts.init(document.getElementById('main')); // Vue3中: 需要引入 var myChart = echarts.init(chart.value) // 使用刚指定的配置项和数据显示图表。 myChart.setOption({ title: { // 标题 text: '统计分析', textStyle: { color: '#fff', fontSize: 18, }, top: '20px', left: 'center', // 标题居中 }, legend: { // 设置图例 top: 'bottom', // 放到最下面 width: '60%', // 自适应 height: 'auto', textStyle: { color: "#fff" } }, tooltip:{ show:true, //显示 }, // 调整图标:位置 grid: { // 上下左右 // top: '3%', // left: '3%', // right: '6%', bottom:'15%', containLabel: true, // 包含坐标轴文字 }, series: [ { type: 'pie', // 饼图 data: threeData.data.chartThree.chartData, radius: [10,90], // 饼图的半径数组的第一项是内半径,第二项是外半径 center: 'center', // 饼图的中心(圆心)坐标,数组的第一项是横坐标,第二项是纵坐标。 roseType: "area", // 玫瑰类型 itemStyle: { borderRadius: 10 // 圆角:用于指定饼图扇形区域块的内外圆角半径 }, }, ], }); // 单图表响应式: 跟随浏览器大小改变 window.addEventListener("resize",()=>{ myChart.resize() }) }) }) </script> <style scoped> </style>
16.图表4 产品月销图
<template>
<div>
<!--<h2>图表2</h2>-->
<div ref="chart" style="height: 340px">
</div>
</div>
</template>
<script setup>
import {onMounted, reactive, ref} from 'vue'
import axios from "axios";
import * as echarts from "echarts";
let chart = ref(); // 创建Mod容器
let twoData = reactive({})
async function getState(){
twoData = await axios.get("/api/two/data")
}
onMounted(()=>{
getState().then(()=>{
console.log("查看折线图数据",twoData.data.chartTwo.chartData)
// 基于加载完后的DOM,初始化echarts实例
// var myChart = echarts.init(document.getElementById('main'));
// Vue3中: 需要引入
var myChart = echarts.init(chart.value)
// 使用刚指定的配置项和数据显示图表。
myChart.setOption({
title: { // 标题
text: '地区销售',
textStyle: {
color: '#fff',
fontSize: 18,
},
top: '20px',
left: 'center', // 标题居中
},
tooltip:{ // 提示框组件
trigger: 'axis', // 触发类型:坐标轴类型触发
axisPointer: { // 坐标轴指示器配置项
type:'cross',// 指示器类型:十字准星式,如类型:shadow
label: { // 坐标轴指示器的文本标签样式:提示文本
backgroundColor: "#e6b600", // 文本标签的背景颜色就是XY轴上的内容
}
},
},
legend:{// 图例组件:展现了不同系列的标记(symbol),颜色和名字。可以通过点击图例控制哪些系列不显示。
data: ["郑州","新乡","安阳","商丘","洛阳"],
top: "15%", // 距离容器上侧的距离
textStyle:{ // 文字样式
color: "#fff"
},
},
/*toolbox: { // 下载
feature: {
saveAsImage: {
},
},
},*/
grid: {// 组件离容器的距离
top: "30%",
left: "1%",
right:"6%",
bottom:"5%",
containLabel: true, // grid区域是否包含坐标轴的刻度标签
},
xAxis: {
axisLine: {
lineStyle: {
color: "#fff",
}
},
type: "category", // 类目轴:横向和竖向
boundaryGap:false, // 间隙
data: twoData.data.chartTwo.chartData.day, // 获取日期
},
yAxis: {
type: "value", // 数值轴
axisLine: {
lineStyle: {
color: "#fff",
}
},
},
series: [
{
name:"郑州",
type: "line", // 线性
data: twoData.data.chartTwo.chartData.num.Chemicals,
smooth: true, // 折线图平滑效果,变成曲线图
showSymbol:false, // 隐藏所有数据点
stack: "Total",//数据堆叠
lineStyle: { // 设置线段样式
width: 0,
},
emphasis: { // 设置高亮的图形样式和标签样式
focus: "series",// 只显示选中的内容高亮
},
areaStyle: { // 设置填充区域的样式
opacity: 0.8, // 透明度
color: new echarts.graphic.LinearGradient(0,0,0,1,[
{// 设置渐变:起始
offset: 0,
color: "rgb(128,255,165)",
},
/*{// 设置渐变:中间
offset: 0.5,
color: "rgb(1,191,236)",
},*/
{// 设置渐变:结束
offset: 1,
color: "rgb(1,191,236)",
},
]),
},
},
{
name:"新乡",
type: "line", // 线性
data: twoData.data.chartTwo.chartData.num.Clothes,
smooth: true, // 折线图平滑效果,变成曲线图
showSymbol:false, // 隐藏所有数据点
stack: "Total",//数据堆叠
lineStyle: { // 设置线段样式
width: 0,
},
emphasis: { // 设置高亮的图形样式和标签样式
focus: "series",// 只显示选中的内容高亮
},
areaStyle: { // 设置填充区域的样式
opacity: 0.8, // 透明度
color: new echarts.graphic.LinearGradient(0,0,0,1,[
{// 设置渐变:起始
offset: 0,
color: "rgb(0,221,255)",
},
/*{// 设置渐变:中间
offset: 0.5,
color: "rgb(77,119,255)",
},*/
{// 设置渐变:结束
offset: 1,
color: "rgb(77,119,255)",
},
]),
},
},
{
name:"安阳",
type: "line", // 线性
data: twoData.data.chartTwo.chartData.num.Electrical,
smooth: true, // 折线图平滑效果,变成曲线图
showSymbol:false, // 隐藏所有数据点
stack: "Total",//数据堆叠
lineStyle: { // 设置线段样式
width: 0,
},
emphasis: { // 设置高亮的图形样式和标签样式
focus: "series",// 只显示选中的内容高亮
},
areaStyle: { // 设置填充区域的样式
opacity: 0.8, // 透明度
color: new echarts.graphic.LinearGradient(0,0,0,1,[
{// 设置渐变:起始
offset: 0,
color: "rgb(55,162,255)",
},
/*{// 设置渐变:中间
offset: 0.5,
color: "rgb(1,191,236)",
},*/
{// 设置渐变:结束
offset: 1,
color: "rgb(116,21,219)",
},
]),
},
},
{
name:"商丘",
type: "line", // 线性
data: twoData.data.chartTwo.chartData.num.digit,
smooth: true, // 折线图平滑效果,变成曲线图
showSymbol:false, // 隐藏所有数据点
stack: "Total",//数据堆叠
lineStyle: { // 设置线段样式
width: 0,
},
emphasis: { // 设置高亮的图形样式和标签样式
focus: "series",// 只显示选中的内容高亮
},
areaStyle: { // 设置填充区域的样式
opacity: 0.8, // 透明度
color: new echarts.graphic.LinearGradient(0,0,0,1,[
{// 设置渐变:起始
offset: 0,
color: "rgb(255,0,135)",
},
/*{// 设置渐变:中间
offset: 0.5,
color: "rgb(1,191,236)",
},*/
{// 设置渐变:结束
offset: 1,
color: "rgb(135,0,157)",
},
]),
},
},
{
name:"洛阳",
type: "line", // 线性
data: twoData.data.chartTwo.chartData.num.gear,
smooth: true, // 折线图平滑效果,变成曲线图
showSymbol:false, // 隐藏所有数据点
stack: "Total",//数据堆叠
lineStyle: { // 设置线段样式
width: 0,
},
emphasis: { // 设置高亮的图形样式和标签样式
focus: "series",// 只显示选中的内容高亮
},
areaStyle: { // 设置填充区域的样式
opacity: 0.8, // 透明度
color: new echarts.graphic.LinearGradient(0,0,0,1,[
{// 设置渐变:起始
offset: 0,
color: "rgb(255,191,0)",
},
{// 设置渐变:中间
offset: 0.5,
color: "rgb(224,62,76)",
},
{// 设置渐变:结束
offset: 1,
color: "rgb(1,191,236)",
},
]),
},
},
],
});
// 单图表响应式: 跟随浏览器大小改变
window.addEventListener("resize",()=>{
myChart.resize()
})
})
})
</script>
<style scoped>
</style>
17.图表5统计图
components中的itemFour.vue完整代码
<template>
<div>
<!--<h2>图表4</h2>-->
<div ref="chart" style="height: 340px">
图表的容器
</div>
</div>
</template>
<script setup>
import {onMounted, reactive, ref} from "vue"
import * as echarts from "echarts"
import axios from "axios";
let chart = ref();// 创建MOD
let fourData = reactive({}); // let作用域内,const定义常量
async function getState(){
fourData = await axios.get("/api/four/data")
}
onMounted(()=>{
// 调用函数请求
// getState();
//3.使用then(()=>{})回调函数进行数据处理
getState().then(()=>{
console.log("查看柱状图数据",fourData.data.chartFour.chartData)
// 基于准备好的dom,初始化echarts实例
// var myChart = echarts.init(document.getElementById('main'));
// Vue3中: 需要引入
var myChart = echarts.init(chart.value)
// 使用刚指定的配置项和数据显示图表。
// 第三种写法: 钩子内
myChart.setOption({
title: { // 标题
text: '周回款统计',
textStyle: {
color: '#fff',
fontSize: 18,
},
top: '20px',
left: 'center', // 标题居中
},
tooltip: { // 提示框组件
trigger: "axis", // 触发类型
axisPinter:{ // 坐标轴指示器配置项
type: "shadow",
}
},
legend: {
top: "15%", // 距离容器上侧的距离
textStyle:{ // 文字样式
color: "#fff"
},
},
grid: {// 组件离容器的距离
top: "30%",
left: "1%",
right:"6%",
bottom:"5%",
containLabel: true, // grid区域是否包含坐标轴的刻度标签
},
xAxis:{
type:"category", // 类目轴
// boundaryGap:false, // X轴上ABC间隙
data: fourData.data.chartFour.chartData.day,
axisLine:{
lineStyle: {
color: "#fff",
}
},
},
yAxis: {
type: "value", // 数值轴
axisLine:{
lineStyle: {
color: "#fff",
}
},
},
series: [
{
name: "卫滨",
type: "bar",
data: fourData.data.chartFour.chartData.num.WeiBin,
stack: "total",// 数据堆叠
// barWidth: "50%",
label: { // 文本标签
show: true, // 开启:文本显示,总计合计
// position: 'top', // 标签位置
},
emphasis: { // 设置高亮的图形样式和标签样式
focus: "series", // 只显示选中的内容高亮
}
},
{
name: "红旗",
type: "bar",
data: fourData.data.chartFour.chartData.num.HongQi,
stack: "total",// 数据堆叠
label: { // 文本标签
show: true, // 开启:文本显示,总计合计
// position: 'top', // 标签位置
},
emphasis: { // 设置高亮的图形样式和标签样式
focus: "series", // 只显示选中的内容高亮
}
},
{
name: "牧野",
type: "bar",
data: fourData.data.chartFour.chartData.num.MuYe,
stack: "total",// 数据堆叠
label: { // 文本标签
show: true, // 开启:文本显示,总计合计
// position: 'top', // 标签位置
},
emphasis: { // 设置高亮的图形样式和标签样式
focus: "series", // 只显示选中的内容高亮
}
},
{
name: "凤泉",
type: "bar",
data: fourData.data.chartFour.chartData.num.FengQuan,
stack: "total",// 数据堆叠
label: { // 文本标签
show: true, // 开启:文本显示,总计合计
// position: 'top', // 标签位置
},
emphasis: { // 设置高亮的图形样式和标签样式
focus: "series", // 只显示选中的内容高亮
}
},
{
name: "辉县",
type: "bar",
data: fourData.data.chartFour.chartData.num.HuiXian,
stack: "total",// 数据堆叠
label: { // 文本标签
show: true, // 开启:文本显示,总计合计
// position: 'top', // 标签位置
},
emphasis: { // 设置高亮的图形样式和标签样式
focus: "series", // 只显示选中的内容高亮
}
},
],
});
// 单图表响应式: 跟随浏览器大小改变
window.addEventListener("resize",()=>{
myChart.resize()
})
})
})
</script>
<style scoped>
</style>
完成图例

17.项目打包
由于使用Vue/cli脚手架,浏览器解析后缀.vue文件无法识别

npm run build

2.修改静态资源路径 publicPath
静态资源路径出现问题:需新建项目中src/vue.config.js文件
module.exports = { lintOnSave:false, // 关闭检查 // 配置静态资源路径 : process判断当前环境 publicPath: process.env.NODE_ENV = "production" ? "./" : "/" }
node中全局变量process表示当前进程.env表示当前环境信息.NODE_ENV自定义变量 = 三元判断 是生产模式还是开发模式。
重新项目打包: npm run build
发现页面中内容为空问题
1、打开路由文件夹 router/index.ts
修改为hash模式

// 1.需要引入 import { createRouter, createWebHistory, createWebHashHistory } from 'vuerouter' // 2.修改配置 const router = createRouter({ history: createWebHashHistory(process.env.BASE_URL), routes })
再次npm run build打包
地图配置与打包
将地图数据放入后台接口中
在项目后端express中router文件夹下新建:map.js放置地图内容
1.需要要将前端assets中的China1.json.拷贝到后端Mock数据文件夹中

2.编写map.js
// 定义引入express// 定义引入express let express = require("express"); // 定义路由 let router = express.Router(); // 引入data.json let mapData = require("../Mock/china1.json"); // 设置当前路由:get('路由名',回调函数(请求request,响应response) router.get("/data",(req,res)=>{ // 响应内容 res.send({msg:"我是地图的路由地址",chinaData:mapData}) }) module.exports = router; // export default router;
3.引用路由文件map.js,注册路由

修改前端请求:
components/mapPage.vue中

注意:/api/map/data = "http://localhost:3333/map/data, 可以查看Vite.config.ts中设置

页面不显示 地图数据
mapPage.vue完整代码:
<template> <!-- 为 ECharts 准备一个定义了宽高的 DOM --> <!--vue3.2中 id=‘’ 变更 ref=--> <div class="grid-content ep-bg-purple-light" ref="chart" style="width:100%;height:100%;"> </div> </template> <script setup> import {ref,reactive,onMounted} from 'vue' // 引入echarts核心模块 import * as echarts from 'echarts' // 还需引入本地地图文件 // import chinaMap from '../assets/china1.json' // 引入动态数据axios,二次封装 import axios from 'axios' let chart =ref(); // 创建DOM引用 let mapData = reactive({}); async function getState(){ mapData = await axios.get("/api/map/data") } // 使用生命钩子 onMounted(() => { getState().then(()=>{ console.log("map",mapData) // 基于准备好的dom,初始化echarts实例 // var myChart = echarts.init(document.getElementById('main')); // Vue3中: 需要引入 var myChart = echarts.init(chart.value) // 注册可用的地图 echarts.registerMap('china',mapData.data.chinaData); // 使用刚指定的配置项和数据显示图表。 myChart.setOption({ tooltip: { // 提示框组件 trigger: "item", }, title: { text: '国内城市', left: 'center', // 距离位置 textStyle: { // 文字设置 color: "#fff", fontSize:20, textShadowBlur: 20, // 阴影 textShadowColor:"#33ffff", //阴影颜色 } }, geo: { // 地理坐标系 tooltip: { show: true }, map: 'china', // 地图类型 itemStyle: { // 修改地图区域标签样式 areaColor: '#219edb', // 区域颜色 borderColor: '#00ffff', // 区域边框颜色 shadowColor: 'rgba(230,130,70,0.5)', // 阴影颜色 shadowBlur: 30, // 阴影模糊度 }, label: { // 标签:地图中的标签、文字 show: true, // 开启地图中的标签、文字等,(必须开启) color: '#fff', fontSize: 11, }, emphasis: { // 地图高亮状态的多边形和标签样式 focus:'self', // 当前高亮,其他淡出 label: { color: '#000', fontSize: 12, }, itemStyle: { areaColor: '#f60', borderColor: '#329edb', }, }, roam: true, // 地图可拖拽、平移 }, visualMap: { // 视觉映射效果:热度点、热度柱 type: 'continuous', // 必要设置:连续类型 min: 100, // 必要设置:最小 max: 10000, // 必要设置:最大 text: ['High', 'Low'], realtime: false, calculable: true, // 滑动效果 inRange: { // 热度过渡:颜色设置 color: ['lightskyblue', 'yellow', 'orangered'] }, textStyle: { color: '#fff' }, }, series: [{ // 系列:地图不需XY轴 type: 'effectScatter', // 图表类型:散点图scatter:用到坐标系设置 /*coordinateSystem: "geo", // 当前坐标系设置:经纬度定位 symbolSize: 30, // 大小*/ coordinateSystem: 'geo', // 当前坐标系设置:经纬度定位 geoIndex: 0, symbolSize:function (params){ // 气泡点特效 return (params[2] / 1000) * 1 + 5; // 1000越大越小,+5越大越大 }, itemStyle: { color:"#b02a02", }, encode: { tooltip: 2, }, data: [ // 展示数据项的名字,经纬度,数据量,热力量 {name: '北京', value: [116.46,39.92,4367]}, {name: '上海', value: [121.48,31.22,8675]}, {name: '深圳', value: [114.07,22.62,2461]}, {name: '广州', value: [113.23,23.16,187]}, {name: '西安', value: [108.45,34,375]}, ], /*[ // 展示数据项的名字,经纬度,数据量 {name:'河南省',value:[32300,4000]}, {name: '山东省',value: 21203}, {name: '四川省',value: 41203}, {name: '青海省',value: 31203}, ],*/ }, ], }); // 单图表响应式: 跟随浏览器大小改变 window.addEventListener('resize',()=>{ myChart.resize() }) }) }) </script> <style scoped> </style>
检查无误后:npm run build 打包项目
此处提醒:项目是vite还是vue/cli,打包有区别
打包报错问题:
语法检查问题: 要么<scripts steup lang="ts">,要么vite.config.ts中删除下面

再次检查和新建vue.config.js文件
运行测试:
npm run preview
配置vite打包入口

vite的配置都在根目录下面的vite.config.ts里面,在没有对其进行打包配置时,默认的打包的入口就是根目录的【index.html】。这时候我们直接运行 npm run build就会打包相应的文件:

(ps:为什么默认是.html文件那?因为vue是单页面应用也就是最后打包的html只有一个。vite也提供多入口,但我不再本文继续描述了)
但是如果我们的目录结构改变了 ,比如:

在此时打包就会报错:

原因就是默认的打包入口 根目录的index.html删除了。这时候就需要对vite.config.ts进行配置了:

build.rollupOptions.input即为打包的指定入口。
关于项目vite打包之后直接进入dist文件夹访问index.html时出现空白的问题,网上查找了很多也没有查找到相关资料解决,但是如果你用FTP上传到服务器上是可以正常访问的,所以也就没有管了。如果是用vue-cli创建的vue3项目,打包之后是可以正常访问的。
10月重点更新了rollupOptions分包配置,混淆器设置为minify: "terser"。但运行build时,打包速度很慢,要打包十几分钟才能打包好,不知道有设置过分包的朋友遇到过没
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
// 8月更新-自动导入ElementPlus组件,除了图标需要单独引用外,其他的都可以直接在页面上使用组件,会自动导入
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
const isProduction = process.env.NODE_ENV === "production"
export default defineConfig({
base: "./", // 类似publicPath,'./'避免打包访问后空白页面,要加上,不然线上也访问不了
// 8月更新
productionSourceMap: !isProduction, //关闭生产环境下的SourceMap映射文件
// 8月更新-自动导入ElementPlus
// 需安装 npm install -D unplugin-vue-components unplugin-auto-import
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
resolve: {
alias: {
// 如果报错__dirname找不到,需要安装node,执行npm install @types/node --save-dev
"@": path.resolve(__dirname, "src"),
"@assets": path.resolve(__dirname, "src/assets"),
"@components": path.resolve(__dirname, "src/components"),
"@images": path.resolve(__dirname, "src/assets/images"),
"@views": path.resolve(__dirname, "src/views"),
"@store": path.resolve(__dirname, "src/store"),
},
},
// 8月更新,全局引入less
css: {
sourceMap: !isProduction, // css sourceMap 配置
preprocessorOptions: {
less: {
modifyVars: {
hack: `true; @import (reference) "${path.resolve("src/assets/css/base.less")}";`,
},
javascriptEnabled: true,
},
},
},
build: {
outDir: "dist",
// 9月更新
assetsDir: "assets", //指定静态资源存放路径
sourcemap: false, //是否构建source map 文件
// 10月更新
minify: "terser", // 混淆器,terser 构建后文件体积更小,'terser' | 'esbuild'
chunkSizeWarningLimit: 1500, //chunk 大小警告的限制,默认500KB
rollupOptions: {
output: {
// 最小化拆分包
manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
},
chunkFileNames: 'js/[name].[hash].js', // 用于命名代码拆分时创建的共享块的输出命名,[name]表示文件名,[hash]表示该文件内容hash值
}
},
terserOptions: {
// 生产环境移除console
compress: {
drop_console: true,
drop_debugger: true,
},
// 10月更新
output: {
comments: true, // 去掉注释内容
},
},
},
server: {
https: false, // 是否开启 https
open: false, // 是否自动在浏览器打开
cors: true, // 允许跨域 8月更新
port: 3000, // 端口号
host: "0.0.0.0",
proxy: {
"/api": {
target: "", // 后台接口
changeOrigin: true,
secure: false, // 如果是https接口,需要配置这个参数
// ws: true, //websocket支持
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
// 引入第三方的配置
optimizeDeps: {
include: [],
},
});
项目中Vite.config完整代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 8月更新-自动导入ElementPlus组件,除了图标需要单独引用外,其他的都可以直接在页面上使用组件,会自动导入
// import AutoImport from 'unplugin-auto-import/vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import path from 'path'
const isProduction = process.env.NODE_ENV === "production"
// https://vitejs.dev/config/
export default defineConfig({
// 类似publicPath,'./'避免打包访问后空白页面,要加上,不然线上也访问不了
base:'./',// 配置公共路径:默认base: '/',绝对路径,
// @ts-ignore
productionSourceMap: !isProduction, //关闭生产环境下的SourceMap映射文件
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
// 跨域
server: { // 增:服务器设置
https: false, // 是否开启 https
open: false, // 是否自动在浏览器打开
cors: true, // 允许跨域 8月更新
// port: 3000, // 端口号
host: "0.0.0.0",
proxy: { // 自定义代理规则
'/api': {//代理标识,一般是每个接口前的相同部分
// 可以理解为:/api等于https://127.0.0.1:3333
target: 'http://localhost:3333',// 这里写的是访问后端IP接口的域名和端口号
// secure: true,
changeOrigin: true,// 允许跨域请求
secure: false, // 如果是https接口,需要配置这个参数
// 重写路径,替换请求地址中的指定路径
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
// 引入第三方的配置
/*optimizeDeps: {
include: [],
},*/
resolve: {
//配置根路径别名: import('@/pages/login/login.vue')
alias: {
// '@': fileURLToPath(new URL('./src', import.meta.url))
"@": path.resolve(__dirname, "src"),
// 配置图片要这样引用
"/img": "./src/assets",
}
},
build: { // 打包设置
// Template for index.html 入口配置
/*rollupOptions:{
// 原因就是默认的打包入口 根目录的index.html删除了。这时候就需要对vite.config.ts进行配置了:
input: 'src/pages/default/index.html'
},*/
// 混淆器,terser 构建后文件体积更小,'terser' | 'esbuild'
minify: 'terser', // 必须启用:terserOptions配置才会有效
chunkSizeWarningLimit: 1500, //chunk 大小警告的限制,默认500KB
rollupOptions: {
output: {
// 最小化拆分包
manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
},
chunkFileNames: 'js/[name].[hash].js', // 用于命名代码拆分时创建的共享块的输出命名,[name]表示文件名,[hash]表示该文件内容hash值
}
},
terserOptions: {
compress: {
// 生产环境时移除console.log调试代码
drop_console:true,
drop_debugger: true,
},
// 10月更新
output: {
comments: true, // 去掉注释内容
},
}
},
css: {
preprocessorOptions: {
less: {
modifyVars: {
hack: `true; @import (reference) "${path.resolve('src/assets/lessVar.less')}";`
},
javascriptEnabled: true
}
}
}
})
18.服务器购买与连接

3. 在弹出的页面,单击【立即重启】使新密码生效。



即可连接
19.nginx服务器使用
代理服务器
注意
使用
将dist文件夹放入nginx根目录下
修改新建的XXX.conf文件
3.打开Powershell cd到当前nginx路径下 输入 ./nginx.exe -c ./conf/你复制的文件名.conf 启动

// XXX自定义的文件名 ./nginx.exe -c ./conf/XXX.conf
20. 项目运行



4.在电脑浏览器尝试使用 你的公网ip加端口访问
21.后端上线
后端目录中启动nodejs
// 启动nodejs node index.js

如果前端设置了基准路径,修改公网IP


重新打包,将打包内容放置服务器dist目录下
关闭和启动nginx
// 关闭nginx: demo自定义 ./nginx.exe -c ./conf/demo.conf -s stop // 开启nginx ./nginx.exe -c ./conf/demo.conf
测试:浏览器输入公网IP
https://www.bilibili.com/video/BV14u411D7qK?p=69&spm_id_from=pageDriver&vd_source=e2cfe74d93fb5b3f60bd7487ede60218
完结撒花!~~

浙公网安备 33010602011771号