JS第二十三次笔记(案例)

77 阅读6分钟

目录:

image.png

1 Bootstarp弹框

image.png

1.1 通过属性控制,弹框显示或隐藏

data-bs-toggle='model':控制的是哪一类组件
data-bs-target='#Mymodel'负责打开
data-bs-dismiss='model'关闭模态框

[Modal · Bootstrap v5 中文文档 v5.3 | Bootstrap 中文网]

<!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>Bootstrap 弹框</title>
  <!-- 引入bootstrap.css -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>

  <!-- Button trigger modal -->
   <!-- data是自定义属性 -->
  <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
    Launch demo modal
  </button>

  <!-- Modal -->
  <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
          <button type="button" class="btn btn-primary">Save changes</button>
        </div>
      </div>
    </div>
  </div>
  <!-- 引入bootstrap.js -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js"></script>
</body>

</html>

1.2 通过JS控制,弹框显示或者隐藏.

image.png

<!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>Bootstrap 弹框</title>
  <!-- 引入bootstrap.css -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>
  <!-- 
    目标:使用JS控制弹框,显示和隐藏
    1. 创建弹框对象
    2. 调用弹框对象内置方法
      .show() 显示
      .hide() 隐藏
   -->
  <button type="button" class="btn btn-primary edit-btn">
    编辑姓名
  </button>

  <div class="modal name-box" 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">
          <form action="">
            <span>姓名:</span>
            <input type="text" class="username">
          </form>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
          <button type="button" class="btn btn-primary save-btn">保存</button>
        </div>
      </div>
    </div>
  </div>

  <!-- 引入bootstrap.js -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js"></script>
  <script>
    // 1. 创建弹框对象
    const modalDom = document.querySelector('.name-box')
    const myModal = new bootstrap.Modal(modalDom)

    // 编辑姓名->点击->赋予默认姓名->弹框显示
    document.querySelector('.edit-btn').addEventListener('click', e => {
      myModal.show()
      document.querySelector('.modal-title').innerHTML = '默认姓名'
      myModal.show()
    })



    // 保存->点击->->获取姓名打印->弹框隐藏
    document.querySelector('.save-btn').addEventListener('click', e => {
      const username = document.querySelector('.username').value
      console.log('我是', username)

      // 2. 隐藏弹框
      modal.hide()
      document.querySelector('.username').value = ''
    })
  </script>
</body>

</html>

2 案例——图书管理

image.png

image.png [查询文档](删除-图书 - AJAX阶段)
核心步骤:

image.png

image.png

image.png

image.png

2.1 CSS

/* 公共*/
html,
body {
  width: 100%;
  height: 100%;
}

.container {
  width: 1340px;
  margin: 0 auto;
  padding-top: 60px;
  box-sizing: border-box;
}

/* alert提示框 */
.toast {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
}

.toast .toast-body {
  padding: 0 !important;
}

.toast .alert-success {
  margin-bottom: 0 !important;
}

/* 头部导航 */
.container .top {
  display: flex;
  justify-content: space-between;
}

.container .top h3 {
  font-weight: 900;
}

.container .top .plus-btn {
  background-color: #539ACB !important;
  color: #fff;
  border: none;
}

/* 表格部分 */
.table {
  margin-top: 20px;
  text-align: center;
  font-size: 14px;
}

.table-light th {
  background-color: #939CA7 !important;
  color: #ffffff;
  font-family: PingFangSC-Medium;
  font-size: 16px;
  text-align: center;
  font-weight: 500;
  border-right: 1px solid lightgray;
}

.table-light th:last-of-type {
  border-right: none;
}

/* 表格内容 */
.table tbody td {
  color: #696F77;
}

.table .del {
  color: #E5964C;
  margin-right: 30px;
}

.table .edit {
  color: #539ACB;
}

.table tbody tr {
  height: 30px;
  line-height: 30px;
}

.table tbody tr td:last-of-type span {
  cursor: pointer;
}

/* 弹出层 */
.modal .top {
  display: flex;
  justify-content: center;
  background-color: #F0F3F7;
  padding: 15px 0;
  width: 100%;
  position: relative;
  color: #1E2023;
}

/* 右上角-关闭按钮 */
.modal .btn-close {
  font-size: 12px;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  right: 23px;
  /* 覆盖bootstrap样式 */
  margin: 0;
  padding: 0;
}

