十五(AJAX)、bootstrap弹框、案例(图书管理、图片上传、网站换肤、个人设置)、作业(英雄百科、必要商城分类)

1. bootstrap弹框

2. 案例1_图书管理

javascript 复制代码
// 自己的图书数据: 给自己起个外号
const creator = "chl";

// 获取-图书列表
function render() {
  axios({
    url: "https://hmajax.itheima.net/api/books",
    params: {
      creator,
    },
  }).then((res) => {
    // console.log(res.data.data);
    let str = res.data.data
      .map((item, index) => {
        const { id, bookname, author, publisher } = item;
        return `
          <tr>
            <td>${index + 1}</td>
            <td>${bookname}</td>
            <td>${author}</td>
            <td>${publisher}</td>
            <td>
              <span class="del" data-id="${id}">删除</span>
              <span class="edit" data-id="${id}">编辑</span>
            </td>
          </tr>
        `;
      })
      .join("");
    document.querySelector(".list").innerHTML = str;
  });
}
render();

const editModal = document.querySelector(".edit-modal");
const modalEdit = new bootstrap.Modal(editModal);

// 删除+编辑-事件委托
let id = "";
document.querySelector(".list").addEventListener("click", function (e) {
  id = e.target.dataset.id;
  // console.log(id);

  // 删除-图书
  if (e.target.classList.contains("del")) {
    axios({
      url: `https://hmajax.itheima.net/api/books/${id}`,
      method: "DELETE",
    }).then((res) => {
      render();
    });
  }

  // 编辑
  if (e.target.classList.contains("edit")) {
    // console.log(e.target.parentNode.parentNode); // tr
    modalEdit.show();
    // 获取-图书详情
    axios({
      url: `https://hmajax.itheima.net/api/books/${id}`,
    }).then((res) => {
      // console.log(res);
      // console.log(res.data.data);

      // 解构 剩余参数 对象方法
      /* const { id, ...other } = res.data.data;
      const oValues = Object.values(other);
      // console.log(other);
      Object.keys(other).forEach((key, index) => {
        document.querySelector(`.edit-form .${key}`).value = oValues[index];
      }); */

      // for in遍历对象 key是属性名 获取属性值->对象名[属性名]
      for (const key in res.data.data) {
        document.querySelector(`.edit-form .${key}`).value = res.data.data[key];
      }

      /* document.querySelector(`.edit-form .bookname`).value =
        res.data.data.bookname;
      document.querySelector(`.edit-form .author`).value = res.data.data.author;
      document.querySelector(`.edit-form .publisher`).value =
        res.data.data.publisher; */
    });
  }
});

// 编辑 确认修改按钮
const editBtn = document.querySelector(".edit-btn");
editBtn.addEventListener("click", function () {
  const editForm = document.querySelector(".edit-form");
  const data = serialize(editForm, { hash: true, empty: true });
  // 修改-图书详情
  axios({
    url: `https://hmajax.itheima.net/api/books/${id}`,
    method: "PUT",
    data: {
      ...data,
      creator,
    },
  }).then((res) => {
    render();
    modalEdit.hide();
  });
});

// 新增-图书
const addBtn = document.querySelector(".add-btn");
const addModal = document.querySelector(".add-modal");
const modalAdd = new bootstrap.Modal(addModal);
addBtn.addEventListener("click", function () {
  // serialize 获取表单值
  const addForm = document.querySelector(".add-form");
  const data = serialize(addForm, { hash: true, empty: true });
  // console.log(data); // {bookname: '12', author: '12', publisher: '12'}

  axios({
    url: "https://hmajax.itheima.net/api/books",
    method: "post",
    data: {
      // 展开运算符,解构data
      ...data,
      /* bookname,
      author,
      publisher, */
      creator,
    },
  }).then((res) => {
    // console.log(res);
    render();
    modalAdd.hide();
    // console.log(Object.keys(data)); // ['bookname', 'author', 'publisher']
    // 增加后表单数据置空,data对象内属性名和所需找的标签类名相同 --> forEach
    Object.keys(data).forEach((key) => {
      document.querySelector(`.add-form .${key}`).value = "";
    });
  });
});

3. 案例2_图片上传

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">

<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>
  <style>
    .img {
      width: 200px;
    }
  </style>
</head>

