Home组件
1.Home组件布局
整个页面布局分为左右两个部分------element-ui中的Layout 布局,以及自适应、鼠标移入时阴影效果的实现------element-ui中的Card卡片布局
span:表示左右侧页面所占用的比例,一共是24份
flex布局:能让相邻的两行内容在一行显示
(1)左侧部分布局–用户信息展示部分
①内容的构建–左侧上面部分

②样式的调整—左侧上面部分
.user {
display: flex;
align-items: center; //垂直居中
img {
margin-right:40px;
width: 150px;
height: 150px;
border-radius: 50%;
}
.userinfo {
.name {
font-size: 32px;
margin-bottom: 10px;
}
.access{
color: #999999;
}
}
}

③内容的构建–左侧下面部分

④样式的调整–左侧下面部分
.user {
display: flex;
align-items: center; //垂直居中
padding-bottom: 20px;
margin-bottom: 20px;
border-bottom: 1px solid #ccc;
img {
margin-right:40px;
width: 150px;
height: 150px;
border-radius: 50%;
}
.userinfo {
.name {
font-size: 32px;
margin-bottom: 10px;
}
.access{
color: #999999;
}
}
}
.login-info {
p {
line-height: 28px;
font-size: 14px;
color:#999999;
span {
color: #666;
margin-left: 60px;
}
}
}

(2)左侧部分布局–home购买统计部分
数据展示一般使用table、鼠标移入有高亮显示----element-ui中的Table表格组件
① 内容的构建

