SKU管理模块 开发
- 先完成
静态组件
### Sku.index.vue
<template>
<div>
<el-table style="width: 100%" border >
<el-table-column type="index" label="序号" width="80px" align="center">
</el-table-column>
<el-table-column prop="prop" label="名称" width="width">
</el-table-column>
<el-table-column prop="prop" label="描述" width="width">
</el-table-column>
<el-table-column prop="prop" label="默认图片" width="110">
</el-table-column>
<el-table-column prop="prop" label="重量" width="80">
</el-table-column>
<el-table-column prop="prop" label="价格" width="80">
</el-table-column>
<el-table-column prop="prop" label="操作" width="width">
</el-table-column>
</el-table>
<!--
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
page-sizes: 选择器,每页选择显示几条数据,[3,5,10]
page-count: 页码数量,必须奇数
layout: 组件布局
-->
<el-pagination style="margin-top: 20px;textAlign:center" :current-page="page" :page-size="limit"
:page-sizes="[3,5,10]" :page-count="7" :total="total" layout="prev,pager,next,jumper,->,sizes,total">
</el-pagination>
</div>
</template>
<script>
export default {
name:'Sku'
}
</script>
<style>
</style>
- 配置请求并存储后端返回的数据
### product.sku.js
......
export const reqSkuList = (page,limit)=>request({url:`/admin/product/list/${page}/${limit}`,method:'get'})
### Sku.index.vue
......
<script>
export default {
name:'Sku',
data(){
return {
// 分页相关
page:1,
limit:10,
total:0,
// 存储SKU列表数据
records:[]
}
},
methods:{
async getSkuList(){
const {page,limit} = this;
let res = await this.$API.sku.reqSkuList(page,limit)
if(res.code == 200){
this.records = res.data.records
this.total = res.data.total
}
}
},
mounted(){
this.getSkuList() // 挂载完毕即发请求
},
}
</script>
- 渲染数据
### Sku.index.vue
<template>
<div>
<!--数据源:data-->
<el-table style="width: 100%" border :data="records">
<el-table-column type="index" label="序号" width="80px" align="center">
</el-table-column>
<!--渲染数据-->
<el-table-column prop="skuName" label="名称" width="width">
</el-table-column>
<el-table-column prop="skuDesc" label="描述" width="width">
</el-table-column>
<el-table-column label="默认图片" width="110">
<template slot-scope="{row,$index}">
<img :src="row.skuDefaultImg" style="width: 80px;height: 80px;">
</template>
</el-table-column>
<el-table-column prop="weight" label="重量" width="80">
</el-table-column>
<el-table-column prop="price" label="价格" width="80">
</el-table-column>
<el-table-column prop="prop" label="操作" width="width">
<template slot-scope="{row,$index}">
<el-button type="success" icon="el-icon-sort-down" size="mini"></el-button>
<el-button type="success" icon="el-icon-sort-up" size="mini"></el-button>
<el-button type="primary" icon="el-icon-edit" size="mini"></el-button>
<el-button type="info" icon="el-icon-info" size="mini"></el-button>
<el-button type="danger" icon="el-icon-delete" size="mini"></el-button>
</template>
</el-table-column>
</el-table>
<!--绑定页码事件和每页展示数据量事件-->
<el-pagination style="margin-top: 20px;textAlign:center" :current-page="page" :page-size="limit"
:page-sizes="[3,5,10]" :page-count="7" :total="total" layout="prev,pager,next,jumper,->,sizes,total"
@current-change="getSkuList" @size-change="handleSizeChange">
</el-pagination>
</div>
</template>
<script>
export default {
name:'Sku',
......
methods:{
async getSkuList(pages=1){
......
},
// 每页展示多少条数据
handleSizeChange(limit){
this.limit = limit
this.getSkuList()
}
},
......
}
</script>
SKU
商品的"上架"与"下架" 功能实现
- 结构互斥,是否上架由
isSale
字段来决定
......
<!--互斥-->
<el-button type="success" icon="el-icon-sort-down" size="mini" v-if="row.isSale==0"></el-button>
<el-button type="success" icon="el-icon-sort-up" size="mini" v-else></el-button>
- 发请求通知后端,用户的动作(是'上架'还是'下架')
### product.sku.js
......
// 通知SKU商品是否'上架'
export const reqCancel = (skuId)=>request({url:`/admin/product/cancelSale/${skuId}`,method:'get'})
- 绑定点击事件并书写逻辑
### Sku.index.vue
......
<el-table-column prop="prop" label="操作" width="width">
<template slot-scope="{row,$index}">
<!--绑定两个点击事件-->
<el-button type="success" icon="el-icon-sort-down" size="mini" v-if="row.isSale==0" @click="sale(row)"></el-button>
<el-button type="success" icon="el-icon-sort-up" size="mini" v-else @click="cancel(row)"></el-button>
......
</template>
</el-table-column>
......
async sale(sku){
let res = await this.$API.sku.reqCancel(sku.id)
if(res.code == 200){
sku.isSale = 1;
this.$message({type:'success',message:'上架成功'})
}
},
async cancel(sku){
let res = await this.$API.sku.reqCancel(sku.id)
if(res.code == 200){
sku.isSale = 0;
this.$message({type:'success',message:'下架成功'})
}
}
获取SKU详情 功能实现
- 配置请求
### product.sku.js
......
// 获取SKU详情
export const reqSkuById = (skuId)=>request({url:`/admin/product/getSkuById/${skuId}`,method:'get'})
- 搞定
静态组件
### Sku.index.vue
......
<el-pagination>
......
</el-pagination>
<!--SKU详情抽屉效果-->
<el-drawer
:visible.sync="drawer"
:direction="direction"
:show-close="false"
size="50%"
>
<el-row>
<el-col :span="5">名称</el-col>
<el-col :span="16">sku</el-col>
</el-row>
<el-row>
<el-col :span="5">名称</el-col>
<el-col :span="16">sku</el-col>
</el-row>
<el-row>
<el-col :span="5">名称</el-col>
<el-col :span="16">sku</el-col>
</el-row>
<el-row>
<el-col :span="5">名称</el-col>
<el-col :span="16">sku</el-col>
</el-row>
<el-row>
<el-col :span="5">名称</el-col>
<el-col :span="16">sku</el-col>
</el-row>
</el-drawer>
......
<script>
export default {
name:'Sku',
data(){
return {
......
// 抽屉效果
drawer: false,
direction: 'rtl',
}
},
methods:{
......
async getSkuInfo(sku){
// 若把逻辑写在"发请求"后面,会造成抽屉效果'延迟',故放到前面
this.drawer = true; // 抽屉展示SKU详情
let res= await this.$API.sku.reqSkuById(sku.id)
......
},
},
}
</script>
- 渲染数据
### Sku.index.vue
......
<!--SKU详情抽屉效果-->
<el-drawer
:visible.sync="drawer"
:direction="direction"
:show-close="false"
size="50%"
>
<el-row>
<el-col :span="5">名称</el-col>
<el-col :span="16">{{skuInfo.skuName}}</el-col>
</el-row>
<el-row>
<el-col :span="5">描述</el-col>
<el-col :span="16">{{skuInfo.skuDesc}}</el-col>
</el-row>
<el-row>
<el-col :span="5">价格</el-col>
<el-col :span="16">{{skuInfo.price}}</el-col>
</el-row>
<el-row>
<el-col :span="5">平台属性</el-col>
<el-col :span="16">
<!--使用template插入tag标签-->
<template>
<el-tag type="success" v-for="(attr,index) in skuInfo.skuAttrValueList" :key="attr.id" style="margin-right:10px">{{attr.attrId}}-{{attr.valueId}}</el-tag>
</template>
</el-col>
</el-row>
<el-row>
<el-col :span="5">商品图片</el-col>
<el-col :span="16">
<!--轮播图(也叫"走马灯")-->
<el-carousel height="150px">
<el-carousel-item v-for="item in skuInfo.skuImageList" :key="item.id">
<img :src="item.imgUrl" alt="">
</el-carousel-item>
</el-carousel>
</el-col>
</el-row>
</el-drawer>
......
<script>
export default {
name:'Sku',
data(){
return {
......
drawer: false,
direction: 'rtl',
}
},
......
}
</script>
<style scoped>
.el-row .el-col-5 {
font-size: 18px;
text-align: right;
}
.el-col {
margin: 10px 10px;
}
</style>
<style>
/* 组件自带样式 */
.el-carousel__item h3 {
color: #475669;
font-size: 14px;
opacity: 0.75;
line-height: 150px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
/* 自定义轮播图小按钮的样式(原生的太丑) */
.el-carousel__button {
width: 10px;
height: 10px;
background: red;
border-radius: 50%;
}
</style>
深度选择器
scoped
属性: 只对当前的组件样式有用- 底层原理: 给当前组件添加上了一个
data-v-xxxx
自定义属性,vue
通过属性选择器,给元素添加上样式
- h3[data-v-78b7sd7f790]
子组件
的根标签
(拥有父组件当中的自定义属性)
- 若子组件的根节点,和父组件中书写的样式相同,也会添加上相应的样式
- 通俗理解: 此时父组件中使用了"scoped",子组件也会生效
-
注意事项: 如果父组件的样式(scoped),此时还想影响子组件的样式,这种情况可以使用
深度选择器
-
深度选择器
可以实现样式穿透
- 原生CSS: >>>
<style scoped>
>>>h3{
color:red;
}
</style>
- less: /deep/
- scss: ::v-deep
- 应用到项目中,可以这么写
### Sku,index.vue
......
<style scoped>
.el-row .el-col-5 {
font-size: 18px;
text-align: right;
}
.el-col {
margin: 10px 10px;
}
/* 样式穿透 */
>>>.el-carousel__button {
width: 10px;
height: 10px;
background: red;
border-radius: 50%;
}
</style>
<style>
......
/* .el-carousel__button {
width: 10px;
height: 10px;
background: red;
border-radius: 50%;
} */
</style>
canvas(画布)
- 基本使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
/*画布效果*/
canvas {
border: 1px solid red;
}
</style>
</head>
<body>
<canvas></canvas>
</body>
</html>
- 默认宽度和高度是 300*150
- 浏览器认为canvas标签是一张图片
- 添加文本 || 子节点 没有任何意义
- 该标签的宽度和高度务必通过 width||height设置
<body>
<canvas width="600" height="400"></canvas>
</body>
- 绘制线段并闭合图形(三角形)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
canvas {
border: 1px solid red;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
</body>
</html>
<script>
let canvas = document.querySelector('canvas') // 获取cavas对象
let ctx = canvas.getContext('2d') // 获取画笔
ctx.moveTo(100,100) // 设置起点
ctx.lineTo(100,200) // 设置其他点
ctx.lineTo(200,100)
ctx.closePath() // 闭合路径
ctx.stroke() // 开始绘图
</script>
- 配置线段的颜色,填充区域
<script>
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
ctx.moveTo(100,100)
ctx.lineTo(100,200)
ctx.lineTo(200,100)
ctx.fillStyle = "red"
ctx.fill() // 填充
ctx.strokeStyle = "purple" // 线段颜色
ctx.lineWidth = 2
ctx.closePath()
ctx.stroke()
</script>
- 绘制矩形
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
canvas {
border: 1px solid red;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
</body>
</html>
<script>
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
// (x,y,宽度,高度)
// 注意: 使用strokeRect无法填充图形并设置样式(局限性大)
ctx.strokeRect(100,200,100,200)
</script>
- 绘制可以填充样式的矩形
......
<script>
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
ctx.fillStyle = 'skyblue' // 设置样式
ctx.fill()
ctx.fillRect(300,200,100,200)
</script>
- 绘制圆形
......
<script>
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
// 绘制圆形
ctx.beginPath();
// 参数(x,y(圆心位置),半径,起始弧度,结束弧度,顺/逆时针)
ctx.arc(100,100,50,0,2*Math.PI,true)
ctx.fillStyle = 'skyblue'
ctx.fill()
ctx.stroke()
</script>
注意事项: 再次强调
- canvas的宽度和高度,一定不能通过css去设置,否则绘图的时候,会出现各种不可思议的问题
- 清除画布(清除部分 && 清除全部)
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
ctx.fillStyle = 'skyblue'
ctx.fill()
ctx.fillRect(300,200,100,200)
// 清除部分画布内容
// ctx.clearRect(300,200,50,100)
// 清除所有画布内容
ctx.clearRect(0,0,600,400)
- 绘制文字
<script>
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
ctx.font = "30px 微软雅黑" // 设置大小,字体,颜色
ctx.fillStyle = 'red'
ctx.fillText('数据可视化',50,50) // 绘制文字
</script>
案例: 绘制矩形柱状图
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
canvas {
border: 1px solid red;
}
</style>
</head>
<body>
<canvas width="800" height="420"></canvas>
</body>
</html>
<script>
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
ctx.font = "16px 微软雅黑"; // 绘制文字
ctx.fillText('数据可视化',50,80)
ctx.moveTo(100,100) // 绘制Y轴
ctx.lineTo(100,400)
ctx.lineTo(700,400) // 绘制X轴
ctx.stroke() // 作画
// 绘制横线
ctx.moveTo(100,100);
ctx.lineTo(700,100) // 绘制最上层的横线
ctx.fillText('150',70,110) // Y轴数值
ctx.moveTo(100,160);
ctx.lineTo(700,160) // 绘制次上层的横线
ctx.fillText('120',70,170) // Y轴数值
ctx.moveTo(100,220);
ctx.lineTo(700,220) // 绘制第三层的横线
ctx.fillText('90',70,230) // Y轴数值
ctx.moveTo(100,280);
ctx.lineTo(700,280) // 绘制第四层的横线
ctx.fillText('60',70,290) // Y轴数值
ctx.moveTo(100,340);
ctx.lineTo(700,340) // 绘制第五层的横线
ctx.fillText('30',70,350) // Y轴数值
ctx.stroke()
// 绘制水平轴底部的线段
ctx.moveTo(250,400); // 最近的线段
ctx.lineTo(250,410)
// ctx.stroke()
ctx.moveTo(400,400); // 第二个线段
ctx.lineTo(400,410)
ctx.moveTo(550,400); // 第三个线段
ctx.lineTo(550,410)
ctx.stroke()
// 绘制底部文字
ctx.fillText('食品',170,415)
ctx.fillText('数码',310,415)
ctx.fillText('服饰',450,415)
ctx.fillText('箱包',600,415)
ctx.stroke()
// 绘制矩形
ctx.fillStyle = 'red'
ctx.fillRect(120,200,100,200)
</script>
svg
- 矢量图
- 通俗理解: 封装度更高的
canvas
### demo演示: 画各种图形
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 800px;
height: 800px;
}
</style>
</head>
<body>
<svg class="box">
<!--x1,y1是第一个点的左边,以此类推-->
<line x1="100" y2="100" x2="200" y2="200" stroke="red"></line>
<!--绘制折线-->
<polyline points="300 300,50 100,120 400,20,20" fill-opacity="0" stroke="cyan"></polyline>
<!--绘制矩形-->
<rect x="400" y="400" width="150" height="50" fill="pink"></rect>
<!--绘制圆形-->
<circle cx="370" cy="95" r="50" style="stroke:cyan;fill:none"></circle>
<!--绘制椭圆-->
<ellipse cx="500" cy="500" rx="100" ry="50" style="fill:black"></ellipse>
<!--绘制多边形-->
<polygon points="600 100,300 400,750 100" stroke="red" fill-opacity="0"></polygon>
<!-- 绘制任意图形 -->
<path fill-opacity="0" stroke="skyblue" d="
M 10 10
L 20 400
L 30 120
L 40 66
L 50 99
L 60 120
L 70 99
Z
"></path>
</svg>
</body>
</html>
......
echarts
- 准备工作
- 引入js依赖包
- 准备容器
- 创建echarts实例
- 配置项
- 注意事项: 若有多张表图,就创建多个容器,实例以及配置项即可
- demo演示: 柱状图
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 引入echarts依赖包 -->
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 800px;
height: 400px;
}
</style>
</head>
<body>
<!--准备容器-->
<div></div>
</body>
</html>
<script>
let dom = document.querySelector('div') // 获取dom节点
let mycharts = echarts.init(dom) // 初始化实例
mycharts.setOption({ // 开始配置
title:{
text:'数据可视化',
subtext:'echarts基本使用'
},
xAxis:{
data:['飞机','大炮','轮船','自行车']
},
yAxis:{
axisLine:{show:true}, // 展示y轴数值
axisTick:{show:true} // 展示y轴刻度
},
series:{
type:"bar", // 柱状图
data:[10,20,30,40],
color:"red"
}
})
</script>
- 展示多个图表:
柱状图
和折线图
展示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 引入echarts依赖包 -->
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 800px;
height: 400px;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
<script>
let dom1 = document.querySelector('.box1')
let dom2 = document.querySelector('.box2')
let mycharts1 = echarts.init(dom1)
let mycharts2 = echarts.init(dom2)
mycharts1.setOption({
title:{
text:'数据可视化',
subtext:'echarts基本使用'
},
xAxis:{
data:['飞机','大炮','轮船','自行车']
},
yAxis:{
axisLine:{show:true},
axisTick:{show:true}
},
series:{
type:"bar",
data:[10,20,30,40],
color:"red"
}
});
mycharts2.setOption({
title:{
text:'折线图',
left:"center",
textStyle:{
color:'red'
},
subtext:'echarts基本使用',
subtextStyle:{
color:'cyan'
}
},
xAxis:{
data:['星期一','星期二','星期三','星期四','星期五','星期六','星期日']
},
yAxis:{},
series:{
type:"line",
data:[10,20,15,44,2,19,100],
color:"skublue"
}
})
</script>
- 一个容器内,显示多张图表:
series
变成`list``,包裹一个个配置项即可
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 引入echarts依赖包 -->
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 800px;
height: 400px;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
<script>
let dom1 = document.querySelector('.box1')
// let dom2 = document.querySelector('.box2')
let mycharts1 = echarts.init(dom1)
// let mycharts2 = echarts.init(dom2)
mycharts1.setOption({
title:{
text:'数据可视化',
subtext:'echarts基本使用'
},
xAxis:{
data:['飞机','大炮','轮船','自行车']
},
yAxis:{
axisLine:{show:true},
axisTick:{show:true}
},
series:[
{
type:"bar", // 柱状图
data:[10,20,30,40],
color:"red"
},
{
type:"line", // 折线图
data:[10,20,30,40],
color:"pink"
},
{
type:"pie", // 饼状图
data:[
{name:'x',value:10},
{name:'y',value:20},
{name:'z',value:30},
{name:'t',value:40},
],
width:150,
height:150,
left:150,
top:100,
radius:25,
}
]
});
</script>
dataset属性介绍
- 通俗理解: 把原来分散在
series
的数据,集中放到一起,统一管理(方便组件的复用)
- 之前的方式
series:[
{
type:"bar",
data:[10,20,30,40], // 分散的数据
color:"red"
},
{
type:"line",
data:[10,20,30,40], // 分散的数据
color:"pink"
},
{
type:"pie",
data:[ // 分散的数据
{name:'x',value:10},
{name:'y',value:20},
{name:'z',value:30},
{name:'t',value:40},
],
width:150,
height:150,
left:150,
top:100,
radius:25
}
]
- 现在的方式
<script>
......
let data = [ // 把数据集放入dataset即可
["衣服",10,22,'x',10],
["直播",12,55,'y',60],
["游戏",16,44,'z',50],
["电影",19,32,'t',70],
]
mycharts.setOption({
dataset:{
//数据源
source:data
},
- 注意事项: 数据的定义方式,必须是一个
二维数组
或者对象数组(即数组里面包裹一个个对象)
demo
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入echarts依赖包 -->
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.js"></script>
<style>
*{
margin: 0;
padding: 0;
}
div{
width: 800px;
height: 400px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
<script>
let dom = document.querySelector('div');
let mycharts = echarts.init(dom);
//数据集
let data = [
// X轴数据 Y轴数据(柱状) Y轴数据(折线) 饼状数据
["衣服",10,10,'x',10],
["直播",20,20,'y',20],
["游戏",30,30,'z',30],
["电影",40,40,'t',40],
]
mycharts.setOption({
//设置数据集
dataset:{
//数据源
source:data
},
title:{
text:'数据可视化',
subtext:"echarts基本使用",
textStyle:{
color:'cyan'
},
left:'center'
},
//x轴的配置项
xAxis:{
data:["衣服",'直播','游戏','电影']
},
yAxis:{
axisLine:{
show:true
},
axisTick:{
show:true
}
},
series:[
//柱状图
{
type:"bar",
// data:[10,20,30,40],
color:'red',
encode:{ // 映射维度为1的数据到y轴
y:1
}
}
,
// 折线图
{
type:'line',
// data:[10,20,30,40],
color:'pink',
encode:{ // 映射维度为2的数据到y轴
y:2
}
},
//饼图
{
type:'pie',
// data:[{name:'x',value:10},{name:'y',value:20},{name:'z',value:30},{name:'t',value:40}],
width:250,
height:250,
left:150,
top:100,
radius:25,
encode:{ // 映射数据集
//饼图旁边的文字
itemName:3, // 映射维度为3和4 key-value 键值对
value:4
}
}
]
});
</script>
Echarts组件
- 除绘图之外的部分,都可以认为是
组件
- xAxis(X轴)
- yAxis(Y轴)
- grid(直角坐标系底板)
demo
环境搭建: 简单展示柱状图
和折线图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入echarts依赖包 -->
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 100%;
height: 400px;
border: 1px solid black;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
<script>
let dom = document.querySelector('div');
let mycharts = echarts.init(dom);
mycharts.setOption({
title: {
text: '数据可视化',
},
xAxis: {
data: ["衣服", '直播', '游戏', '电影']
},
yAxis: {},
series: [
//柱状图
{
type: "bar",
data:[10,20,30,40],
},
// 折线图
{
type: 'line',
data:[20,30,40,50],
},
]
});
</script>
- 添加几个功能组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 100%;
height: 400px;
/* border: 1px solid black; */
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
<script>
let dom = document.querySelector('.box');
let mycharts = echarts.init(dom);
mycharts.setOption({
dataZoom: {}, // 数据滑动条变焦组件
title: {
text: "echarts组件"
},
xAxis: {
data: ['游戏', '电影', "直播", '娱乐']
},
yAxis: {},
series: [
{
name: "柱状图",
type: "bar",
data: [20, 30, 40, 50]
}
,
{
name: "折线图",
type: 'line',
data: [30, 40, 50, 60]
}
]
,
//提示组件
tooltip: {
//提示框文字的颜色
textStyle: {
color: 'red'
}
},
//图表切换组件
legend: {
data: ['柱状图', '折线图']
},
//工具栏组件
toolbox: {
show: true,
feature: {
saveAsImage: {},
dataZoom: {
yAxisIndex: "none"
},
dataView: {
readOnly: false
},
magicType: {
type: ["line", "bar"]
},
restore: {},
}
},
//调整图标布局(使图表全屏展示)
grid: {
left: 30,
right: 0,
}
})
</script>
Echarts
基本概念之坐标系
- 一个
坐标系
可能由多个组件写作而成,以最常见的直角坐标系
举例
- xAxis
- yAxis
- grid(底板)
- xAxis和yAxis 被 grid 自动引用并组织起来,共同工作
demo
举例: 散点图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入echarts依赖包 -->
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 100%;
height: 400px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
<script>
let dom = document.querySelector('div');
let mycharts = echarts.init(dom);
//一个坐标系:散点图
mycharts.setOption({
/
title: {
text: "一个坐标系"
}
,
//x轴
xAxis: {
type:'category' // 映射10,13,50....
},
yAxis: {},
//散点图
series: [
{
type: "scatter",
//散点图的数据
data: [
[10, 20],
[13, 66],
[50, 9],
[44, 22],
[15, 10]
]
}
]
});
</script>
首页图表实现
- 先搞定
静态组件
### dashboard新建子组件
### Card.index.vue
<template>
<div>
我是顶部显示的card组件
<Detail></Detail>
</div>
</template>
<script>
import Detail from './Detail'
export default {
name:'',
components:{
Detail
}
}
</script>
......
### dashboard注册
<template>
<div>
<Card></Card>
</div>
</template>
<script>
import Card from './Card'
export default {
name: 'Dashboard',
components:{
Card
},
}
</script>
<style lang="scss" scoped>
.dashboard {
&-container {
margin: 30px;
}
&-text {
font-size: 30px;
line-height: 46px;
}
}
</style>
### Card新建子组件Detail(需展示四个)
### Detail.index.vue
<template>
<div>
<!--把每块区域拆成4个部分-->
<div class="card-header">头部地方</div>
<div class="card-content">内容区域</div>
<div class="card-charts">图标区域</div>
<div class="card-footer">底部</div>
</div>
</template>
<script>
export default {
name:''
}
</script>
......
- 搞定
布局
### Card.index.vue
<template>
<div>
<el-row :gutter="10">
<!--总共24个空间-->
<!--每6个空间插入一个'卡片组件',用来包裹'Detail组件'-->
<el-col :span="6">
<el-card>
<Detail></Detail>
</el-card>
</el-col>
<el-col :span="6">
<el-card>
<Detail></Detail>
</el-card>
</el-col>
<el-col :span="6">
<el-card>
<Detail></Detail>
</el-card>
</el-col>
<el-col :span="6">
<el-card>
<Detail></Detail>
</el-card>
</el-col>
</el-row>
</div>
</template>
......
- 所谓
插槽
子组件
留坑- 父组件填坑
- 用途: 复用子组件的时候,遇到结构不一致的时候,子组件预设
插槽
,由父组件
根据插槽
渲染不同的结构,传值即可
### 子组件
<template>
<div>
<div class="card-header">
......
</div>
<div class="card-charts">
<!--留坑-->
<slot name="charts">
</slot>
</div>
### 父组件
<el-card>
<Detail title="总销售额" count=" ¥ 12306">
<!--占坑-->
<template slot="charts">
<span>周同比 56.67%</span>
<span>周同比 19.96%</span>
</template>
</Detail>
</el-card>
- 完成其他静态结构
### Card.index.vue
<template>
<div>
<el-row :gutter="10">
<!--总共24个空间-->
<el-col :span="6">
<el-card>
<Detail title="总销售额" count=" ¥ 12306">
<!--响应子组件charts插槽,插入自定义的结构-->
<template slot="charts">
<span>周同比 56.67%</span>
<!--插入矢量图-->
<svg t="1692935095365" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5389" width="16" height="16"><path d="M698.7 480.9v429.5c0 54.8-44.5 99.3-99.3 99.3H434c-54.8 0-99.3-44.5-99.3-99.3V480.9H70l446.9-463 446.9 463H698.7z m0 0" fill="#1afa29" p-id="5390"></path></svg>
<span>周同比 19.96%</span>
<svg t="1692935225089" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6581" width="16" height="16"><path d="M335 546.6V117.1c0-54.8 44.5-99.3 99.3-99.3h165.4c54.8 0 99.3 44.5 99.3 99.3v429.5h264.7l-446.9 463L70 546.6h265z m0 0" fill="#d81e06" p-id="6582"></path></svg>
</template>
<!--响应子组件footer插槽,插入自定义的结构-->
<template slot="footer">
<span>日销售额¥ 12423</span>
</template>
</Detail>
</el-card>
</el-col>
<el-col :span="6">
<el-card>
<Detail title="访问量" count=12306>
<template slot="footer">
<span>日访问量1234</span>
</template>
</Detail>
</el-card>
</el-col>
<el-col :span="6">
<el-card>
<Detail title="支付笔数" count=12306>
<template slot="footer">
<span>转换率64%</span>
</template>
</Detail>
</el-card>
</el-col>
<el-col :span="6">
<el-card>
<Detail title="运营活动效果" count=78%>
<template slot="footer">
<span>周同比 12%</span>
<svg t="1692935095365" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5389" width="16" height="16"><path d="M698.7 480.9v429.5c0 54.8-44.5 99.3-99.3 99.3H434c-54.8 0-99.3-44.5-99.3-99.3V480.9H70l446.9-463 446.9 463H698.7z m0 0" fill="#1afa29" p-id="5390"></path></svg>
<span>日同比 11%</span>
<svg t="1692935225089" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6581" width="16" height="16"><path d="M335 546.6V117.1c0-54.8 44.5-99.3 99.3-99.3h165.4c54.8 0 99.3 44.5 99.3 99.3v429.5h264.7l-446.9 463L70 546.6h265z m0 0" fill="#d81e06" p-id="6582"></path></svg>
</template>
</Detail>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import Detail from './Detail'
export default {
name:'',
components:{
Detail
}
}
</script>
### Detail.index.vue
<template>
<div>
<div class="card-header">
<span>{{title}}</span>
<!--复用组件,使用同一个矢量图-->
<svg t="1692932780198" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4025" width="16" height="16"><path d="M468.394667 936.448a427.946667 427.946667 0 0 1-42.368-6.485333 431.488 431.488 0 0 1-80.085334-24.832 426.368 426.368 0 0 1-72.533333-39.338667 429.312 429.312 0 0 1-63.146667-52.096 429.269333 429.269333 0 0 1-52.096-63.146667 426.666667 426.666667 0 0 1-39.338666-72.533333 418.602667 418.602667 0 0 1-24.832-80.085333 425.429333 425.429333 0 0 1-6.485334-42.368A434.474667 434.474667 0 0 1 85.333333 512a434.517333 434.517333 0 0 1 2.218667-43.605333 425.514667 425.514667 0 0 1 6.485333-42.368 431.488 431.488 0 0 1 24.832-80.085334 426.666667 426.666667 0 0 1 39.338667-72.533333 429.312 429.312 0 0 1 52.096-63.146667 429.44 429.44 0 0 1 63.146667-52.096 426.325333 426.325333 0 0 1 72.533333-39.338666 418.602667 418.602667 0 0 1 80.085333-24.832 427.349333 427.349333 0 0 1 42.368-6.485334A433.194667 433.194667 0 0 1 512 85.333333a433.493333 433.493333 0 0 1 43.605333 2.218667 427.818667 427.818667 0 0 1 42.368 6.485333 431.488 431.488 0 0 1 80.085334 24.832 426.666667 426.666667 0 0 1 72.533333 39.338667 429.909333 429.909333 0 0 1 63.146667 52.096 429.866667 429.866667 0 0 1 52.096 63.146667 426.666667 426.666667 0 0 1 39.338666 72.533333c5.418667 12.8 10.24 25.984 14.336 39.210667s7.68 27.136 10.538667 40.874666 5.034667 28.16 6.442667 42.368A431.488 431.488 0 0 1 938.666667 512a431.445333 431.445333 0 0 1-2.218667 43.605333 428.458667 428.458667 0 0 1-6.442667 42.368 419.114667 419.114667 0 0 1-24.874666 80.085334 426.666667 426.666667 0 0 1-39.338667 72.533333 429.781333 429.781333 0 0 1-52.096 63.146667 429.866667 429.866667 0 0 1-63.146667 52.096 426.666667 426.666667 0 0 1-72.533333 39.338666 414.293333 414.293333 0 0 1-80.085333 24.832 428.416 428.416 0 0 1-42.368 6.485334A433.493333 433.493333 0 0 1 512 938.666667a433.194667 433.194667 0 0 1-43.605333-2.218667zM145.066667 512a367.36 367.36 0 0 0 366.933333 366.933333 367.36 367.36 0 0 0 366.933333-366.933333A367.36 367.36 0 0 0 512 145.066667 367.36 367.36 0 0 0 145.066667 512z m270.933333 250.666667v-59.733334h66.133333V416H424.533333v-59.733333h117.333334v346.666666h66.133333v59.733334zM482.133333 322.133333v-59.733333h59.733334v59.733333z" p-id="4026"></path></svg>
</div>
<div class="card-content">{{count}}</div>
<!--留坑-->
<div class="card-charts">
<slot name="charts">
</slot>
</div>
<div class="card-footer">
<slot name="footer">
</slot>
</div>
</div>
</template>
<script>
export default {
name:'',
props:['title','count'] // 接收父组件传过来的值
}
</script>
<style scoped>
/*自定义的样式*/
.card-header {
display: flex;
justify-content: space-between;
color: #d9d9d9;
}
.card-content {
font-size: 30px;
padding: 10px 0px;
}
.card-charts {
height: 40px;
}
.card-footer {
border-top: 1px solid #eee;
padding: 10px;
}
</style>