AJAX的入门案例

图书管理系统和个人信息的小案列,进一步加深前端的增删改查和图片处理

一、效果图(图书管理系统)

二、form-serialize.js

// 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;
}

三、index.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 href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/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://unpkg.com/axios/dist/axios.min.js"></script>
  <script src="./lib/form-serialize.js"></script>
  <!-- 引入bootstrap.js -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.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>

四、index.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;
}

五、index.js

/**
 * 目标1:渲染图书列表
 *  1.1 获取数据
 *  1.2 渲染数据
 */
const creator = '老王'
function getBooksList() {
    axios({
        url: 'http://hmajax.itheima.net/api/books',
        method: 'GET',
        params: {
            creator
        }
    }).then(result => {
        console.log(result);
        const booksList = result.data.data
        const htmlStr = booksList.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 data-id=${id}>
                <span class="del">删除</span>
                <span class="edit">编辑</span>
                </td>
            </tr>
            `
        }).join('')
        document.querySelector('.list').innerHTML = htmlStr
    })
}

getBooksList()


/**
 * 目标2:新增图书
 *  2.1 新增弹框->显示和隐藏
 *  2.2 收集表单数据,并提交到服务器保存
 *  2.3 刷新图书列表
 */
//创建弹框对象
const addModalDom = document.querySelector('.add-modal')
const addModal = new bootstrap.Modal(addModalDom)
//保存按钮->点击->隐藏弹框
document.querySelector('.add-btn').addEventListener('click', () => {
    //获取表单数据
    const addForm = document.querySelector('.add-form')
    const bookObj = serialize(addForm, { hash: true, empty: true })
    console.log(bookObj);
    //发送请求
    axios({
        url: 'http://hmajax.itheima.net/api/books',
        method: 'POST',
        data: {
            ...bookObj, creator
        }
    }).then(result => {
        getBooksList()
        //重置表单
        addForm.reset()
        //隐藏弹框
        addModal.hide()
    })
})


/**
 * 目标3:删除图书
 *  3.1 删除元素绑定点击事件->获取图书id
 *  3.2 调用删除接口
 *  3.3 刷新图书列表
 */
document.querySelector('.list').addEventListener('click', e => {
    if (e.target.classList.contains('del')) {
        const id = e.target.parentNode.dataset.id
        axios({
            url: `http://hmajax.itheima.net/api/books/${id}`,
            method: 'DELETE'
        }).then(result => {
            getBooksList()
            console.log(result.data.message);
        })
    }
})


/**
 * 目标4:编辑图书
 *  4.1 编辑弹框->显示和隐藏
 *  4.2 获取当前编辑图书数据->回显到编辑表单中
 *  4.3 提交保存修改,并刷新列表
 */
const editModalDom = document.querySelector('.edit-modal')
const editModal = new bootstrap.Modal(editModalDom)

document.querySelector('.list').addEventListener('click', e => {
    if (e.target.classList.contains('edit')) {
        const id = e.target.parentNode.dataset.id
        axios({
            url: `http://hmajax.itheima.net/api/books/${id}`,
            method: 'GET'
        }).then(result => {
            const bookObj = result.data.data
            const keys = Object.keys(bookObj)
            keys.forEach(key => {
                document.querySelector(`.edit-modal .${key}`).value = bookObj[key]
            })
        })
        editModal.show()
    }
})


document.querySelector('.edit-btn').addEventListener('click', e => {
    const editForm = document.querySelector('.edit-form')
    const bookObj = serialize(editForm, { hash: true, empty: true })
    const { id, bookname, author, publisher } = bookObj
    axios({
        url: `http://hmajax.itheima.net/api/books/${id}`,
        method: 'PUT',
        data: {
            bookname,
            author,
            publisher,
            creator, creator
        }
    }).then(result => {
        getBooksList()
    })
    getBooksList()
    editModal.hide()
})

六、效果图(个人信息)

七、index.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">
  <!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"> -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/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-delay="1500">
    <div class="toast-body">
      <div class="alert alert-success info-box">
        操作成功
      </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="prew" src="./img/头像.png" alt="">
          <label for="upload">更换头像</label>
          <input id="upload" type="file" class="upload">
      </div>

    </div>
  </div>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js"></script> -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js"></script>
  <script src="./lib/form-serialize.js"></script>
  <!-- 核心逻辑 -->
  <script src="./js/index.js"></script>
</body>

</html>

八、index.css

body {
  background-color: #f0f2f5;
  padding: 20px;
  -moz-user-select: none;
  /*火狐*/
  -webkit-user-select: none;
  /*webkit浏览器*/
  -ms-user-select: none;
  /*IE10*/
  -khtml-user-select: none;
  /*早期浏览器*/
  user-select: none;
  font-size: 14px;
}

.container {
  background-color: #ffffff;
  padding: 20px;
  display: flex;
  padding-left: 0;
  margin: 0 auto;
  min-width: 700px;
  max-width: 1000px;
  border-radius: 2px;
}

.my-nav {
  width: 200px;
  border-right: 1px solid #f0f0f0;
  list-style: none;
}

.my-nav li {
  cursor: pointer;
  height: 40px;
  line-height: 40px;
  padding-left: 20px;
  font-size: 14px;
}

.my-nav li.active {
  background-color: #e9f7fe;
  color: #448ef7;
  border-right: 4px solid #448ef7;
  font-weight: 600;
}