<body>
  <!-- file标签 -->
  <input type="file" class="upload">

  <!-- 渲染服务器返回的图片URL -->
  <img src="" class="img" alt="">

  <!-- 导入axios -->
  <!-- <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script> -->
  <script src="./axios.min.js"></script>
  <script>
    /**
     * 图片上传
     * 1. 选择图片
     * 2. FormData对象
     * 3. 调用上传接口
     * */
    const upload = document.querySelector('.upload')
    upload.addEventListener('change', function () {
      // FormData内置对象,负责向服务器传递表单数据,常用于文件上传
      const data = new FormData()
      data.append('img', this.files[0])
      // 调用上传接口
      axios({
        url: 'https://hmajax.itheima.net/api/uploadimg',
        method: 'post',
        // data:formData对象
        data,
      }).then(res => {
        // console.log(res.data)
        document.querySelector('.img').src = res.data.data.url
      })
    })

  </script>
</body>

</html>

4. 案例3_网站换肤

javascript 复制代码
const skin = document.querySelector("#skin");
skin.addEventListener("change", function () {
  const data = new FormData();
  data.append("img", this.files[0]);
  axios({
    url: "https://hmajax.itheima.net/api/uploadimg",
    method: "post",
    data,
  }).then((res) => {
    // document.body.style.backgroundImage = `url(${res.data.data.url})`;

    // 本地存储
    localStorage.setItem("url", res.data.data.url);
    document.body.style.backgroundImage = `url(${localStorage.getItem("url")})`;
  });
});
document.body.style.backgroundImage = `url(${
  localStorage.getItem("url") || ""
} )`;

5. 案例4_个人设置

html

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">

<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">
  <!-- 导入bootstrap -->
  <!-- <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet"> -->
  <!-- 核心样式 -->
  <link rel="stylesheet" href="./css/index.css">
  <title>个人设置</title>
</head>

<body>
  <!-- toast 提示框 -->
  <div class="toast my-toast" data-bs-autohide="true" data-bs-delay="1500" aria-live="assertive" aria-atomic="true"
    role="alert">
    <div class="toast-body">
      <div class="alert alert-success info-box" role="alert">
        操作成功
      </div>
    </div>
  </div>
  <!-- 核心内容区域 -->
  <div class="container">
    <ul class="my-nav">
      <li class="active">基本设置</li>
      <li>安全设置</li>
      <li>账号绑定</li>
      <li>新消息通知</li>
    </ul>
    <div class="content">
      <div class="info-wrap">
        <h3 class="title">基本设置</h3>
        <form class="user-form" action="javascript:;">
          <div class="form-item">
            <label for="email">邮箱</label>
            <input id="email" name="email" class="email" type="text" placeholder="请输入邮箱" autocomplete="off">
          </div>
          <div class="form-item">
            <label for="nickname">昵称</label>
            <input id="nickname" name="nickname" class="nickname" type="text" placeholder="请输入昵称" autocomplete="off">
          </div>
          <div class="form-item">
            <label>性别</label>
            <label class="male-label"><input type="radio" name="gender" class="gender" value="0">男</label>
            <label class="male-label"><input type="radio" name="gender" class="gender" value="1">女</label>
          </div>
          <div class="form-item">
            <label for="desc">个人简介</label>
            <textarea id="desc" name="desc" class="desc" placeholder="请输入个人简介" cols="20" rows="10"
              autocomplete="off"></textarea>
          </div>
          <button class="submit">提交</button>
        </form>
      </div>
      <div class="avatar-box">
        <h4 class="avatar-title">头像</h3>
          <img class="avatar" src="./img/头像.png" alt="">
          <label for="upload">更换头像</label>
          <input id="upload" type="file">
      </div>

    </div>
  </div>
  <!-- 导入 axios -->
  <!-- <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script> -->
  <script src="../axios.min.js"></script>
  <!-- 导入 bootstrap -->
  <!-- <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.min.js"></script> -->
  <!-- 导入 form-serialize -->
  <script src="./lib/form-serialize.js"></script>
  <!-- 核心逻辑 -->
  <script src="./js/index.js"></script>
</body>

</html>

js

javascript 复制代码
// 修改-个人头像
const upload = document.querySelector("#upload");
const creator = "chl";
upload.addEventListener("change", function () {
  const data = new FormData();
  data.append("avatar", this.files[0]);
  data.append("creator", creator);

  axios({
    url: "https://hmajax.itheima.net/api/avatar",
    method: "put",
    data,
  }).then((res) => {
    // console.log(res.data);
    document.querySelector(".avatar").src = res.data.data.avatar;
  });
});

// 获取-个人信息
function getData() {
  axios({
    url: "https://hmajax.itheima.net/api/settings",
    params: {
      creator,
    },
  }).then((res) => {
    // 方法一:解构并渲染到页面
    // const {} = res.data.data;
    // console.log(res.data.data);

    // 方法二:将要获取的元素类名和数据对象属性名相同 --> 遍历
    Object.keys(res.data.data).forEach((key) => {
      if (key == "avatar") {
        document.querySelector(".avatar").src = res.data.data[key];
      } else if (key == "gender") {
        const genders = document.querySelectorAll(".gender");
        genders[res.data.data[key]].checked = true;
      } else {
        document.querySelector(`.${key}`).value = res.data.data[key];
      }
    });
  });
}
getData();