/* 表单容器 */
.form-wrap {
  box-sizing: border-box;
  background-color: white;
  padding: 40px;
}

.form-wrap .form-label {
  color: #696F77;
}

/* 修改输入框默认占位文字
    webkit内核, firefox18-, firfox19+, 其他
    */
.form-wrap input::-webkit-input-placeholder {
  color: #BFBFBF !important;
  font-size: 14px;
}


/* 底部按钮组 */
.modal-footer{
  border-top: 0;
}
.btn-group {
  text-align: center;
  width: 100%;
}

/* 修改bs的按钮弹性布局-改成自己设置大小 */
.btn-group,
.btn-group-vertical {
  display: block;
}

.btn-group button {
  width: 120px
}

.btn-group button:first-of-type {
  border: 1px solid #E3E3E3;
  background-color: #fff;
  color: black;
  margin-right: 60px;
}

.btn-group button:last-of-type {
  background-color: #539ACB;
}

.alert-success {
  border-color: transparent;
}

.toast {
  border: none;
}

2.2 JavaScript(最重点)

需考虑哪种业务情况使用属性操作模态框,哪种业务使用js控制

// 1.获取数据 
const creator = 'csq'
// 获取列表
const list = document.querySelector('.list')
// 封装一个函数,用来渲染函数
const render = () => {
  // 1.1 发送请求,获取数据
  axios({
    url: 'https://hmajax.itheima.net/api/books',
    method: 'GET',
    params: {
      creator
    }
    // 使用then方法得到返回结果
  }).then(({ data: { data } }) => {
    // console.log(res)
    // 解构数据
    // const { data } = res.data
    // console.log(data);
    //渲染页面(map+join)
    list.innerHTML = data.map((item, index) => {
      const { bookname, author, publisher, id } = item
      return `
      <tr>
          <td>${index + 1}</td>
          <td>${bookname}</td>
          <td>${author}</td>
          <td>${publisher}</td>
          <td data-id="${id}">
            <span class="del" ">删除</span>
            <span class="edit">编辑</span>
          </td>
        </tr>
      `
    }).join('')

  })
}

// 调用函数,首次渲染页面(加载)
render()


// 2:新增图书
// 2.1点击添加按钮 弹出模态框=>可使用属性控制(无额外操作)=>已经实现
// 2.2 点击保存 获取数据,发送请求,渲染页面=>必须使用js控制,因为存在额外操作
const addBtn = document.querySelector('.add-btn')
const addForm = document.querySelector('.add-form')
const addModal = new bootstrap.Modal('.add-modal')
addBtn.addEventListener('click', e => {
  // 获取数据=>serialize=>查看接口文档,后端需要什么数据
  // Body参数 (application/json) 服务端需要 请求体传参,并且需要json格式数据,
  // 但是axios可以将对象自动转化为json,所以我们只需要给data传入对象
  // 因为获取的是对象数据,所以使用hash。后还要判断非空,所以使用empty
  const data = serialize(addForm, { hash: true, empty: true })
  console.log(data);
  // 判断数据是否为空
  if (!data.author || !data.bookname || !data.publisher) {
    return alert('请输入完整信息!')

  }
  // 根据数据发送请求
  axios({
    url: 'https://hmajax.itheima.net/api/books',
    method: 'POST',
    // 使用对象展开将creator数据快速添加到data之中,传给后端
    data: {
      creator,
      // 对象展开
      ...data
    }
  }).then(res => {
    // console.log(res);
    // 添加成功后,先关闭弹框(只能做js操作),后渲染页面,再渲染页面

    // 关闭模态框
    // 
    addModal.hide()
    render()
    // 清空表单
    addForm.reset()
  })
})

// 2.3 新增成功,就刷新页面重新渲染

// 4.删除图书
// 给删除按钮绑定事件=>事件委托=>删除按钮是后追加的元素,所以不能直接获取,要给父级添加事件委托
list.addEventListener('click', e => {
  // const { target } = e
  // 获取当前元素
  // const target = e.target
  // 判断是否是删除按钮
  const { target, target: { parentNode: { dataset } } } = e
  if (target.classList.contains('del')) {
    // 获取当前数据的id值
    console.log(dataset.id);
    // 根据id发送请求,删除数据
    // 4.3 删除成功后,渲染页面
    // Path参数叫做路径参数,就是将参数写在url后面
    axios({
      url: `https://hmajax.itheima.net/api/books/${dataset.id}`,
      method: 'DELETE'
    }).then(res => {
      // console.log(res);
      alert(res.data.message)
      // 删除成功后,渲染页面
      render()
    })
  }
})