数据:
data() {
return {
tableLabel: {
name: "课程",
todayBuy: "今日购买",
monthBuy: "本月购买",
totalBuy: "总购买",
},
tableData: [
{
name: "oppo",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "vivo",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "苹果",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "小米",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "三星",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "魅族",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
],
};
},
(3)右侧部分-订单统计部分实现
该部分的整体布局也是一个左右布局–左侧是一个图标,右侧是显示的内容
① 将数据渲染到页面上

countData: [
{
name: "今日支付订单",
value: 1234,
icon: "success",
color: "#2ec7c9",
},
{
name: "今日收藏订单",
value: 210,
icon: "star-on",
color: "#ffb980",
},
{
name: "今日未支付订单",
value: 1234,
icon: "s-goods",
color: "#5ab1ef",
},
{
name: "本月支付订单",
value: 1234,
icon: "success",
color: "#2ec7c9",
},
{
name: "本月收藏订单",
value: 210,
icon: "star-on",
color: "#ffb980",
},
{
name: "本月未支付订单",
value: 1234,
icon: "s-goods",
color: "#5ab1ef",
},
],
② 样式的调整
<el-card v-for="item in countData" :key="item.name" :body-style="{display:'flex',padding:0}">
<i class="icon" :class="`el-icon-${item.icon}`" :style="{background:item.color}"></i>
<div class="detail">
<p class="price">¥{{ item.value }}</p>
<p class="desc">{{ item.name }}</p>
</div>
</el-card>
<style lang="less" scoped>
.num {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.icon {
width: 80px;
height: 80px;
font-size: 30px;
color: #fff;
text-align: center;
line-height: 80px;
}
.detail {
margin-left: 15px;
display: flex;
flex-direction: column;
justify-content: center;
.price {
font-size: 30px;
margin: 0;
height: 30px;
}
.desc {
font-size: 14px;
color: #999;
text-align: center;
}
}
.el-card {
width: 32%;
margin-bottom: 20px;
}
}
</style>

2.axios
(1)axios的基本使用
axios安装:npm install axios
(2)axios的二次封装
封装的基本思路:在创建的实例上面配置一些属性,然后对外进行暴露
//axios二次封装 src/utils.request.js
import axios from "axios";
//创建实例
const http = axios.create({
//通用请求的地址前缀
baseURL: '/api',
//超时时间:最大的请求时间,单位是毫秒
timeout: 10000,
})
//拦截器是绑定在当前创建的实例http上面的
// 添加请求拦截器
http.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
http.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
//对外暴露创建的实例
export default http
测试请求是否可以调用成功:
首先在src/api/index.js中配置接口数据的信息,请求首页数据
//api文件夹中放置关于接口数据的信息
import http from '../utils/request'
//请求首页数据
export const getData = () => {
//返回一个Promise对象
return http.get('/home/getData')
}
然后在Home.vue组件中获取请求到的数据

3.mock数据模拟
mock.js:生成随机数据,拦截ajax请求
下载mockjs:npm i mockjs
mock是前端用来模拟后端接口的工具库,可以通过拦截前端发起的请求,然后自己定义一些仿真的数据来实现数据的交互
① 定义mock请求拦截:
//api/mock.js
import Mock from 'mockjs'
import homeApi from './mockServeData/home'
//定义mock请求拦截
//第一个参数:请求地址 ,第二个参数:请求类型(如果是get可以省略, 第三个参数:拦截到请求后的处理函数
Mock.mock('/api/home/getData', 'get', homeApi.getStatisticalData)
② 数据封装:

// 封装模拟的首页数据
// mock数据模拟
import Mock from 'mockjs'
// 图表数据
let List = []
export default {
getStatisticalData: () => {
//Mock.Random.float 产生随机数100到8000之间 保留小数 最小0位 最大0位
for (let i = 0; i < 7; i++) {
List.push(
Mock.mock({
苹果: Mock.Random.float(100, 8000, 0, 0),
vivo: Mock.Random.float(100, 8000, 0, 0),
oppo: Mock.Random.float(100, 8000, 0, 0),
魅族: Mock.Random.float(100, 8000, 0, 0),
三星: Mock.Random.float(100, 8000, 0, 0),
小米: Mock.Random.float(100, 8000, 0, 0)
})
)
}
return {
code: 20000,
data: {
// 饼图
videoData: [
{
name: '小米',
value: 2999
},
{
name: '苹果',
value: 5999
},
{
name: 'vivo',
value: 1500
},
{
name: 'oppo',
value: 1999
},
{
name: '魅族',
value: 2200
},
{
name: '三星',
value: 4500
}
],
// 柱状图
userData: [
{
date: '周一',
new: 5,
active: 200
},
{
date: '周二',
new: 10,
active: 500
},
{
date: '周三',
new: 12,
active: 550
},
{
date: '周四',
new: 60,
active: 800
},
{
date: '周五',
new: 65,
active: 550
},
{
date: '周六',
new: 53,
active: 770
},
{
date: '周日',
new: 33,
active: 170
}
],
// 折线图
orderData: {
date: ['20191001', '20191002', '20191003', '20191004', '20191005', '20191006', '20191007'],
data: List
},
tableData: [
{
name: 'oppo',
todayBuy: 500,
monthBuy: 3500,
totalBuy: 22000
},
{
name: 'vivo',
todayBuy: 300,
monthBuy: 2200,
totalBuy: 24000
},
{
name: '苹果',
todayBuy: 800,
monthBuy: 4500,
totalBuy: 65000
},
{
name: '小米',
todayBuy: 1200,
monthBuy: 6500,
totalBuy: 45000
},
{
name: '三星',
todayBuy: 300,
monthBuy: 2000,
totalBuy: 34000
},
{
name: '魅族',
todayBuy: 350,
monthBuy: 3000,
totalBuy: 22000
}
]
}
}
}
}
③使用封装好的数据:

注意:需要在main.js入口文件中引入mock:
import './api/mock'
4.首页可视化图表样式调整
(1)将左侧table中的数据换成动态数据

(2)调整右侧图表样式布局–flex布局
<el-card style="height: 280px;">
<!-- 折线图 -->
</el-card>
<div class="graph">
<el-card style="height: 260px;"></el-card>
<el-card style="height: 260px;"></el-card>
</div>
.graph {
margin-top: 20px;
display: flex;
justify-content: space-between;
.el-card {
width: 48%;
}
}

(3)echarts表格的基本使用
echarts安装: npm i echarts@5.1.2
(4)echarts表格的折线图、柱状图、饼状图
<el-card style="height: 280px">
<!-- 折线图 -->
<div ref="echarts1" style="height: 280px"></div>
</el-card>
<div class="graph">
<el-card style="height: 260px">
<!-- 柱状图 -->
<div ref="echarts2" style="height: 280px"></div>
</el-card>
<el-card style="height: 260px">
<!-- 饼状图 -->
<div ref="echarts3" style="height: 240px"></div>
</el-card>
import { getData } from "../api";
// 引入echarts 使用 * as echarts
import * as echarts from "echarts";
export default {
mounted() {
getData().then(({ data }) => {
const { tableData } = data.data;
this.tableData = tableData;
// 设置折线图
this.setline(data);
// 设置柱状图
this.setbar(data);
// 设置饼状图
this.setpie(data);
});
},
data() {
return {
tableLabel: [],
tableData: [],
countData: [
{
name: "今日支付订单",
value: 1234,
icon: "success",
color: "#2ec7c9",
},
{
name: "今日收藏订单",
value: 210,
icon: "star-on",
color: "#ffb980",
},
{
name: "今日未支付订单",
value: 1234,
icon: "s-goods",
color: "#5ab1ef",
},
{
name: "本月支付订单",
value: 1234,
icon: "success",
color: "#2ec7c9",
},
{
name: "本月收藏订单",
value: 210,
icon: "star-on",
color: "#ffb980",
},
{
name: "本月未支付订单",
value: 1234,
icon: "s-goods",
color: "#5ab1ef",
},
],
};
},
methods: {
/**
* 初始化并配置echarts图表-折线图
*
* @returns {void} 无返回值
*/
setline(data) {
//基于准备好的dom,初始化echarts实例
const echarts1 = echarts.init(this.$refs.echarts1);
//指定图标的配置项和数据
var echarts1option = {};
//处理数据xAxis-x轴
const { orderData } = data.data;
const xAxis = Object.keys(orderData.data[0]);
const xAxisData = { data: xAxis };
echarts1option.xAxis = xAxisData;
echarts1option.yAxis = {};
echarts1option.legend = xAxisData;
echarts1option.series = [];
//对原数据进行重新组装
xAxis.forEach((key) => {
echarts1option.series.push({
name: key,
data: orderData.data.map((item) => item[key]),
type: "line",
});
});
//使用刚指定的配置项和数据显示图表
echarts1.setOption(echarts1option);
},
/**
* 初始化并配置echarts图表-柱状图
*
* @returns {void} 无返回值
*/
setbar(data) {
//获取mock中的数据
const { orderData, userData } = data.data;
//柱状图
//初始化实例
const echarts2 = echarts.init(this.$refs.echarts2);
const echarts2option = {
legend: {
// 图例文字颜色
textStyle: {
color: "#333",
},
},
grid: {
left: "20%",
},
// 提示框
tooltip: {
trigger: "axis",
},
xAxis: {
type: "category", // 类目轴
data: userData.map((item) => item.date),
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
axisLabel: {
interval: 0,
color: "#333",
},
},
yAxis: [
{
type: "value",
axisLine: {
lineStyle: {
color: "#17b3a3",
},
},
},
],
color: ["#2ec7c9", "#b6a2de"],
series: [
{
name: "新增用户",
data: userData.map((item) => item.new),
type: "bar",
},
{
name: "活跃用户",
data: userData.map((item) => item.active),
type: "bar",
},
],
};
//调用实例的setOption
echarts2.setOption(echarts2option);
},
/**
* 初始化并配置echarts图表-饼状图
*
* @returns {void} 无返回值
*/
setpie(data) {
//获取mock中的数据
const { videoData } = data.data;
//饼状图
//初始化实例
const echarts3 = echarts.init(this.$refs.echarts3);
//配置数据
const echarts3option = {
tooltip: {
trigger: "item",
},
color: [
"#0f78f4",
"#dd536b",
"#9462e5",
"#a6a6a6",
"#e1bb22",
"#39c362",
"#3ed1cf",
],
series: [
{
data: videoData,
type: "pie",
},
],
};
//调用实例的setOption
echarts3.setOption(echarts3option);
},
},
};

5.顶部面包屑的实现
(1)面包屑&tag的介绍
要实现面包屑的功能:当点击商品管理时,顶部出现面包屑,同时在下面的内容区出现tag(当前的tag标签是一个高亮显示)
功能:可以通过点击面包屑实现路由的切换 (同时tag高亮显示)、点击tag时也要实现路由的切换
-----tag和面包屑需要相互联动 、数据同步(组件通信)
tag属于公共部分–main.vue中
(2)面包屑数据处理
面包屑默认显示首页,且显示在Header区;如果点击面包屑没有的路由组件话,就会增加一个面包屑;点击已有的菜单时,面包屑不会重复添加 -----在不同组件间实现数据的共享–vuex
element-ui–面包屑

点击菜单时需要获取到当前路由组件的名称和路径




(3)面包屑样式遗留问题处理
①面包屑应该与button按钮所处一行 ②一些样式调整
.l-content {
display: flex;
align-items: center; //垂直居中
/deep/ .el-breadcrumb__item {
.el-breadcrumb__inner {
font-weight: normal;
&.is-link {
color: #666;
cursor: pointer;
}
}
&.is-active {
.el-breadcrumb__inner {
color: #fff;
cursor:initial;
}
}
}
}
(4)tag功能介绍及页面编写
tag包含的功能:默认显示首页的tag;点击左侧菜单时会新增一个tag;点击tag时会引起页面路由的一个跳转;点击tag关闭的时候,点击的tag会被删除,同时其对应的面包屑也会删除;当前激活的tag标签会有一个高亮的效果
样式部分----elementui中的tag标签
需要判断当前的name属性是不是所需要渲染的name属性
:effect=“$route.name === item.name ? ‘dark’:‘plain’”


(5)tag点击与删除事件
①点击tag进行路由跳转:添加点击事件

② 点击tag进行路由组件的删除
首先,点击tag删除的时候是调用的store中的mutation方法实现了路径的删除


然后,获取到更新之后的数据 -1,获取到当前点击的tag的位置标识
//获取当前点击的tag的长度(索引)
const length = this.tags.length - 1;
最后效果:

参考学习:https://blog.youkuaiyun.com/weixin_45835813/article/details/131673563?spm=1001.2014.3001.5502
1万+

被折叠的 条评论
为什么被折叠?



