2 Star 8 Fork 3

老汤 / 数据可视化155

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

echarts使用步骤

  • 必须有一个具有宽高的div
  • 引入echarts.min.js
  • JS代码
    • 初始化echarts(写法固定)let 变量 = echarts.init(盒子)
    • 配置echarts图表(配置项决定了图表的样子) let 配置项 = {}
    • 根据配置项,创建图表(写法固定)变量.setOption(配置项)
<body>

  <!-- 准备一个具有宽高的盒子 -->
  <div style="width: 600px; height: 400px;"></div>

  <!-- 引入echarts -->
  <script src="./lib/echarts.min.js"></script>

  <script>
    // 1. 初始化echarts(写法固定)
    // let 变量 = echarts.init(盒子)
    let myChart = echarts.init(document.querySelector('div'))

    // 2. 配置echarts图表(配置项决定了图表的样子)
    // let 配置项 = {}
    let option = {
      xAxis: {
        type: 'category',
        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
      },
      yAxis: {
        type: 'value'
      },
      series: [
        {
          data: [150, 230, 224, 218, 135, 147, 260],
          type: 'line'
        }
      ]
    }

    // 3. 根据配置项,创建图表(写法固定)
    myChart.setOption(option) // setOption 第1个O是大写的

  </script>

</body>

echarts常用的配置项

image-20230430084452814

title - 标题

xAxis - X轴配置

yAxis - Y轴配置

series - 系列数据

  • 格式是 [{ 一个图形 }, { 一个图形 }, { 一个图形 }]

color - 颜色配置

  • 格式 ['red', 'green', 'blue']
  • 格式 ['red', 'green', '渐变色'] ----- 渐变色传送门

grid - 坐标轴区域的配置,比如配置距离顶部 100 像素

legend - 图例配置

  • 需要设置series中每一项的 name 属性才行。

tooltip - 鼠标移入提示

  • 默认是鼠标移入图形才能提示
  • 将 trigger: 'axis' 之后,鼠标输到轴上即可提示。
let option = {
  // 标题配置
  title: {
    text: '我的第1个图表', // 主标题文本
    left: 'center', // 主标题的位置
    textStyle: {
      color: 'red',
      // 要求 标题的字体大小是 24px 
      fontSize: 24
    },
  },
  // X轴配置
  xAxis: {
    type: 'category',
    data: ['星期一', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    axisLabel: {
      color: 'blue' // 坐标轴文字的颜色
    }
  },
  // Y轴配置
  yAxis: {
    type: 'value'
  },
  // 下面是构成图表的必须的配置,叫做系列数据
  series: [
    // 数组中的每一个小对象,就是一个图形
    {
      // data 构成图表的数据
      data: [150, 230, 224, 218, 135, 147, 260],
      // type 表示图表的类型:(line-折线)(bar-柱状图)(pie-饼图)(map-地图)
      type: 'line',
      name: '订单量'
    },
    {
      data: [250, 130, 124, 118, 235, 247, 160],
      type: 'line',
      name: '销售额'
    },
    {
      data: [50, 30, 24, 18, 35, 47, 60],
      type: 'bar',
      barWidth: '60%', // 控制柱子的宽度
      name: '纯收入'
    }
  ],
  // 颜色配置
  color: ['red', 'green', {
    type: 'linear',
    x: 0,
    y: 0,
    x2: 0,
    y2: 1,
    colorStops: [{
      offset: 0, color: 'red' // 0% 处的颜色
    }, {
      offset: 1, color: 'blue' // 100% 处的颜色
    }],
    global: false // 缺省为 false
  }],
  // 网格配置(坐标轴这个区域)
  grid: {
    top: 100 // 调整坐标轴区域的位置
  },
  // 图例(用于表达 每个图形的意义)
  // 需要series中,每项数据必须定义name名字
  legend: {
    top: 60
  },
  // 提示框组件
  tooltip: {
    // 提示的触发方式
    // 默认是 item,鼠标放到每一项上才能提示
    // 可选 axis ,鼠标放到轴上即可提示
    trigger: 'axis',
  }
}

折线图

写基础的步骤

// ------------------- 折线图 --------------------------------
function lineChart () {
  let myChart = echarts.init(document.querySelector('#line'))
  let option = {}
  myChart.setOption(option) // 第1个O是大写的
}
lineChart()

套用官方示例

官方示例代码如下:

let option = {
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [820, 932, 901, 934, 1290, 1330, 1320],
      type: 'line',
      smooth: true
    }
  ]
}