// 5.编辑图书
// 5.1 给编辑按钮绑定事件=>事件委托=>编辑按钮是后追加的元素,所以不能直接获取,要给父级添加事件委托
// 点击编辑时弹窗中的表单数据会回显,(服务器返回)

const editModal = new bootstrap.Modal(document.querySelector('.edit-modal'))

const editForm = document.querySelector('.edit-form')

// 1. 点击编辑按钮 显示模态框=>js控制 点击之后执行其他的逻辑、
list.addEventListener('click', e => {
  // 获取当前元素
  const { target } = e
  // 判断是否是编辑按钮
  if (target.classList.contains('edit')) {
    // 获取当前数据的id值
    const id = e.target.parentNode.dataset.id
    axios({
      url: `https://hmajax.itheima.net/api/books/${id}`,
      method: 'GET'
    }).then(res => {
      // console.log(res)
      const { bookname, author, publisher, id } = res.data.data
      // 回显数据(右赋值给左边,渲染)
      // editForm.querySelector('[name="bookname"]').value = bookname
      // editForm.querySelector('[name="author"]').value = author
      // editForm.querySelector('[name="publisher"]').value = publisher
      //左边的data是对象
      const { data } = res.data



      // Object.keys方法快速获取对象的key值(返回数组) 
      // arr是一个数组,所以需要循环遍历其每一个键,输出对应属性
      const arr = Object.keys(data)
      // foreach获取所以属性(153行的优化)
      arr.forEach(item => {
        editForm.querySelector(`[name=${item}]`).value = data[item]
      })
      // 显示编辑模态框
      editModal.show()
    })
  }
})
// 2. 显示模态框后,根据这个id获取图书详情并回显数据
// 3. 回显到模态框中
// 4. 点击编辑的修改按钮,将最新的数据发送给后端
// 5. 修改成功后,关闭模态框,渲染页面

//修改图书表单
// 4.4 点击编辑 修改按钮 将最新的数据发送给服务器,修改数据
document.querySelector('.edit-btn').addEventListener('click', e => {
  // 获取数据
  const data = serialize(editForm, { hash: true, empty: true })
  console.log(data);

  // 通过ajax发送数据给服务器做修改
  axios({
    url: `https://hmajax.itheima.net/api/books/${data.id}`,
    method: 'PUT',
    data: {
      creator,
      ...data
    }
  }).then(res => {
    // console.log(res);
    // alert(res.data.message)
    // 修改成功后,关闭模态框,渲染页面
    editModal.hide()
    render()
    editForm.reset()
  })

})

2.3 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">
  <title>案例-图书管理</title>
  <!-- 字体图标 -->
  <link rel="stylesheet" href="https://at.alicdn.com/t/c/font_3736758_vxpb728fcyh.css">
  <!-- 引入bootstrap.css -->
  <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">
</head>