// 修改-个人信息
document.querySelector(".submit").addEventListener("click", function () {
  const userForm = document.querySelector(".user-form");
  const data = serialize(userForm, { hash: true, empty: true });
  // console.log(data);
  // serialize获取到的data数据为字符串,axios请求时其gender数据类型应为数字类型 --> 数据类型转换
  data.gender = +data.gender;
  axios({
    url: "https://hmajax.itheima.net/api/settings",
    method: "PUT",
    data: {
      ...data,
      creator,
    },
  }).then((res) => {
    // console.log(res.data);

    getData();
  });
});

6. 作业

6.1 英雄百科

html 复制代码
<!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" />
  <link rel="stylesheet" href="./css/bootstrap.min.css" />
  <link rel="stylesheet" href="./css/index.css" />
  <title>英雄百科</title>
</head>

<body>
  <div class="main">
    <img class="cover"
      src="https://img.crawler.qq.com/lolwebschool/0/JAutoCMS_LOLWeb_f6416138ae858f73e2ca40a11587e17f/0" />
    <div class="hero-container">
      <input type="text" class="search" placeholder="检索" />
      <ul class="list">
        <li>
          <img src="http://game.gtimg.cn/images/lol/act/img/champion/Annie.png" class="pic" alt="" />
          <p>安妮</p>
        </li>
      </ul>
    </div>
  </div>
  <div id="infoModal" class="modal" tabindex="-1">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">黑暗之女安妮</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          <div class="info">
            <img src="http://game.gtimg.cn/images/lol/act/img/champion/Annie.png" class="icon img-thumbnail"
              alt="..." />
            <div class="progress-box">
              <div class="progress">
                <div class="attack progress-bar bg-success" style="width: 25%">攻击:</div>
              </div>
              <div class="progress">
                <div class="defense progress-bar bg-info" role="progressbar" style="width: 50%">防御:</div>
              </div>
              <div class="progress">
                <div class="magic progress-bar bg-warning" role="progressbar" style="width: 75%">魔法:</div>
              </div>
              <div class="progress">
                <div class="difficulty progress-bar bg-danger" role="progressbar" style="width: 100%">难度:</div>
              </div>
            </div>
          </div>
          <p>
            拥有危险夺命的能力,却长着一幅小大人儿的可爱模样,这就是掌握深不可测占火魔法的女孩------安妮。安妮生活在诺克萨斯北边的山脚下,但即便是在这种地方,她也依然是魔法师中的异类。她与火焰的紧密关系与生俱来------最初那些火焰是伴随着喜怒无常的冲动情绪出现的,后来她学会了如何掌握这些"好玩的小把戏"。其中,安妮最喜欢的就是她召唤亲爱的泰迪熊提伯斯------那头狂野的守护火兽。如今安妮已经迷失在了永恒的天真里,她在黑暗森林中游荡,寻觅着能陪自己玩耍的人。
          </p>
        </div>
      </div>
    </div>
  </div>
</body>
<script src="./lib/axios.js"></script>
<script src="./lib/bootstrap.min.js"></script>
<script>
  /*
    需求如下:
      渲染英雄列表数据
      搜索英雄
      渲染英雄详情数据
  */

  // 1. 渲染英雄列表数据
  axios({
    url: 'https://hmajax.itheima.net/api/lol/search',
  }).then(res => {
    console.log(res.data.data)
    render(res.data.data)
  })
  function render(data) {
    let str = data.map(item => {
      return `
        <li>
          <img src=${item.icon} class="pic" alt="" data-id="${item.heroId}" />
          <p>${item.title}</p>
        </li>
      `
    }).join('')
    document.querySelector('.list').innerHTML = str
  }


  // 2. 搜索英雄
  const search = document.querySelector('.search')
  search.addEventListener('keyup', function (e) {
    console.log(e)
    if (e.code === 'Enter') {

      // if (e.key === 'Enter') {
      console.log(1)
      const q = search.value
      axios({
        url: 'https://hmajax.itheima.net/api/lol/search',
        params: {
          q,
        }
      }).then(res => {
        render(res.data.data)
      })
    }
  })

  // 3. 渲染英雄详情数据 事件委托
  const modal = new bootstrap.Modal(document.querySelector('.modal'))
  document.querySelector('.list').addEventListener('click', function (e) {
    console.log(e)

    if (e.target.classList.contains('pic')) {
      // console.log(11)
      // console.log()

      const id = e.target.dataset.id
      axios({
        url: 'https://hmajax.itheima.net/api/lol/info',
        params: {
          id
        }
      }).then(res => {
        console.log(res.data.data.hero)
        const { name, title, icon, shortBio, attack, defense, magic, difficulty } = res.data.data.hero
        document.querySelector('.modal-content').innerHTML = `
          <div class="modal-header">
            <h5 class="modal-title">${name + title}</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            <div class="info">
              <img src=${icon} class="icon img-thumbnail"
                alt="..." />
              <div class="progress-box">
                <div class="progress">
                  <div class="attack progress-bar bg-success" style="width: ${attack / 10 * 100 + '%'}">攻击:</div>
                </div>
                <div class="progress">
                  <div class="defense progress-bar bg-info" role="progressbar" style="width: ${defense / 10 * 100 + '%'}">防御:</div>
                </div>
                <div class="progress">
                  <div class="magic progress-bar bg-warning" role="progressbar" style="width: ${magic / 10 * 100 + '%'}">魔法:</div>
                </div>
                <div class="progress">
                  <div class="difficulty progress-bar bg-danger" role="progressbar" style="width: ${difficulty / 10 * 100 + '%'}">难度:</div>
                </div>
              </div>
            </div>
            <p>${shortBio}</p>
          </div>
        `

        modal.show()
      })
    }
  })