修改配置

  1. 增加标题(title)

    1. 标题文本(text):2022全学科薪资走势
    2. 距离顶部(top):15
    3. 距离左侧(left):10
    4. 文字大小(textStyle > fontSize):16
  2. X 轴(xAxis)

    1. 标签文字(data):['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
    2. 标签文字颜色(axisLabel > color):#999
    3. 轴线颜色(axisLine > lineStyle > color):#ccc
    4. 轴线类型(axisLine > lineStyle > type):点划线
  3. Y 轴(yAxis)

    1. Y 轴分割线类型((splitLine > lineStyle > type)):点划线
  4. 鼠标移入提示(tooltip)

    1. (trigger: 'axis')设置为鼠标移入轴线提示
  5. 网格(grid)

    1. 距离顶部:20%
  6. 颜色(color)

    1. 渐变颜色,参考链接:https://echarts.apache.org/zh/option.html#color
    2. 0%处的颜色:#499FEE
    3. 100%处的颜色:#5D75F0
  7. 系列数据(series)

    1. 数据:[9000, 12000, 15000, 13000, 10000, 18000, 14000, 10000, 12000, 13000, 15000, 19000]
    2. 平滑曲线
    3. 线条粗细:6
    4. 拐点空心圆:10
    5. 区域面积渐变:
      1. 0处颜色:#499FEE
      2. 0.8处颜色:rgba(255,255,255,0.2)
      3. 1处颜色:rgba(255,255,255,0)
      4. 渐变色设置参考https://echarts.apache.org/zh/option.html#color

饼图(右上角)

写基础的步骤

function classSalaryChart () {
  let myChart = echarts.init(document.querySelector('#salary'))
  let option = {}
  myChart.setOption(option) // 第1个O是大写的
}
classSalaryChart()

套用官方示例

传送门

修改配置

  1. 增加标题(title)

    1. 标题文本:班级薪资分布
    2. 距离顶部:15
    3. 距离左侧:10
    4. 文字大小:16
  2. 系列数据(series)

    1. 去掉了 avoidLabelOverlap 和 emphasis 两个配置
    2. 系列数据名 name:班级薪资分布
    3. 环形内外圈半径 radius:['50%', '64%']
    4. 每一项样式 itemStyle(不需要改):
      1. 边框颜色:#fff
      2. 边框大小:2
      3. 扇形内外圆角半径:10
    1. 文字标签 label(不需要改):不显示
    2. 视觉引导线 labelLine(不需要改):不显示
    3. 数据:
[
  { value: 1048, name: '1万以下' },
  { value: 235, name: '1万-2万' },
  { value: 580, name: '1.5万-2万' },
  { value: 484, name: '2万以上' }
]
  1. 图例(legend)

    1. 左右居中
    2. 距离部:6%
  2. 鼠标移入提示(tooltip)(不需要改)

    1. 鼠标移入每一项上提示
  3. 颜色(color)

    1. ['#FDA224', '#5097FF', '#3ABCFA', '#34D39A']

饼图(左下角)

写基础的步骤

function sexSalaryChart () {
  let myChart = echarts.init(document.querySelector('#gender'))
  let option = {}
  myChart.setOption(option)
}

sexSalaryChart()

复制上一个饼图并修改

复制之后

  • 删除 series中的 itemStyle
  • 删除 series中的 label
  • 删除 series中的 baleLine
  • 复制 series 中的一个小对象,并修改圆心点
    • center: ['50%', '30%'] center: ['50%', '70%']
  • 删除图例 legend

标题设置:

  • 一个标题,使用一个 对象 {} 表示
  • 多个标题,使用一个 数组 [{标题1}, {标题2}, {标题3}] 表示
title: [
  {
    text: '男女生薪资分布',
    top: 15,
    left: 10,
    textStyle: {
      fontSize: 16
    }
  },
  {
    text: '男生',
    top: '50%',
    left: '45%',
    textStyle: {
      fontSize: 12
    }
  },
  {
    text: '女生',
    top: '85%',
    left: '45%',
    textStyle: {
      fontSize: 12
    }
  }
],

地图

准备工作

要做地图,除了引入 echarts.min.js 之外,还需要地区的配置文件。

比如做中国地图,需要引入 china.js 才可以。

更多地图做法,参考群里的 7 分钟视频。

// ------------------- 地图 ----------------------------------
function mapChart () {
  let myChart = echarts.init(document.querySelector('#map'))
  let option = {
    // 从 0 开始,自己写配置
  }
  myChart.setOption(option)
}
mapChart()

配置

修改配置

  1. 标题(title)

    1. 标题文字:籍贯分布
    2. 距离顶部:10
    3. 距离左边:10
    4. 文字大小:16
  2. 系列数据(series)

    1. 系列数据名(name):籍贯分布
    2. 类型(type: 'map') -- 表示地图
    3. map: 'china' --- 表示使用中国地图(到这一步,就可以显示中国地图了)
    4. 通过 label 设置每个区域(每个省)的名字
      1. (show: true)显示省的名字
      2. (fontSize)文字大小:10
      3. (color)字体颜色:rgba(0,0,0,0.7)
    1. 通过 itemStyle 设置每个区域(每个省)默认的颜色
      1. borderColor 区域边界线(省界线)颜色:rgba(0, 0, 0, 0.2)
      2. areaColor 区域颜色:#E0FFFF
    1. 通过 emphasis 设置高亮状态(鼠标移入)的样式
      1. areaColor 区域颜色:#34D39A
      2. borderWidth 区域边框(省界线)大小:0
      3. shadowBlur 阴影模糊大小:20
      4. shadowOffsetX shadowOffsetY 阴影偏移:0
      5. shadowColor 阴影颜色:rgba(0, 0, 0, 0.5)
    1. 使用data设置每个省的数据
// 因为用地图表示每个省有几名同学
// 所以可以提前准备好数据
const mapData = [
  { name: '南海诸岛', value: 0 },
  { name: '北京', value: 3 },
  { name: '天津', value: 2 },
  { name: '上海', value: 4 },
  { name: '重庆', value: 1 },
  { name: '河北', value: 20 },
  { name: '河南', value: 23 },
  { name: '云南', value: 0 },
  { name: '辽宁', value: 15 },
  { name: '黑龙江', value: 12 },
  { name: '湖南', value: 2 },
  { name: '安徽', value: 5 },
  { name: '山东', value: 18 },
  { name: '新疆', value: 0 },
  { name: '江苏', value: 5 },
  { name: '浙江', value: 1 },
  { name: '江西', value: 4 },
  { name: '湖北', value: 3 },
  { name: '广西', value: 2 },
  { name: '甘肃', value: 9 },
  { name: '山西', value: 11 },
  { name: '内蒙古', value: 14 },
  { name: '陕西', value: 14 },
  { name: '吉林', value: 10 },
  { name: '福建', value: 0 },
  { name: '贵州', value: 0 },
  { name: '广东', value: 0 },
  { name: '青海', value: 3 },
  { name: '西藏', value: 0 },
  { name: '四川', value: 1 },
  { name: '宁夏', value: 1 },
  { name: '海南', value: 0 },
  { name: '台湾', value: 0 },
  { name: '香港', value: 0 },
  { name: '澳门', value: 0 }
]

​ 然后series中,通过 data 指定使用这些数据

series: [
  {
    type: 'map',
    ...
    ... 其他配置略
    data: mapData   // 指定数据
  }
]
  1. 鼠标移入提示(tooltip)

    1. 鼠标放到每个省的时候,进行提示
    2. 自定义提示的格式为:河北:20 位学员 这样的格式
    3. 提示框边框透明
    4. 提示框背景色:rgba(0,0,0,0.5)
    5. 文字颜色:#fff
  2. 视觉映射组件(visualMap)

    1. 视觉映射组件,根据每个区域数据的大小来修改每个区域的颜色
    2. 显示视觉映射组件
    3. max min 约定最大值20,最小值0
    4. text: [20, 0] 视觉映射组件开头和结尾文字也是 20和0
    5. 组件距离左边40,距离下边20
    6. inRange: { color: ['', ''] } 从小到大的颜色分别为:#fff 和 #0075F0

作业:柱状图要求

修改配置

网格(grid)

    1. 距离左边:70
    2. 距离顶部:30
    3. 距离右边:30
    4. 距离下边:50

X 轴(xAxis)

    1. 轴线颜色:#ccc
    2. 轴线类型:点划线
    3. 文字颜色:#999

Y 轴(yAxis)

    1. Y轴分割线:点划线

鼠标移入提示(tooltip)

    1. 鼠标移入柱子提示

系列数据(series)

    1. 因为有两个柱子,所以需要两份数据
series: [
  {
    data: [12200, 17932, 13901, 13934, 21290, 23300, 13300, 13320],
    type: 'bar',
    name: '期望薪资' // 这个数据的名字,可以在鼠标移入的提示上显示
  },
  {
    data: [22820, 19932, 16901, 15934, 31290, 13300, 14300, 18320],
    type: 'bar',
    name: '就业薪资' // 这个数据的名字,可以在鼠标移入的提示上显示
  }
]

颜色(color)

    1. 因为有两个柱子,所以颜色也使用数组,并且每一个柱子使用渐变色
    2. 第1个柱子:0处的颜色#34D39A,1处的颜色rgba(52,211,154,0.2)
    3. 第2个柱子:0处的颜色#499FEE,1处的颜色rgba(73,159,238,0.2)

作业:自己做一个自己家乡的地图(做市级地图,参考群里的视频)

创建并切换到login

image-20230430144425456

插件

val()

作用一:获取表单各项的值,语法: let data = val(表单)

作用二:修改的时候,可以做数据回填,语法: val(表单, 数据)

message

  • message.success('成功的提示')
  • message.error('失败的提示')
  • message.confirm('标题', '提示内容', 函数) ---- 删除学员的时候用

注册代码

// 注册业务:获取输入框的账号、密码,提交给接口即可;
// 如果有问题,则提示一下(比如账号已存在、比如账号太长了、.......)
// 如果注册成功,则跳转到登录页去登录

document.querySelector('#btn-login').addEventListener('click', function (e) {
  e.preventDefault()
  // 使用插件收集表单各项的值
  // let data = val(表单) // val() 函数就会把表单各项的值收集到(要求表单各项必须有name属性)
  let data = val(document.querySelector('form'))   // serialize(表单, { hash: true })
  // console.log(data) // {username: 'aaa', password: 'bbb'}
  // 简单的验证一下数据格式
  if (data.username.length < 2 || data.username.length > 30) {
    message.error('用户名长度应该是2~30位')
    return
  }
  if (data.password.length < 6 || data.password.length > 30) {
    message.error('密码长度应该是6~30位')
    return
  }
  // Ajax把数据提交给接口
  axios({
    method: 'POST',
    url: 'http://ajax-api.itheima.net/register',
    data: data
  }).then(result => {
    // 成功后提示
    message.success(result.data.message) // 提示注册成功
    // 清空输入框的值
    document.querySelector('form').reset() // 重置表单
    // 跳转到登录页
    setTimeout(() => {
      // 等一下,等提示隐藏了再跳转
      location.href = './login.html'
    }, 1500)
  }).catch(err => {
    // console.dir(err)
    message.error(err.response.data.message) // 提示账号已存在
  })
})

登录功能

因为登录的业务逻辑和注册差不多。

所以,复制上述注册的代码 到 login.html 中。

并修改以下内容:

  • 接口地址修改为: http://ajax-api.itheima.net/login
  • 登录成功后,跳转到:location.href = './index.html'

token的使用

image-20230430165815243

具体到代码:

  1. 登录成功之后,存储token
localStorage.setItem('token', result.data.data.token)
  1. 首页请求接口数据的时候,带请求头
// ====================================================================================
// 发送请求,获取接口数据,把数据渲染到页面中,把数据用到图表中
axios({
  url: 'http://ajax-api.itheima.net/dashboard',
  headers: {
    Authorization: localStorage.getItem('token')
  }
}).then(result => {
  console.log(result)
})

axios配置请求根路径和请求头

axios配置好请求根路径之后,后续所有的请求,都不用写请求根路径了。

配置语法:axios.defaults.baseURL = 'http://ajax-api.itheima.net'

只要有上述这行代码,后面所有的请求,都不用加 请求根路径了。

项目中,由于每个html文件,都引入了 common.js 的文件,所以,我们可以选择把 统一的配置,放到 common.js 中。

同理,也可以全局统一配置请求头,代码如下。

common.js 中的代码:

// 上面这个代码处理过度动画(默认加上不用管)
document.addEventListener('DOMContentLoaded', () => {
  setTimeout(() => {
    document.body.classList.add('sidenav-pinned')
    document.body.classList.add('ready')
  }, 200)
})

// 加入axios的配置
// 配置请求根路径
axios.defaults.baseURL = 'http://ajax-api.itheima.net'

// 配置请求头
axios.defaults.headers.common['Authorization'] = localStorage.getItem('token')

响应拦截器处理401错误

拦截器分为

  • 请求拦截器
  • 响应拦截器

参考地址:https://www.axios-http.cn/docs/interceptors

项目中,如果是token 的问题(不是忘记携带了,就是token过期了),接口都会响应 401 状态码。

所以,添加响应拦截器,判断响应状态码是否是401,如果是,则跳转到登录。

在common.js中,添加如下代码:

// 添加响应拦截器
axios.interceptors.response.use(
  function (response) {
    // 2xx 范围内的状态码都会触发该函数。成功进入这个函数
    // 对响应数据做点什么
    return response;
  },
  function (error) {
    // 超出 2xx 范围的状态码都会触发该函数。失败进入这个函数
    // 对响应错误做点什么
    // console.dir(error)
    if (error.response.status === 401) {
      // 说明 token 有问题了(不是忘记携带了,就是token过期了)
      location.href = './login.html'
    }
    return Promise.reject(error);
  }
);

首页数据处理

概览区处理

折线图数据处理

  • 原来 那次 调用函数,注释掉
  • 等接口响应数据之后,再调用函数,并且传递实参 lineChart(year)
  • lineChart 函数里面:
    • X轴数据: data: a.map(item => item.month)
    • series数据:data: a.map(item => item.salary)

饼图数据处理

  • 原来 那次 调用函数,注释掉
  • 等接口响应数据之后,再调用函数,并且传递实参
    • classSalaryChart(salaryData) -- 右上角饼图
    • sexSalaryChart(salaryData) -- 左下角
  • classSalaryChart(右上角函数)
    • series中, data: a.map(item => { // return { value: 20, name: '一万以下' } return { value: item.g_count + item.b_count, name: item.label } })
  • sexSalaryChart(左下角函数)
    • series中,data: a.map(item => { // return { value: 20, name: '一万以下' } return { value: item.g_count, name: item.label } })

柱状图数据处理

  • 原来 那次 调用函数,注释掉

  • 等接口响应数据之后,再调用函数,并且传递实参 groupSalaryChart(groupData)

  • 默认展示1组数据

    • X轴的人名 data: a[1].map(item => item.name)
    • series中的两组数据 a[1].map(item => item.hope_salary)a[1].map(item => item.salary)
  • 点击之后,做排他效果

  • 点击之后,设置对应组的数据,并重新创建图表

// 给柱状图上面的 8 个按钮,注册click事件
document.querySelector('#btns').addEventListener('click', function (e) {
  if (e.target.tagName === 'BUTTON') {
    // 排他效果
    document.querySelector('#btns .btn-blue').classList.remove('btn-blue')
    e.target.classList.add('btn-blue')
    // echarts更换图表数据的步骤【1. 更换图表中x轴、series数据   2. myChart.setOption(option)重新创建图表即可】
    // 获取组号
    let i = e.target.innerHTML.trim() // trim()是去掉字符串两边的空白
    // console.log(i) // 组号有了,每组的数据就是  a[i]
    // 换图表配置项中的数据
    option.xAxis.data = a[i].map(item => item.name)
    option.series[0].data = a[i].map(item => item.hope_salary)
    option.series[1].data = a[i].map(item => item.salary)

    myChart.setOption(option)
  }
})

地图数据处理

  • 原来 那次 调用函数,注释掉
  • 等接口响应数据之后,再调用函数,并且传递实参 mapChart(provinceData)
  • 函数中,在模板数据(mapData)之后,加入下面的代码即可
// 在模板数据、接口返回的数据 之后。融合两部分数据
mapData.forEach(item => {
  // 判断接口返回的数据有没有北京、河北的、内蒙古的
  let 结果 = a.find(v => {
    return v.name.includes(item.name)
  })
  // console.log(结果) 
  if (结果) {
    // item.value = 接口返回的value
    item.value = 结果.value
  }
})

合并,创建新分支

上述完成

  • 将当前 login 分支的代码都提交了 (git add . git commit -m 'xxxxx')
  • 切换到master分支 (git checkout master)
  • 合并login分支 (git merge login)

创建新分支,准备开发学生列表页

  • 创建新分支 (git branch student)
  • 切换到新分支 (git checkout student)

学生列表

添加学员

模态框的使用

模态框的使用:

let modal = new bootstrap.Modal(盒子)

// 让模态框显示
modal.show()

// 让模态框隐藏
modal.hide()

具体到我们的项目代码:

// --------------------------- 添加学员 -----------------------------------
// 模态框盒子 在 student.html 第 205~285 行
let addModal = new bootstrap.Modal(document.querySelector('#modal'))

// 点击 + 的时候,让模态框显示
document.querySelector('#openModal').addEventListener('click', function () {
  addModal.show() // 让模态框显示
})

// 点击模态框中的 确认 按钮
document.querySelector('#submit').addEventListener('click', function () {
  addModal.hide() // 让模态框隐藏
})

省市县联动

// --------------------------- 省市县联动 ---------------------------------
let sheng = '<option value="">--省份--</option>'
let shi = '<option value="">--城市--</option>'
let xian = '<option value="">--地区--</option>'

let province = document.querySelector('[name=province]') // 下拉框
let city = document.querySelector('[name=city]')
let area = document.querySelector('[name=area]')
// 获取省,并渲染
axios({
  url: '/api/province'
}).then(result => {
  // console.log(result)
  let newArr = result.data.data.map(item => `<option value="${item}">${item}</option>`)
  province.innerHTML = sheng + newArr.join('')
})
// 省切换的时候,获取市,并渲染
province.addEventListener('change', function () {
  // console.log(province.value)
  area.innerHTML = xian // 切换省的时候,重置区县
  axios({
    url: '/api/city',
    params: {
      pname: province.value
    }
  }).then(result => {
    let newArr = result.data.data.map(item => `<option value="${item}">${item}</option>`)
    city.innerHTML = shi + newArr.join('')
  })
})
// 市切换的时候,获取区县,并渲染
city.addEventListener('change', function () {
  axios({
    url: '/api/area',
    params: {
      pname: province.value,
      cname: city.value
    }
  }).then(result => {
    let newArr = result.data.data.map(item => `<option value="${item}">${item}</option>`)
    area.innerHTML = xian + newArr.join('')
  })
})

完成添加功能

// 点击模态框中的 确认 按钮
document.querySelector('#submit').addEventListener('click', function () {
  // 获取表单各项的值
  // let data = val(表单)
  let data = val(document.querySelector('#form'))
  // 检查是否是接口需要的数据
  // console.log(data)
  data.age = +data.age
  data.group = +data.group
  data.gender = +data.gender
  data.hope_salary = +data.hope_salary
  data.salary = +data.salary
  // console.log(data)
  // Ajax提交
  axios({
    method: 'POST',
    url: '/students',
    data: data
  }).then(result => {
    // console.log(result)
    message.success(result.data.message) // 使用插件提示消息
    document.querySelector('#form').reset() // 重置表单
    renderStudent() // 更新页面数据
    addModal.hide() // 让模态框隐藏
  })
})

删除和编辑的click事件

页面渲染的时候,给 <i>标签加自定义属性 data-id="${item.id}"

// 找到tbody注册点击事件,里面判断点击的是删除,还是编辑
document.querySelector('tbody').addEventListener('click', function (e) {
  if (e.target.classList.contains('bi-trash')) {
    // 说明点击了删除
    // console.log('你点击了删除')
    let id = e.target.dataset.id
    // 发送ajax请求,进行删除操作
    axios({
      url: `/students/${id}`,
      method: 'DELETE'
    }).then(result => {
      // console.log(result)
      message.success('删除成功') // 提示
      renderStudent() // 更新页面数据
    })
  }

  if (e.target.classList.contains('bi-pen')) {
    // 说明点击了编辑
    console.log('你点击了编辑')
  }
})

编辑功能

修改模态框的标题

点击 + 号的时候,修改模态框的标题:

// 点击 + 的时候,让模态框显示
document.querySelector('#openModal').addEventListener('click', function () {
  document.querySelector('.modal-title').innerHTML = '添加学员'
  addModal.show() // 让模态框显示
})

点击 编辑 的时候,修改模态框的标题和 属性:

// 找到tbody注册点击事件,里面判断点击的是删除,还是编辑
document.querySelector('tbody').addEventListener('click', function (e) {
  // 判断点击的是否是删除 -------------- 略,上一步已经写完了
  // 判断点击的是否是编辑
  if (e.target.classList.contains('bi-pen')) {
    // 说明点击了编辑
    // console.log('你点击了编辑')
    let id = e.target.dataset.id
    document.querySelector('.modal-title').innerHTML = '修改学员'
    // document.querySelector('.modal-title').setAttribute('属性名', 值)
    document.querySelector('.modal-title').setAttribute('data-id', id)
    addModal.show() // 显示模态框
  }
})

做数据回填

代码位置:点击 tbody 的时候,判断点击的是 编辑。

// 找到tbody注册点击事件,里面判断点击的是删除,还是编辑
document.querySelector('tbody').addEventListener('click', async function (e) {
  if (e.target.classList.contains('bi-trash')) {
    // 说明点击了删除
    // 代码略。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  }

  if (e.target.classList.contains('bi-pen')) {
    // 说明点击了编辑
    // console.log('你点击了编辑')
    let id = e.target.dataset.id // 获取编辑按钮的自定义属性值
    document.querySelector('.modal-title').innerHTML = '修改学员'
    // 下面是设置模态框标题(h5)的自定义属性,值是当前修改的学员的id
    // document.querySelector('.modal-title').setAttribute('属性名', 值)
    document.querySelector('.modal-title').setAttribute('data-id', id)
    addModal.show() // 显示模态框
    // 发送请求,获取当前修改的这个学员的详细信息
    let result = await axios({ url: `/students/${id}` })
    console.log(result.data.data) // 输出的是 个人的详细信息
    // 获取城市 和 区县,渲染到第2个和第3个下拉框的位置
    let res1 = await axios({
      url: '/api/city',
      params: {
        pname: result.data.data.province
      }
    })
    let res2 = await axios({
      url: '/api/area',
      params: {
        pname: result.data.data.province,
        cname: result.data.data.city
      }
    })
    // console.log(res1)
    let newArr1 = res1.data.data.map(item => `<option value="${item}">${item}</option>`)
    city.innerHTML = shi + newArr1.join('')
    // console.log(res2)
    let newArr2 = res2.data.data.map(item => `<option value="${item}">${item}</option>`)
    area.innerHTML = xian + newArr2.join('')
    // 做数据回填,继续使用插件 【 val(表单, 数据) 】,关于这个插件,只是简化代码的步骤。
    val(document.querySelector('#form'), result.data.data)
  }
})

点击确认,完成编辑

// 点击模态框中的 确认 按钮
document.querySelector('#submit').addEventListener('click', async function () {
  // 获取表单各项的值
  // let data = val(表单)
  let data = val(document.querySelector('#form'))
  // 检查是否是接口需要的数据
  // console.log(data)
  data.age = +data.age
  data.group = +data.group
  data.gender = +data.gender
  data.hope_salary = +data.hope_salary
  data.salary = +data.salary
  // console.log(data)
  let title = document.querySelector('.modal-title').innerHTML
  let result
  if (title === '添加学员') {
    // Ajax提交,添加数据
    result = await axios({
      method: 'POST',
      url: '/students',
      data: data
    })
  } else if (title === '修改学员') {
    // Ajax提交,修改数据
    let id = document.querySelector('.modal-title').dataset.id
    result = await axios({
      method: 'PUT',
      url: `/students/${id}`,
      data: data
    })
  }
  message.success(result.data.message) // 使用插件提示消息
  document.querySelector('#form').reset() // 重置表单
  renderStudent() // 更新页面数据
  addModal.hide() // 让模态框隐藏
})

项目的退出功能

退出,和登录是相反的。

登录后,存储了token,跳转到index.html

退出后,移除token,跳转到login.html

common.js中:

// 退出功能
document.querySelector('#logout')?.addEventListener('click', function () {
  // 1. 移除token
  localStorage.removeItem('token')
  // 2. 跳转到登录页
  location.href = './login.html' // 路径和JS文件在哪里无关;和html文件有关
})

空文件

简介

数据可视化项目,黑马顺义前端就业155期专属 展开 收起
CSS 等 3 种语言
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/laotang1234/data-visualization-155.git
git@gitee.com:laotang1234/data-visualization-155.git
laotang1234
data-visualization-155
数据可视化155
master

搜索帮助