<body>
  <!-- 主体区域 -->
  <div class="container">
    <!-- 头部标题和添加按钮 -->
    <div class="top">
      <h3>图书管理</h3>
      <button type="button" class="btn btn-primary plus-btn" data-bs-toggle="modal" data-bs-target=".add-modal"> + 添加
      </button>
    </div>
    <!-- 数据列表 -->
    <table class="table">
      <thead class="table-light">
        <tr>
          <th style="width: 150px;">序号</th>
          <th>书名</th>
          <th>作者</th>
          <th>出版社</th>
          <th style="width: 180px;">操作</th>
        </tr>
      </thead>
      <tbody class="list">
        <!-- <tr>
          <td>1</td>
          <td>JavaScript程序设计</td>
          <td>马特·弗里斯比</td>
          <td>人民邮电出版社</td>
          <td>
            <span class="del">删除</span>
            <span class="edit">编辑</span>
          </td>
        </tr> -->

      </tbody>
    </table>
  </div>
  <!-- 新增-弹出框 -->
  <div class="modal fade add-modal">
    <!-- 中间白色区域 -->
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header top">
          <span>添加图书</span>
          <button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body form-wrap">
          <!-- 新增表单 -->
          <form class="add-form">
            <div class="mb-3">
              <label for="bookname" class="form-label">书名</label>
              <input type="text" class="form-control bookname" placeholder="请输入书籍名称" name="bookname">
            </div>
            <div class="mb-3">
              <label for="author" class="form-label">作者</label>
              <input type="text" class="form-control author" placeholder="请输入作者名称" name="author">
            </div>
            <div class="mb-3">
              <label for="publisher" class="form-label">出版社</label>
              <input type="text" class="form-control publisher" placeholder="请输入出版社名称" name="publisher">
            </div>
          </form>
        </div>
        <div class="modal-footer btn-group">
          <button type="button" class="btn btn-primary" data-bs-dismiss="modal"> 取消 </button>
          <button type="button" class="btn btn-primary add-btn"> 保存 </button>
        </div>
      </div>
    </div>
  </div>
  <!-- 编辑-弹出框 -->
  <div class="modal fade edit-modal">
    <!-- 中间白色区域 -->
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header top">
          <span>编辑图书</span>
          <button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body form-wrap">
          <!-- 编辑表单 -->
          <form class="edit-form">
            <input type="hidden" class="id" name="id">
            <div class="mb-3">
              <label for="bookname" class="form-label">书名</label>
              <input type="text" class="form-control bookname" placeholder="请输入书籍名称" name="bookname">
            </div>
            <div class="mb-3">
              <label for="author" class="form-label">作者</label>
              <input type="text" class="form-control author" placeholder="请输入作者名称" name="author">
            </div>
            <div class="mb-3">
              <label for="publisher" class="form-label">出版社</label>
              <input type="text" class="form-control publisher" placeholder="请输入出版社名称" name="publisher">
            </div>
          </form>
        </div>
        <div class="modal-footer btn-group">
          <button type="button" class="btn btn-primary" data-bs-dismiss="modal"> 取消 </button>
          <button type="button" class="btn btn-primary edit-btn"> 修改 </button>
        </div>
      </div>
    </div>
  </div>
  <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
  <script src="./lib/form-serialize.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.min.js"></script>
  <!-- 核心逻辑 -->
  <script src="./js/index.js"></script>
</body>

</html>

2.4 serilalize(也可自行查询)

// get successful control from form and assemble into object
// http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2

// types which indicate a submit action and are not successful controls
// these will be ignored
var k_r_submitter = /^(?:submit|button|image|reset|file)$/i;

// node names which could be successful controls
var k_r_success_contrls = /^(?:input|select|textarea|keygen)/i;

// Matches bracket notation.
var brackets = /(\[[^\[\]]*\])/g;