.content {
  padding-top: 10px;
  /* padding-left: 40px; */
  flex: 1;
  display: flex;
  justify-content: space-evenly;
}

.content .title {
  font-size: 20px;
  margin-bottom: 30px;
}

.content .info-wrap {
  /* margin-right: 20px; */
}

.content .avatar-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 20px;
  /* flex: 1; */
  padding-top: 55px;
  width: 200px;
}

.content .avatar-box .avatar-title {
  font-size: 16px;
  text-align: left;
  align-self: flex-start;
  margin: 0;
}

.content .avatar-box .prew {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  margin-bottom: 15px;
}

.content .avatar-box label {
  width: 100px;
  height: 30px;
  transition: all .3s;
  box-shadow: 0 2px 0 rgb(0 0 0 / 2%);
  cursor: pointer;
  font-size: 14px;
  border-radius: 2px;
  color: rgba(0, 0, 0, .85);
  border: 1px solid #d9d9d9;
  text-align: center;
  line-height: 30px;
}

.content .avatar-box label:hover {
  color: #40a9ff;
  border-color: #40a9ff;
  background: #fff;
}

.content .avatar-box #upload {
  display: none;
}



.content .user-form label:not(.male-label) {
  display: block;
  margin-bottom: 15px;
  margin-top: 15px;
}

.content .user-form .form-item {
  margin-bottom: 20px;
}

.content .user-form .form-item .male-label {
  margin-right: 20px;
  display: inline-flex;
  align-items: center;
}

.content .user-form input[type=radio] {
  margin-right: 10px;
  outline: none;
  background-size: contain;
  border: 1px solid rgba(0, 0, 0, .25);
  border-radius: 50%;
  box-sizing: border-box;
  width: 16px;
  height: 16px;
  appearance: none;

}



.content .user-form input[type=radio]:checked {
  border-radius: 50%;
  border-color: #0d6efd;
  background-color: #0d6efd;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e");
}



.content .user-form input:not([type=radio]) {
  height: 30px;
  appearance: none;
}


.form-item input:not([type=radio]),
textarea {
  display: block;
  width: 330px;
  outline: none;
  font-size: 14px;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
  transition: all .3s;
  padding-left: 5px;
}

.content .user-form textarea {
  padding-top: 10px;
  width: 350px;
  resize: none;
}



.content .user-form input:focus,
textarea:focus {
  border-color: #40a9ff;
  border-right-width: 1px;
  z-index: 1;
  border-color: #40a9ff;
  box-shadow: 0 0 0 2px rgb(24 144 255 / 20%);
  border-right-width: 1px;
  outline: 0;
}

.content .user-form button.submit {
  background: #4D8FF7;
  width: 78px;
  height: 32px;
  color: white;
  text-align: center;
  line-height: 32px;
  font-size: 14px;
  color: #FFFFFF;
  letter-spacing: 0;
  font-weight: 500;
  border: none;
  cursor: pointer;
}

.toast {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
}

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

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

九、index.js

/**
 * 目标1:信息渲染
 *  1.1 获取用户的数据
 *  1.2 回显数据到标签上
 * */
const creator = '播仔'
axios({
    url: 'http://hmajax.itheima.net/api/settings',
    params: {
        creator
    }
}).then(result => {
    console.log(result);
    const userObj = result.data.data
    const keys = Object.keys(userObj)
    keys.forEach(key => {
        if (key === 'avatar') {
            // 赋予默认头像
            document.querySelector('.prew').src = userObj[key]
        } else if (key === 'gender') {
            // 赋予默认性别
            // 获取性别单选框:[男radio元素,女radio元素]
            const gRadioList = document.querySelectorAll('.gender')
            // 获取性别数字:0男,1女
            const gNum = userObj[key]
            // 通过性别数字,作为下标,找到对应性别单选框,设置选中状态
            gRadioList[gNum].checked = true
        } else {
            // 赋予默认内容
            document.querySelector(`.${key}`).value = userObj[key]
        }
    })

})

/**
 * 目标2:修改头像
 *  2.1 获取头像文件
 *  2.2 提交服务器并更新头像
 * */
document.querySelector('.upload').addEventListener('change', e => {
    const image = e.target.files[0]
    // console.log(image);
    const formData = new FormData()
    formData.append('avatar', image)
    formData.append('creator', creator)
    axios({
        url: 'http://hmajax.itheima.net/api/avatar',
        method: 'PUT',
        data: formData
    }).then(result => {
        console.log(result);
        const url = result.data.data.avatar
        document.querySelector('.prew').src = url
    })

})


/**
 * 目标3:提交表单
 *  3.1 收集表单信息
 *  3.2 提交到服务器保存
 */
/**
 * 目标4:结果提示
 *  4.1 创建toast对象
 *  4.2 调用show方法->显示提示框
 */
document.querySelector('.submit').addEventListener('click', e => {
    const userForm = document.querySelector('.user-form')
    const userObj = serialize(userForm, { hash: true, empty: true })
    userObj.creator = creator
    // userObj.gender = userObj.gender+
    userObj.gender = parseInt(userObj.gender, 10)
    axios({
        url: 'http://hmajax.itheima.net/api/settings',
        method: 'PUT',
        data: userObj
    }).then(result => {
        console.log(result.data.message)
        const toastDom = document.querySelector('.my-toast')
        const toast = new bootstrap.Toast(toastDom)
        toast.show()
    })

})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值