尚品汇后台项目(一)https://developer.aliyun.com/article/1590757?spm=a2c6h.13148508.setting.14.2db54f0emglpB8
P38、照片墙数据的收集
照片墙何时收集数据
删除的时候要收集
照片墙参数的意义
action:图片上传的地址 需要加入/dev/api/ 不然出现跨域问题
list-type:内置属性 类型为照片墙
file-list:展示图片的数据来源 数组类型
on-preview:预览的回调
on-remove:删除的回调
回调参数的意义 看上图
目前先把数据收集到之前初始的imgList字段里面
PS :服务器返回的数据我们给添加上了name和url字段
为了在照片墙上显示图片 但是给服务器提交的时候不需要这个字段 后续会处理
删除时候数据收集完成
添加图片的时候也要收集数据
上传成功的回调
参数解释:response:返回的上传状态的信息
file:返回的当前上传图片的信息
fileList:上传完毕之后全部的数组信息
照片数据收集完毕
注意这里全部有name和url属性 没有这些属性无法回显
但是给服务器传递参数的时候不能带name和url这两个属性
P39、销售属性添加的事件
销售属性要收集的内容
baseSaleAttrId
saleAttrName
spuSaleAttrValueList 数组类型 这些是需要收集的数据
什么时候收集?
选择下拉框的时候
如何收集呢 value绑定的数据来进行收集
value绑定的数据再添加一条
这时就可以收集到baseSaleAttrId:saleAttrName了
收集到哪里?
收集到spu.spuSaleAttrList数组里面
因为下面数据的展示需要这些数据
因为数组里面是对象 所以传入的类型要为对象
P40、销售属性值的收集和展示
和之前做的span/input切换类似
选择添加之后 在下拉框内把改属性清除
在点击之前的span标签的时候添加控制input显示的属性inputVisible
以及收集数据的地方 inputValue 注意这里不能直接赋值 直接赋值的数据不是响应式的 需要属于$set
给按钮添加点击事件
添加了控制切换的属性 数据也收集到了
此时就可以实现按钮和input的切换了
input失焦实现input和按钮切换标签显示inputValue值
表单失焦事件
P41、删除销售属性和属性值的操作
删除属性值
v-for的时候传入index 让属性值的数组删除自身
删除销售属性
使用作用域插槽 传入$index $index表示的是 表格的销售属性列表的索引
三级联动的可操作性
给子组件传值来控制
P42、完成修改spu的保存操作
此时数据全部获取到了 只有照片墙的数据收集到的不再spu.spuImageList数组里面 而是在自定义响应式数据spuImageList字段里面
处理一下参数 返回的数据有imgName和imgUrl字段 是需要发送给服务器的 但是新增的没有imgName和imgUrl字段 只有name和url字段 处理一下参数
写接口
根据有没有id来选择是修改还是添加
保存按钮的点击事件
整理参数
系统数据不能修改 res返回成功之后 让页面显示变量为0的页面
但是保存之后数据不更新 提示父组件再次获取数据来进行展示
传入参数 停留到当前页
P43、完成添加spu按钮的操作
在保存完毕之后需要把数据清除
使用
//清空数据
//_data:全部的响应式数据
//$options是配置对象
//$options.data()执行响应式数据data函数 执行结果 获取到的是空的 返回的是起始状态
把空对象辅助给响应式数据 实现数据的清除
Object.assign(this._data,this.$options.data())
点击添加的时候需要发两个请求
获取品牌列表的数据和销售属性的数据
父组件直接调用子组件的方法
这时候点击添加的时候只有两个下拉框有数据
添加和修改的参数不同是判断你有没有id 这里的id使用的是category3id的值 这个值在添加的时候传入子组件
现在书籍全部可以收集到了 但是如果是修改按钮 显示当前页 如果是添加按键 显示在第一页 这里需要再次传入数据
不止传入scene 还传入flag 有id是修改 没有id是添加
父组件来获取到flag数据判断保存完之后停留在第几页 不写参数默认第一页
子组件的取消按钮需要改写形式 不能只传入0
不然会出现点击取消参数错误 不能正确切换的业务
取消按钮的业务逻辑抽取为一个函数
P44、删除spu的操作
点击删除 添加pop 删除整行
接口
给delete按钮添加事件 传入row
把点击按钮的事件传递到pop确定的时候才做
传参数 发请求
确定最后传入的page参数
P45、完成SKU静态组件
给添加点击事件 切换场景为2
sku静态组件
<template> <div> <el-form ref="form" label-width="80px"> <el-form-item label="SPU名称"> 海绵宝宝 </el-form-item> <el-form-item label="SKU名称"> <el-input placeholder="SKU名称"></el-input> </el-form-item> <el-form-item label="价格(元)"> <el-input placeholder="价格(元)"></el-input> </el-form-item> <el-form-item label="重量(千克)"> <el-input placeholder="重量(千克)"></el-input> </el-form-item> <el-form-item label="规格描述"> <el-input type="textarea" placeholder="规格描述" rows="4"></el-input> </el-form-item> <el-form-item label="平台属性"> <el-form :inline="true" label-width="80px"> <el-form-item label="屏幕属性"> <el-select placeholder="请选择" value=""> <el-option label="区域一" value="shanghai"></el-option> <el-option label="区域二" value="beijing"></el-option> </el-select> </el-form-item> </el-form> </el-form-item> <el-form-item label="销售属性"> <el-form :inline="true" label-width="80px"> <el-form-item label="颜色"> <el-select placeholder="请选择" value=""> <el-option label="区域一" value="shanghai"></el-option> <el-option label="区域二" value="beijing"></el-option> </el-select> </el-form-item> </el-form> </el-form-item> <el-form-item label="图片列表"> <el-table border style="width: 100%"> <el-table-column type="selection" prop="date" label="日期" width="80" align="center" > </el-table-column> <el-table-column prop="name" label="图片" width="180"> </el-table-column> <el-table-column prop="address" label="名称"> </el-table-column> <el-table-column prop="address" label="操作"> <el-button type="primary">设为默认</el-button> </el-table-column> </el-table> </el-form-item> <el-form-item> <el-button type="primary">保存</el-button> <el-button>取消</el-button> </el-form-item> </el-form> </div> </template>
P46、获取SKUform数据
在点击按钮跳转页面内的时候需要发三个请求 获取数据
分别是获取图片的数据
获取销售属性的数据
获取平台属性的数据来进行展示、
给子组件写入ref 直接点击按钮的时候调用子组件的方法即可
写接口
需要4个参数 分别是id category1id category2id category3id
这些参数父组件都有的 调用子组件方法的时候直接传过去
数据来源:menus组件 mounted的时候获取一级菜单的数据 三级菜单选择的时候收集到的是选择的id 这个就是category1id 根据category1id来获取 二级菜单的数据 二级菜单选择的时候收集了category2id,根据category2id收集到三级菜单的数据 三级菜单选择收集category3id 并且在获取菜单的时候 把数据通过自定义事件传给父组件使用 父组件通过category3id来控制分页器以及把数据给spuform组件使用
父组件调用子组件的方法 传四个参数
子组件接收四个参数 为发请求做准备
发请求 存储数据
数据全部获取到
P47、展示SKU和收集SKU的数据
保存的接口需要的参数
//收集sku数据的字段 skuInfo: { //第一类收集的数据:父组件给的数据 category3Id: 0, spuId: 0, tmId: 0, //第二类:需要通过数据双向绑定v-model收集 skuName: "", price: 0, weight: "", skuDesc: "", //第三类:需要自己书写代码 //默认图片 skuDefaultImg: "", //收集图片的字段 skuImageList: [ // { // id: 0, // imgName: "string", // imgUrl: "string", // isDefault: "string", // skuId: 0, // spuImgId: 0, // }, ], //平台属性 skuAttrValueList: [ // { // attrId: 0, // valueId: 0, // }, ], //销售属性 skuSaleAttrValueList: [ // { // id: 0, // saleAttrId: 0, // saleAttrName: "string", // saleAttrValueId: 0, // saleAttrValueName: "string", // skuId: 0, // spuId: 0, // }, ], },
整理父亲给的参数 直接把row拿过来进行拷贝
使用数据:
1.收集简单的表单数据 v-model
这样的输入框需要加入type=number
2.复杂数据收集
数据从服务器返回了 需要渲染之后进行收集
2.1遍历平台属性
2.2平台属性和属性值收集
收集的字段只有属性的id和属性值的id 暂时使用末班字符串收集到属性值的对象里面 后续进行处理
需要收集的数据
收集的方式
通过options的value值收集属性的idattr.id和属性值的id option.id
收集到v-model的attr的一个没有定义的属性上面 后续进行处理
此时两个id都收集到了
进行销售属性的展示与收集
销售属性和上面类似 select的v-model收集options的value值
value值收集两个id v-model绑定一个skuattrList的每一项的自定义属性上面
也是收集两个id
P48、添加SKU图片列表展示和数据收集
静态展示图片
作用域插槽 data绑定数据
数据展示完毕 开始收集数据
收集复选框选中的图片的信息
element-ui table有内置事件 是选择复选框的回调 返回的是已经选中的内容的数组
@selection-change=“handleSelectionChange” 选中事件 有一个参数 这个参数就是选中内容
但是目前收集到的数据有问题 缺少内容 缺少isDefault字段
但是目前先保存一下
在图片数据回来的时候先给他加上字段 默认为0
点击默认按钮的时候进行排他
进行默认和设为 默认的v-if事件
最后把默认图片数据收集一下 收集到skuDefaultImg的字段
现在的图片字段也都完整了
P49、完成添加sku保存的业务
1.写接口
取消按钮的回调
变量变为0 通知父亲切换场景
父组件绑定自定义事件
清除数据
父组件接收
2.整理参数
整理平台属性参数
保存按钮的回调
再加入销售属性的值的id的抽取
优化写法:
const {attrInfoList,skuInfo,spuSaleAttrList,imageList} = this; //整理平台属的数据 skuInfo.skuAttrValueList = attrInfoList.reduce((prev,item)=>{ if(item.attrIdAndValueId){ const [attrId,valueId] = item.attrIdAndValueId.split(":"); prev.push({attrId,valueId}); } return prev; },[]); //整理销售属性 skuInfo.skuSaleAttrValueList = spuSaleAttrList.reduce((prev,item)=>{ if(item.attrIdAndValueId){ const [saleAttrId,saleAttrValueId] = item.attrIdAndValueId.split(':'); prev.push({saleAttrId,saleAttrValueId}); } return prev; },[]);
暂时不解决
3.发请求
这里对数据进行map遍历 把有用的参数进行赋值操作 最后返回一个新的数组
切换场景 显示message
P50、SKU列表的展示
点击table这个按钮的时候 会有table来展示之前添加的sku的列表
写接口
点击事件
准备初始值
点击按钮 出现表格
发请求
使用spu的数据来展示对话框的title
再次准备初始化的值来存储请求接受过来的sku的值
请求成功 存储数据 来进行表格的展示
table的展示
P51、loading效果
给table 添加v-loding指令 值为loading 这个值什么都可以只要是布尔值就行
初始化loading值 为true
i获取到数据的时候loading消失
出现问题 loading效果是一次性的 而且在点击下一次的时候 数据没有回来的时候会回显上一次的表单
如何解决?
关闭对话框的时候实现数据的清除 把loading值变为true
:before-close 属性 为一个函数
相应回调
P52、sku模块分析和分页功能
完成sku静态
<template> <div> <el-table style="width: 100%" border> <el-table-column type="index" label="序号" align="center" width="80"> </el-table-column> <el-table-column prop="name" label="名称" width="180"> </el-table-column> <el-table-column prop="address" label="描述"> </el-table-column> <el-table-column label="默认图片" width="80"> <template slot-scope="{row,$idnex}"> <img src="" alt=""> </template> </el-table-column> <el-table-column prop="name" label="重量(KG)" width="180"> </el-table-column> <el-table-column prop="address" label="价格(元)" width="80"> </el-table-column> <el-table-column prop="address" label="操作"> <template slot-scope="{row,$index}"> <el-button icon="el-icon-download" type="success"></el-button> <el-button icon="el-icon-edit" type="primary"></el-button> <el-button icon="el-icon-info" type="info"></el-button> <el-button icon="el-icon-delete" type="danger"></el-button> </template> </el-table-column> </el-table> <!-- @size-change="handleSizeChange" @current-change="handleCurrentChange" --> <el-pagination style="text-align: center;margin-top: 20px 0;" :current-page="1" :page-sizes="[3, 5, 10]" :page-size="5" layout=" prev, pager, next, jumper,->,sizes,total" :total="30"> </el-pagination> </div> </template>
获取数据
写接口
初始化数据来保存数据
mounted执行methods的函数
渲染table
分页器的回调:
P53、SKU上架下架功能
records数组里面哪有一个字段 isSale控制上架和下架功能 1为上架 0为下架
控制两个按钮的显示和隐藏
上架下架功能 分别给上架按钮和下架按钮添加事件 发请求
点击第二个按钮的时候弹出灰色的正在开发中的按钮
P54、SKU查看详情业务
从右往左弹出抽屉的效果
发请求 得到数据 抽屉展示
初始化数据 根据数据类型
按钮添加事件
初始化数据赋值
数据格式
使用抽屉
布局:
24个为一栏 可以找到类名修改每个内容的样式
轮播图
<el-drawer :visible.sync="drawer" size="50%" :show-close='false'> <!-- 使用栅格系统的布局 --> <el-row> <el-col :span="6">名称</el-col> <el-col :span="18">{{skuInfo.skuName}}</el-col> </el-row> <el-row> <el-col :span="6">描述</el-col> <el-col :span="18">{{skuInfo.skuDesc}}</el-col> </el-row> <el-row> <el-col :span="6">价格</el-col> <el-col :span="18">{{skuInfo.price}}元</el-col> </el-row> <el-row> <el-col :span="6">平台属性</el-col> <el-col :span="18"> <el-tag type="success" v-for="item in skuInfo.skuAttrValueList" style="margin-right:10px" :key="item.id">{{item.attrId}}--{{item.valueId}}</el-tag> </el-col> </el-row> <el-row> <el-col :span="6">商品图片</el-col> <el-col :span="18"> <el-carousel height="300px" style="width:300px;margin: 0 auto;" > <el-carousel-item v-for="item in skuInfo.skuImageList" :key="item.id"> <img :src="item.imgUrl" alt="" style="width:300px;height:300px"> </el-carousel-item> </el-carousel> </el-col> </el-row> </el-drawer>
尝试修改轮播图小点点的样式
在style样式为scpped内书写不生效 没有这个属性的会生效
P55、深度选择器
scoped 什么用
总体来说就是当前的样式只在当前组件内生效
但是加入scoped也是可以影响到子组件的样式的 只有一种情况 就是style里面写的样式 刚好是子组件的最外层标签 name会影响到子组件的样式
scoped的原理是给当前子组件全部加入自定义属性 加入scoped之后就会加入自定义属性data-v-xxxx 只要组件加入scoped之后 就会有自己独特的自定义属性 并且当前组件的全部子组件全部添加这个自定义属性 会在当前页面影响子组件 但是如果子组件加入了scoped 也有自己的自定义属性 name就不会影响到了 子组件内部的组件只会有子组件的自定义属性 并没有父组件的自定义属性 所以不生效
而css写的是属性选择器
标签【自定义属性】
如果我加入scoped 还想进行对子组价内的控制
使用深度选择器
原生css >>>
less /deep/
scss ::
加在标签前面 这样组件内的所有H3标签都会生效,不管是不是加入了scoped
P56、数据可视化简介
完成首页
庞大数据通过图形图标来展示 方便观看
excel xmind等等
基础 canvas svg webgl html
本项目使用echarts
P57、canvas绘制线段
H5新增标签canvas
<canvas width="500" height="300"></canvas> <script> let canvas = document.querySelector('canvas') //调用getContext方法 传入2d 获取毛笔 let ctx = canvas.getContext('2d') //moveTo 起点 ctx.moveTo(100, 100) //lineTo其他点设置 可以设置多个 ctx.lineTo(100, 200) ctx.lineTo(200, 100) //fillStyle 设置图形填充颜色 ctx.fillStyle = 'red' //fill 执行fill 填充颜色才会生效 ctx.fill() //strokeStyle 设置线段的颜色 ctx.strokeStyle = 'purple' //lineWidth 设置线段的宽度 ctx.lineWidth = '20' //closePath 设置起点和终点连接在一起 ctx.closePath() //stroke 执行绘图方法 ctx.stroke() </script>
canvas画布是HTML5新增的特性 双闭合标签
canvas 的默认宽高为300*150
浏览器解析canvas为默认是一张图片 可以另存为
给canvas添加子节点没有意义
给canvas添加子文字没有意义
想操作canvas显示图形和文字 都需要使用js来完成
canvas的宽高使用属性的width和height属性来添加 不能使用style样式去改变宽高 坐标会出问题的
别的没有问题
P58、canvas绘制矩形
<canvas width="500" height="500"></canvas> <script> let canvas = document.querySelector('canvas') let ctx = canvas.getContext('2d') //1.绘制矩形 参数为x y w h 这个方法没有办法填充颜色 ctx.strokeRect(100, 200, 100, 200) //填充颜色 ctx.fillStyle = 'skyblue' //填充 ctx.fill() //2.填充矩形 参数为x y w h 这个方法可以在填充矩形之前设置填充颜色 ctx.fillRect(300, 200, 100, 200) </script>
P59、canvas绘制圆形
前置条件
度和弧度的转换
1度=π/180≈0.01745弧度,1弧度=180/π≈57.3度。
ctx.beginPath() 开始
ctx.arc(100, 100, 50, 0, 0.1, true) 配置
ctx.stroke() 结束
<canvas width="500" height="500"></canvas> </body> <script> let canvas = document.querySelector('canvas') let ctx = canvas.getContext('2d') //开始绘制圆形提示 ctx.beginPath() //圆形参数 x位置 y位置 r半径 开始的弧度 结束的弧度 是否逆时针绘制 //弧度 2*PI*ROW = 360° 1row = 180°/PI ctx.arc(100, 100, 50, 0, 2 * Math.PI, true) //开始绘制 ctx.stroke() ctx.beginPath() ctx.arc(100, 100, 50, 0, 0.1, true) ctx.stroke() </script>
这些图形都可以添加填充颜色和线段颜色
P60、canvas清除画布和绘制文字
<canvas width="500" height="500"></canvas> <script> let canvas = document.querySelector('canvas') let ctx = canvas.getContext('2d') //填充矩形 ctx.fillRect(100, 200, 100, 200) //清除部分画布 和矩形的参数一样 清除的区域也是矩形 ctx.clearRect(0, 0, 50, 100) //清除全部画布 //ctx.clearRect(0, 0, 500, 500) //设置文字大小 ctx.font = "20px 微软雅黑" //设置文字颜色 ctx.fillStyle = 'red' //绘制文字 文字内容 x y ctx.fillText('数据可视化', 50, 20) </script>
P61、绘制柱状图
后续补 计算太麻烦
P62、SVG的基本使用
SVG是一张局域XML的图像文件格式 可以缩放的矢量图
矢量图:放大不失真的图 会对IE有兼容问题
线段
<svg width="500" height="500"> <!-- x1 属性在 x 轴定义线条的开始 y1 属性在 y 轴定义线条的开始 x2 属性在 x 轴定义线条的结束 y2 属性在 y 轴定义线条的结束 --> <line x1="0" y1="0" x2="300" y2="300" style="stroke:rgb(99,99,99);stroke-width:2"/> </svg>
折线
<svg width="500" height="500"> <polyline points="0,0 0,20 20,20 20,40 40,40 40,60" style="fill:white;stroke:red;stroke-width:2"/> </svg>
矩形
<svg width="500" height="500"> <!-- rect 元素的 width 和 height 属性可定义矩形的高度和宽度 style 属性用来定义 CSS 属性 CSS 的 fill 属性定义矩形的填充颜色(rgb 值、颜色名或者十六进制值) CSS 的 stroke-width 属性定义矩形边框的宽度 CSS 的 stroke 属性定义矩形边框的颜色 --> <rect width="300" height="100"style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)"/> </svg>
圆
<svg width="500" height="500"> <!-- cx 和 cy 属性定义圆点的 x 和 y 坐标。如果省略 cx 和 cy,圆的中心会被设置为 (0, 0) r 属性定义圆的半径。 fill:边框颜色 --> <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/> </svg>
椭圆
<svg width="500" height="500"> <!-- cx 属性定义圆点的 x 坐标 椭圆 cy 属性定义圆点的 y 坐标 rx 属性定义水平半径 ry 属性定义垂直半径 --> <ellipse cx="300" cy="150" rx="200" ry="80" style="fill:rgb(200,100,50); stroke:rgb(0,0,100);stroke-width:2"/> </svg>
P63、echarts基本使用
PC 移动端都可以用
做一个柱状图
1.引包
2.准备有宽高的容器
- echarts.init 方法初始化一个 echarts 实例
- 传入setOption 配置对象
<!-- 1.引包 --> <script src="./echarts.min.js"></script> <style> * { margin: 0; padding: 0; } div { width: 800px; height: 500px; } </style> </head> <body> <!-- 2.准备有宽高的容器 --> <div></div> <!-- 3.创建echarts实例 --> <script> let div = document.querySelector('div') let myChart = echarts.init(div) //4.使用setOption方法传入配置对象 const option = { //标题数据 title: { text: 'ECharts 入门示例' }, //x轴 xAxis: { data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'] }, //y轴 yAxis: { show: true }, //图标类型 series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] } myChart.setOption(option); </script>
P64、多个容器展示多个图表
以两个为例
1.引包
2.创建两个宽高容器
3.创建两个echarts实例
4.传入两个配置对象 各传各的 就相当于搞了两个图标而已
<script src="./echarts.min.js"></script> <style> .box1 { width: 500px; height: 500px; border: 1px solid black; } .box2 { width: 500px; height: 500px; border: 1px solid black; } </style> </head> <body> <div class="box1"></div> <div class="box2"></div> <script> let dom1 = document.querySelector('.box1') let dom2 = document.querySelector('.box2') let Mychart1 = echarts.init(dom1) let Mychart2 = echarts.init(dom2) const option1 = { title: { text: 'ECharts 入门示例' }, tooltip: {}, legend: { data: ['销量'] }, xAxis: { data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] } const option2 = { title: { text: 'ECharts 入门示例' }, tooltip: {}, legend: { data: ['销量'] }, xAxis: { data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'] }, yAxis: { show: true }, series: [{ name: '销量', type: 'pie', data: [{ value: 335, name: '直接访问' }, { value: 234, name: '联盟广告' }, { value: 1548, name: '搜索引擎' }], //饼图半径 radius: '50%' }] } Mychart1.setOption(option1) Mychart2.setOption(option2) </script>
P65、一个容器显示多个图表
主要是配置对象的series字段
//图标类型 series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] },{ name: '销量', type: 'line', data: [5, 20, 36, 10, 10, 20] },{ name: '销量', type: 'pie', data: [5, 20, 36, 10, 10, 20] }] } <style> .box1 { width: 500px; height: 800px; border: 1px solid black; } </style> </head> <body> <div class="box1"></div> <div class="box2"></div> <script> let dom1 = document.querySelector('.box1') let Mychart1 = echarts.init(dom1) const option1 = { title: { text: 'ECharts 入门示例' }, tooltip: {}, legend: { data: ['销量'] }, xAxis: { data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }, { name: '销量', type: 'pie', data: [{ value: 335, name: '直接访问' }, { value: 234, name: '联盟广告' }, { value: 1548, name: '搜索引擎' }], //饼图半径 radius: '50%', //位置 left: 10, top: 20 }] } Mychart1.setOption(option1) </script>
如果里面有多个对象 多个type 就会在一个容器内显示多个图表
在series对象内各自设置各自的位置什么的
如果数饼状图 需要的数据可能是两个{name:11,value:值的显示}
查看文档
P66、echarts中数据集dataSet的使用
定义一个二维数组 来决定图表的数据 data【【】】
所有的series配置对象的data全部去掉 只需要设置一个二维数组 给实例添加配置对象为dataset:data
每个单独的配置需要加入source字段 设置显示的数组的索引位置
<script src="./echarts.min.js"></script> <style> .box1 { width: 500px; height: 800px; border: 1px solid black; } </style> </head> <body> <div class="box1"></div> <div class="box2"></div> <script> let dom1 = document.querySelector('.box1') let Mychart1 = echarts.init(dom1) let data = [ ['衬衫', 5, '直接访问', 335, 120], ['羊毛衫', 15, '联盟广告', 235, 20], ['雪纺衫', 5, '搜索引擎', 135, 150], ['裤子', 25, '联盟广告', 435, 190], ['袜子', 15, '直接访问', 435, 190] ] const option1 = { //数据集 dataset: data, title: { text: 'ECharts 入门示例' }, xAxis: { data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'] }, yAxis: {}, series: [{ name: '销量', type: 'bar', encode: { //x: [3, 1, 5], // 表示维度 3、1、5 映射到 x 轴。 // x: 0, y: 1, // 表示维度 2 映射到 y 轴。 } }, { name: '销量', type: 'pie', encode: { //饼图的维度 itemName显示的文字 value显示文字的值 itemName: 2, value: 3 }, //饼图半径 radius: '50%', //饼图的宽高 width: 150, height: 150, //位置 left: 10, top: 20 }, { type: 'line', encode: { y: 4, // 表示维度 3 映射到 y 轴。 } }] } Mychart1.setOption(option1)
P67、echarts内置组件的使用
下图圈住的全部都是组件 其中x–y轴也是组件
都可以进行相应的配置
<script src="./echarts.min.js"></script> <style> * { margin: 0; padding: 0; } .box { width: 800px; height: 400px; } </style> </head> <body> <div class="box"></div> <script> let dom = document.querySelector('.box') let mycharts = echarts.init(dom) mycharts.setOption({ //x轴 xAxis: { data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, //y轴 yAxis: {}, //图形配置 series: [{ //柱状图 //name属性配合legend使用 name: '柱状图', type: 'bar', data: [23, 24, 18, 25, 27, 28, 25] }, { //柱状图 name: '折线图', type: 'line', data: [23, 24, 18, 25, 27, 28, 25] }, ], //tooltip提示组件 tooltip: { show: true, textStyle: { //提示框文字的颜色 color: 'red' } }, //legend系列显示组件 legend: { data: ['柱状图', '折线图'] }, //toolbox 工具栏展示组件 toolbox: { show: true, //这些位置可以随意变化 展示IDE位置也会不同 feature: { //缩放 dataZoom: { yAxisIndex: "none" }, //还原 dataView: { readOnly: false }, //文字展示类型 magicType: { type: ["line", "bar"] }, //刷新 restore: {}, //下载 saveAsImage: {} } }, //最下面的区域这哪是组件 dataZoom: {}, //布局 grid: { //距离left的位置 给了固定宽高不会实现响应式 left: 30, right: 0, top: 10 } } ) </script>
P68、echarts坐标体系
一个坐标系的散点图
<script src="./echarts.min.js"></script> <style> * { margin: 0; padding: 0; } .box { width: 800px; height: 400px; } </style> </head> <body> <div class="box"></div> <script> let dom = document.querySelector('.box') let mycharts = echarts.init(dom) mycharts.setOption({ //x轴 xAxis: { //让散点图的点均匀的显示 type: 'category' }, //y轴 yAxis: {}, //图形配置 series: [{ //散点图 name: '散点图', type: 'scatter', //散点图的数据是二维数组 data: [ [10, 10], [20, 15], [20, 32], [15, 20] ] }] } ) </script>
双坐标系
yAxis 从对象变为数组 数组里面两个对象
<script src="./echarts.min.js"></script> <style> * { margin: 0; padding: 0; } .box { width: 800px; height: 400px; } </style> </head> <body> <div class="box"></div> <script> let dom = document.querySelector('.box') let mycharts = echarts.init(dom) mycharts.setOption({ //x轴 xAxis: { }, //y轴 成为数组 //yAxis: {}, yAxis: [{ //展示刻度 axisTick: { show: true }, //展示y轴的线 axisLine: { show: true } }, { //展示刻度 axisTick: { show: true }, //展示y轴的线 axisLine: { show: true } }], //图形配置 series: [{ type: 'line', data: [10, 20, 60, 30], //规范使用那个y轴 索引值 yAxisIndex: 0 }, { type: 'bar', data: [20, 32, 15, 42], yAxisIndex: 1 }] } ) </script>
多坐标系
yAxis 从对象变为数组 数组里面多个对象
P69、Home首页Card静态组件
头部完成
1.在首页组件dashboard组件 创建card组件 这里书写头部
头部的每一个卡片的具体显示内容由子组件Detail组件来展示
2.组件内容
dashboard:
card:
detail:
目前展示:
使用具名插槽来展示具体的内容
浏览器如何使用取色器
1.找到color的标签 点击后面的颜色就可以找到取色器
具名插槽:
子:< slot name=“11”
父:<template v-slot:11
button template>
1/4处 title字段的显示 采用props来展示
2/4处 content字段的显示 采用props来展示
3/4处 具名插槽
4/4处 具名插槽
子组件:
父组件:
PS:此处如果传入的字段不是data里面的或者script里面的 父传子不需要加入:title来传
依次改写其他四个card
P70、折线图完成
在第二个card里面的第三个部分 插槽内容直接写入这个组件就行
1.引包
下载依赖
npm i echarts --save
2.准备容器
在准备一个组件 在插槽区域直接显示组件就行
3.初始化实例
在mounted生命周期进行获取节点
<template> <div> <!-- 准备容器 --> <div class="line" ref="dom"> </div> </div> </template> <script> //引包 import * as echarts from 'echarts'; export default { mounted(){ //实例化 let Mycharts = echarts.init(this.$refs.dom) Mycharts.setOption({ xAxis: { show:false, //均匀分布 type:'category' }, yAxis: { show:false }, series: [ { data: [10, 22, 28, 23, 19,26,35,18,24], type: 'line', //曲线平滑 smooth: true, lineStyle:{ //线条颜色 color:'purple', }, itemStyle:{ //拐点消失 opacity:0 }, //填充颜色 areaStyle:{ color: { type: 'linear', x: 0, y: 0, x2: 0, y2: 1, colorStops: [{ offset: 0, color: 'purple' // 0% 处的颜色 }, { offset: 1, color: 'white' // 100% 处的颜色 }], global: false // 缺省为 false } } } ], //布局 grid:{ left:-15, top:0, bottom:0, right:-10 }, //tooltip提示组件 tooltip: { show: true, textStyle: { //提示框文字的颜色 color: 'red' } }, }) } } </script> <style scoped> .line{ width: 100%; height: 50px; } </style>
P71、柱状图和进度条完成
柱状图
和折线图一样 只不过类型选择bar就行
进度条完成
这个进度条其实就是柱状图倒下之后显示的样子
Mycharts.setOption({ xAxis: { show:false, //设置x轴的最大值和最小值 min:0, max:100 }, yAxis: { show:false, //均匀分布 实现躺倒的效果 type:'category' }, series: [ { data: [78], type: 'bar', //柱状图的宽度 barWidth:10, //柱状图的颜色 color:'yellowgreen', //背景颜色设置 showBackground:true, //背景颜色配置 backgroundStyle:{ color:"#eee" }, //文本 label:{ show:true, //展示的文字从文字变成| formatter:"|", //让|显示在右边 position:'right' } } ], //布局 grid:{ left:-25, top:0, bottom:0, right:-10 }, //tooltip提示组件 tooltip: { show: true, textStyle: { //提示框文字的颜色 color: 'red' } }, }) }
P72、sale静态组件(上)
先注册和使用sale组件
书写sale静态样式
<template> <div> <el-card style="margin:20px 0"> <div class="sale"> <!-- @tab-click="handleClick" --> <!-- 左侧区域 --> <div class="left"> <el-tabs v-model="activeName" class="tabs"> <el-tab-pane label="销售额" name="销售额"> </el-tab-pane> <el-tab-pane label="访问量" name="访问量"> <el-row> <el-col :span="16">11</el-col> <el-col :span="8">1122</el-col> </el-row> </el-tab-pane> </el-tabs> 下面的内容写在这里就不用进行切换了 换显示的文字就行 <el-row> <el-col :span="16">1</el-col> <el-col :span="8">11</el-col> </el-row> </div> <!-- 右侧区域 --> <div class="right"> <span>今日</span> <span>本周</span> <span>本月</span> <span>本年</span> <!-- 时间选择器 --> <!-- v-model="value1" --> <el-date-picker style="margin:0 20px" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" size="mini"> </el-date-picker> </div> </div> </el-card> </div> </template> <script> export default { data(){ return{ activeName:'销售额' } } } </script> <style scoped> .sale{ position: relative; display: flex; justify-content: space-between; } .right span{ font-size: 14px; margin: 0 10px; margin-top: 5px; } .right{ position: absolute; right: 0; height: 30px; } .left{ width: 100%; } </style>
P73、sale静态组件(中)
柱状图完成
在tab组件的内容区域进行柱状图还有门店铺销售排名的操作
只有一个柱状图和ul
柱状图从echarts里面的示例里面去找
P74、sale静态组件完毕
访问量和销售量的切换
我们点击tab的时候就可以获取到activeName值是sale销售还是vister访问
就可以通过计算属性计算出一个值来进行具体文字的显示 右边区域好解决 直接进行mustache语法就行 那么左边的柱状图的title怎么变
解决 给MyCharts初始为null 在mounted 生命周期进行赋值操作 然后使用watch来对计算属性的值进行监听 如果发生改变 那么进行title字段的改变
tab切换收集两个值 sale和vister
此时默认显示显示的数值是sale
由计算属性计算出值来title
把MyCharts也设置为null
在mounted执行的时候把echarts实例赋值给data数据
再次监听title的变化 如果发生改变 就把配置对象的title字段重新设置一下
PS:此时的mounted函数必须要在watch之前 不然会报错
处理时间收集器
时间收集器v-model绑定一个数组 value-format 是编辑的格式
如果选择好之后就会显示这样的数组
给span添加点击事件 分别给数组的第一个和第二个值填入对应的值
【start,end】
把date赋值过去 就会出现日期文字 自己选择日期的操作了
P75、observe静态组件
最终实现效果
P76、动态展示mock数据
1.mock的文件放到mock文件夹下面
在mock文件里面创建home.js 大概模板使用table.js
改写一下home.js
const data = require('./data.json') module.exports = [{ url: '/home/list', type: 'get', response: config => { const items = data.items return { code: 20000, data } } }]
在mock文件下的index.js进行引入
此时获取不到数据 因为需要在vue.config.js文件中配置mock
此处可以删除或者写成after 不然登录不了
mock/mock-serve.js改写配置
.env.development增加配置
utils文件下复制一个request.js文件 路径配置为mock-api
重启项目
在store/models文件下创建home.js文件
在index.js合并入大仓库
home.js文件
import MOCKrequest from '@/utils/MOCKrequest.js' const state = { list: {} } const mutations = { GETDATA(state, list) { state.list = list } } const actions = { async getData({ commit }) { let res = await MOCKrequest.get('/home/list') if (res.code == 20000) { commit('GETDATA', res.data) } } } const getters = { } export default { state, mutations, actions, getters }
在dashboard首页的mounted生命周期来进行dispatch
这时仓库内的list就成为了mock的数据
使用数据
sale组件使用辅助函数来进行list数据的使用
1.引入辅助函数
2.挂载为计算属性
此时sale组件就获取到了list的数据
3.使用数据
把setOption的配置的datamounted里面为空
在watch里面进行title的监听
此时实现点击tab标题的时候实现切换柱状图的数据
但是在第一次进入的时候数据是空的 怎么办
监听vuexlist的数据 改变的时候进行重新赋值 组件一创建就会获取到vuex的数据 直接赋值为销售额的数据
其余数据依次进行展示 后续处理
P77、权限管理模块介绍
超级管理员 分配角色 角色权限
P78、权限管理模块的串讲
cv
复制一下 api 配置api
复制一下组件 配置路由
改写一下请求函数的导出方式
细细查看一下文件的业务
P79、菜单&按钮的权限
动态展示组件的本质就是根据权限来展示路由
怎么实现 我们在登录的时候会发请求 服务器会返回登陆者的权限信息 根据这些信息我们来进行判断权限
如何实现菜单的权限
1.登录页面实现的逻辑
登录按钮实现点击事件
这个事件是派发一个vuex任务 把登录的信息传入
vuex这个事件具体实现的逻辑
根据用户填入的用户名和密码返回taken信息 把token存了
然后根据存入的token获取页面
这里改写为把所有根据token返回的数据全部都存了
服务器的数据 name用户名 avatar用户头像 rotes:用户角色信息 routes:用户应该展示那些组件 buttons:按钮权限
此时在login组件把表单验证关掉
然后在角色管理添加一个角色和密码 就可以使用这个账号密码进行登录 可以发现展示的权限是不一样的 此时的账号是edit 111111
此时实现的问题可以多账号进行登录 但是展示的路由都是一样的 因为我们在路由配置的时候都是写死的 没办法进行分辨
解决 把路由分类
常量路由 异步路由 任意路由
这时没有改变下面的routes的配置 现在所有人进来都是首页 其他的没有了
我们需要用vuex存储的信息和这些路由对比 决定展示哪一个
给user下的vuex添加一个数组 这个数组准备放服务器反馈的routes数组和异步路由进行对比重合的数组
给根据token 获取用户信息的事件commit一个mutations 让resaultAsyncRouer这个值等于传入的值 只不过现在传入的值还没有进行计算
这个值 如何计算呢?
在vuex把刚刚配置的三个路由进行引入
异步路由和存储的routes数组进行过滤 然后和常量路由和任意路由进行合并之后出现新的路由配置
在刚刚commit传入的值设置为一个对象 这个对象两个参数 一个刚刚传入的异步路由 一个服务器获取到的routes数组 这个函数的返回值是一个新数组就行
书写这个函数 和actions这些配置同级
需要过滤
item的信息
此时实现的是能把以及路由过滤出去 name二级三级路由呢
解决 使用递归
const computedAsyncRouters = (sayncRoutes, routes) => { // console.log(sayncRoutes); // console.log(routes); return sayncRoutes.filter(item => { //服务器返回的信息字段里面没有我们配置的路由信息的name字段 那么return出去 if (routes.indexOf(item.name) != -1) { //递归 if (item.children && item.children.length) { item.children = computedAsyncRouters(item.children, routes) } return true } }) }
此时就可以知道展示那些异步路由
此时的 ressultAsyncRoutes:数组里面存储的就是和服务器返回的权限传的异步路由了
路由注册的最后计算 常量,异步,任意路由进行合并
准备变量 存储最后的路由信息
计算完异步路由直接进行数组的合并 concat
在vuex引入router 然后使用router.addRoutes来进行重新配置路由
此时路由已经根据权限配置完毕 但是页面展示的只有首页
因为这个模板取得数据不是从仓库 是从router里面取的常量路由
改写数据 从vuex里面拿
此时的权限业务逻辑完成
按钮权限 不同权限下面展示不同的按钮 或者按钮的可见性
1.06.02
解决bug 在品牌管理模块出现不了商品管理的菜单
在router配置的时候的name是Trademark
解决bug 在登录之后进行路由的跳转出现白屏
在permission.js修改代码
try { // get user info await store.dispatch('user/getInfo') //next() next({...to })