// serializes form fields
// @param form MUST be an HTMLForm element
// @param options is an optional argument to configure the serialization. Default output
// with no options specified is a url encoded string
//    - hash: [true | false] Configure the output type. If true, the output will
//    be a js object.
//    - serializer: [function] Optional serializer function to override the default one.
//    The function takes 3 arguments (result, key, value) and should return new result
//    hash and url encoded str serializers are provided with this module
//    - disabled: [true | false]. If true serialize disabled fields.
//    - empty: [true | false]. If true serialize empty fields
function serialize(form, options) {
    if (typeof options != 'object') {
        options = { hash: !!options };
    }
    else if (options.hash === undefined) {
        options.hash = true;
    }

    var result = (options.hash) ? {} : '';
    var serializer = options.serializer || ((options.hash) ? hash_serializer : str_serialize);

    var elements = form && form.elements ? form.elements : [];

    //Object store each radio and set if it's empty or not
    var radio_store = Object.create(null);

    for (var i=0 ; i<elements.length ; ++i) {
        var element = elements[i];

        // ingore disabled fields
        if ((!options.disabled && element.disabled) || !element.name) {
            continue;
        }
        // ignore anyhting that is not considered a success field
        if (!k_r_success_contrls.test(element.nodeName) ||
            k_r_submitter.test(element.type)) {
            continue;
        }

        var key = element.name;
        var val = element.value;

        // we can't just use element.value for checkboxes cause some browsers lie to us
        // they say "on" for value when the box isn't checked
        if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
            val = undefined;
        }

        // If we want empty elements
        if (options.empty) {
            // for checkbox
            if (element.type === 'checkbox' && !element.checked) {
                val = '';
            }

            // for radio
            if (element.type === 'radio') {
                if (!radio_store[element.name] && !element.checked) {
                    radio_store[element.name] = false;
                }
                else if (element.checked) {
                    radio_store[element.name] = true;
                }
            }

            // if options empty is true, continue only if its radio
            if (val == undefined && element.type == 'radio') {
                continue;
            }
        }
        else {
            // value-less fields are ignored unless options.empty is true
            if (!val) {
                continue;
            }
        }

        // multi select boxes
        if (element.type === 'select-multiple') {
            val = [];

            var selectOptions = element.options;
            var isSelectedOptions = false;
            for (var j=0 ; j<selectOptions.length ; ++j) {
                var option = selectOptions[j];
                var allowedEmpty = options.empty && !option.value;
                var hasValue = (option.value || allowedEmpty);
                if (option.selected && hasValue) {
                    isSelectedOptions = true;

                    // If using a hash serializer be sure to add the
                    // correct notation for an array in the multi-select
                    // context. Here the name attribute on the select element
                    // might be missing the trailing bracket pair. Both names
                    // "foo" and "foo[]" should be arrays.
                    if (options.hash && key.slice(key.length - 2) !== '[]') {
                        result = serializer(result, key + '[]', option.value);
                    }
                    else {
                        result = serializer(result, key, option.value);
                    }
                }
            }

            // Serialize if no selected options and options.empty is true
            if (!isSelectedOptions && options.empty) {
                result = serializer(result, key, '');
            }

            continue;
        }

        result = serializer(result, key, val);
    }

    // Check for all empty radio buttons and serialize them with key=""
    if (options.empty) {
        for (var key in radio_store) {
            if (!radio_store[key]) {
                result = serializer(result, key, '');
            }
        }
    }

    return result;
}

function parse_keys(string) {
    var keys = [];
    var prefix = /^([^\[\]]*)/;
    var children = new RegExp(brackets);
    var match = prefix.exec(string);

    if (match[1]) {
        keys.push(match[1]);
    }

    while ((match = children.exec(string)) !== null) {
        keys.push(match[1]);
    }

    return keys;
}

function hash_assign(result, keys, value) {
    if (keys.length === 0) {
        result = value;
        return result;
    }

    var key = keys.shift();
    var between = key.match(/^\[(.+?)\]$/);

    if (key === '[]') {
        result = result || [];

        if (Array.isArray(result)) {
            result.push(hash_assign(null, keys, value));
        }
        else {
            // This might be the result of bad name attributes like "[][foo]",
            // in this case the original `result` object will already be
            // assigned to an object literal. Rather than coerce the object to
            // an array, or cause an exception the attribute "_values" is
            // assigned as an array.
            result._values = result._values || [];
            result._values.push(hash_assign(null, keys, value));
        }

        return result;
    }

    // Key is an attribute name and can be assigned directly.
    if (!between) {
        result[key] = hash_assign(result[key], keys, value);
    }
    else {
        var string = between[1];
        // +var converts the variable into a number
        // better than parseInt because it doesn't truncate away trailing
        // letters and actually fails if whole thing is not a number
        var index = +string;

        // If the characters between the brackets is not a number it is an
        // attribute name and can be assigned directly.
        if (isNaN(index)) {
            result = result || {};
            result[string] = hash_assign(result[string], keys, value);
        }
        else {
            result = result || [];
            result[index] = hash_assign(result[index], keys, value);
        }
    }

    return result;
}

// Object/hash encoding serializer.
function hash_serializer(result, key, value) {
    var matches = key.match(brackets);

    // Has brackets? Use the recursive assignment function to walk the keys,
    // construct any missing objects in the result tree and make the assignment
    // at the end of the chain.
    if (matches) {
        var keys = parse_keys(key);
        hash_assign(result, keys, value);
    }
    else {
        // Non bracket notation can make assignments directly.
        var existing = result[key];

        // If the value has been assigned already (for instance when a radio and
        // a checkbox have the same name attribute) convert the previous value
        // into an array before pushing into it.
        //
        // NOTE: If this requirement were removed all hash creation and
        // assignment could go through `hash_assign`.
        if (existing) {
            if (!Array.isArray(existing)) {
                result[key] = [ existing ];
            }

            result[key].push(value);
        }
        else {
            result[key] = value;
        }
    }

    return result;
}