</script>

</html>

6.2 必要商城-分类

html 复制代码
<script>
  /*
    需求如下:
      页面默认展示所有一级分类数据
      点击一级分类切换,展示下属二级分类数据
      点击二级分类分类,展示下属三级分类数据
  */
  const ulOne = document.querySelector('#one')
  /* function render(data) {
    let str = data.map(item => {
      return `
        <li class="item">${item.firstName}</li>
      `
    }).join('')
    ulOne.innerHTML = str
  } */

  // 1. 页面默认展示所有一级分类数据
  axios({
    url: 'https://hmajax.itheima.net/api-s/categoryfirst',
  }).then(res => {
    // console.log(res.data.list)
    let str = res.data.list.map(item => {
      // console.log(item.firstId)
      return `
        <li class="item" data-id="${item.firstId}">${item.firstName}</li>
      `
    }).join('')
    ulOne.innerHTML = str
  })

  // 2. 点击一级分类切换,展示下属二级分类数据
  const ulTwo = document.querySelector('#two')
  ulOne.addEventListener('click', function (e) {

    if (e.target.classList.contains('item')) {
      // console.log(e.target.dataset.id)
      // console.log(e)
      const firstId = e.target.dataset.id
      axios({
        url: 'https://hmajax.itheima.net/api-s/categorySecond',
        params: {
          firstId,
        }
      }).then(res => {
        // console.log(res.data.list)
        let str = res.data.list.map(item => {
          return `
            <li class="item" data-id="${item.secondId}">${item.secondName}</li>
          `
        }).join('')
        ulTwo.innerHTML = str
      })
    }
  })

  // 3. 点击二级分类分类,展示下属三级分类数据
  const ulThree = document.querySelector('#three')
  ulTwo.addEventListener('click', function (e) {
    if (e.target.classList.contains('item')) {
      const secondId = e.target.dataset.id
      axios({
        url: 'https://hmajax.itheima.net/api-s/categoryThird',
        params: {
          secondId,
        }
      }).then(res => {
        // console.log(res.data.list)
        let str = res.data.list.map(item => {
          return `
            <li class="item">${item.thiredName}</li>
          `
        }).join('')
        ulThree.innerHTML = str
      })
    }
  })

</script>
相关推荐
2401_8576363935 分钟前
医疗服务品质提升:SSM 与 Vue 打造医院预约挂号系统方案
前端·javascript·vue.js
余生H1 小时前
前端的Python应用指南(一):快速构建 Web 服务器 - Flask vs Node.js 对比
服务器·前端·python
白瑕2 小时前
[JavaScript] 我该怎么去写一个canvas游戏
前端·javascript
m0_748248942 小时前
前端篇-Content-Type 详解
前端
m0_748255022 小时前
新手参加2025年CTF大赛——Web题目的基本解题流程
前端·网络·安全
憨憨小江2 小时前
Vue3 基础记录
前端
SANG嘻嘻嘻2 小时前
ES6中的map和set
前端·javascript·es6
fantasy_arch2 小时前
CPU性能优化--前端优化
前端·性能优化
粥里有勺糖3 小时前
视野修炼第114期 | 2024JS现状调查结果
前端·javascript·github
程序视点3 小时前
【安全漏洞】Vue UI库Vant组件遭恶意投毒,字节RspacK也中招!请紧急修复!
前端·vue.js·ui