// urlform encoding serializer
function str_serialize(result, key, value) {
    // encode newlines as \r\n cause the html spec says so
    value = value.replace(/(\r)?\n/g, '\r\n');
    value = encodeURIComponent(value);

    // spaces should be '+' rather than '%20'.
    value = value.replace(/%20/g, '+');
    return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
}

3 图片上传

image.png

<!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>图片上传</title>
</head>

<body>
  <!-- 文件选择元素 -->
  <input type="file" class="upload">
  <img src="" alt="">
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    /**
     * 目标:图片上传,显示到网页上
     *  1. 获取图片文件
     *  2. 使用 FormData 携带图片文件
     *  3. 提交到服务器,获取图片url网址使用
    */
    //  绑定change修改事件
    document.querySelector('.upload').addEventListener('change', e => {
      // 获取图片文件
      // 获取图片
      // console.log(e.target.files[0]);
      // 调用接口上传数据(form-data数据格式)
      const fd = new FormData()
      // formdata必须使用键值的形式追加属性
      fd.append('img', e.target.files[0])
      // formdata不能直接使用console.log的方式打印出来;必须使用for循环
      // for (const key in fd) {
      //   console.log(key, fd[key]);
      // }
      // 使用axios发送请求
      axios({
        url: 'https://hmajax.itheima.net/api/uploadimg',
        method: 'POST',
        data: fd
      }).then(res => {
        console.log(res);
        // 将图片放到img标签中
        document.querySelector('img').src = res.data.data.url
      })

    })
  </script>
</body>

</html>

4 案例——更换网页背景

/**
 * 目标:网站-更换背景
 *  1. 选择图片上传,设置body背景
 *  2. 上传成功时,"保存"图片url网址
 *  3. 网页运行后,"获取"url网址使用
 * */
let url = localStorage.getItem('url')
if (url) {
  document.body.style.backgroundImage = `url(${url})`
}
document.querySelector('#bg').addEventListener('change', e => {
  // 获取图片信息
  console.dir(e.target.files[0])
  // 创建FormData数据格式
  const fd = new FormData()
  // 添加图片信息(键,值)
  fd.append('img', e.target.files[0])
  // 发送请求
  axios({
    url: 'https://hmajax.itheima.net/api/uploadimg',
    method: 'POST',
    data: fd

  }).then(res => {
    console.log(res.data.data.url)
    localStorage.setItem('url', res.data.data.url)
    document.body.style.backgroundImage = `url(${res.data.data.url})`
  })
})



5 案例——个人信息设置

image.png

5.1 信息渲染

给自己信息起别名,防止用户信息冲突

image.png

/**
 * 目标1:信息渲染
 *  1.1 获取用户的数据
 *  1.2 回显数据到标签上
 * */
const creator = 'csq'// 获取用户数据
const userForm = document.querySelector('.user-form')
const render = () => {
  axios({
    url: 'https://hmajax.itheima.net/api/settings',
    method: 'GET',
    params: { creator }
  }).then(res => {
    const { data } = res.data

    // 回显数据
    Object.keys(data).forEach(item => {
      console.log(item);

      if (item === 'avatar') {
        document.querySelector('.prew').src = data[item]
      } else if (item === 'gender') {
        document.querySelector(`[name=gender][value='${data[item]}']`).checked = true
      } else {
        userForm.querySelector(`[name=${item}]`).value = data[item]
      }
    })
  })
}
render()

// 头像修改
// 点击按钮,选择图片
// 获取图片
// axios上传图片
// 回显图片
document.querySelector('.upload').addEventListener('change', (e) => {
  // console.log(e.target.files[0]);
  const fd = new FormData
  fd.append('avatar', e.target.files[0])
  fd.append('creator', creator)
  axios({
    url: 'https://hmajax.itheima.net/api/avatar',
    method: 'POST',
    data: fd
  }).then(res => {
    console.log(res);
    document.querySelector('.prew').src = res.data.data.avatar
  })
})



image.png