Bootstrap

图书管理系统前端—项目分析(一)

图书管理系统前端代码

1. Element UI 的全局引入与使用

1.1 全局引入 Element UI 及相应配置

◼ 在 main.js 文件中配置

image-20230228133256113

import ElementUI from 'element-ui'  //导入element-ui所有组件
import 'element-ui/lib/theme-chalk/index.css'  //导入element-ui样式
1.2 登录界面相关组件及重要属性
1.2.1 表单
<el-form ref="loginForm"
         :model="loginForm" 
         :rules="loginRules" 
         class="login-form" 
         auto-complete="on" 
         label-position="left">
    <el-form-item prop="username">各种表单项</el-form-item>
</el-form> 
  • ref="loginForm":设置表单的引用名为loginForm,可以通过该名称在Vue实例中访问表单组件的方法和属性。
  • :model="loginForm":将loginForm作为表单的数据模型,用于绑定表单项和数据(单向)。
  • :rules="loginRules":设置表单的验证规则,这里传递的是一个数组,用于验证表单项输入的数据是否符合要求。
  • class="login-form":为表单组件添加了一个CSS类名,可以通过该类名自定义表单的样式。
  • auto-complete="on":浏览器自动完成表单项输入的功能,设置为启用状态。
  • label-position="left":设置表单项的标签(label)显示在左侧。
  • el-form-item标签包含在el-form标签中,用于放置各种表单项,例如输入框、下拉菜单、单选框等

1.关于 ref 属性说明:Vue 为简化DOM获取方法提出了ref 属性和$refs 对象。一般的操作流程是:ref 绑定控件,$refs 获取控件。

绑定:ref="loginForm"

获取:this.&ref.loginForm

2.关于 prop 属性说明:这个属性指定了表单项对应的数据字段名为 username。这个字段名将用于在表单数据对象中标识和访问这个表单项的值。

例如,在提交表单数据时,将会使用 username 字段名来获取用户输入的用户名值。

◼ 表单属性

属性说明
model表单数据对象
rules表单验证规则
inline行内表单模式(false/true)
label-position表单域标签的位置,如果值为 left 或者 right 时,则需要设置 label-width(right/left/top)
label-width表单域标签的宽度,例如 ‘50px’。作为 Form 直接子元素的 form-item 会继承该值。支持 auto
size用于控制该表单内组件的尺寸(medium / small / mini)
disabled是否禁用该表单内的所有组件。若设置为 true,则表单内组件上的 disabled 属性不再生效
show-message是否显示校验错误信息(false/true)
status-icon是否在输入框中显示校验结果反馈图标(false/true)

◼ 表单项属性

属性说明
prop表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的
label标签文本
label-width表单域标签的的宽度,例如 ‘50px’。支持 auto
required是否必填,如不设置,则会根据校验规则自动生成(false/true)
rules表单验证规则
size用于控制该表单域下组件的尺寸(medium / small / mini)
error表单域验证错误信息, 设置该值会使表单验证状态变为error,并显示该错误信息
1.2.2 文本框
<!--用户名-->
<el-input class="yuan"
          ref="username"
          v-model="loginForm.username"
          placeholder="请输入用户名"
          name="username"
          type="text"
          tabindex="1"
          auto-complete="on"/>
<!--密码-->
<el-input class="yuan"
          :key="passwordType"
          ref="password"
          v-model="loginForm.password"
          :type="passwordType"
          placeholder="请输入密码"
          name="password"
          tabindex="2"
          auto-complete="on"
          @keyup.enter.native="handleLogin"/>
  • class="yuan":将该输入框的 CSS 类设置为“yuan”。
  • ref="username":使用ref属性来在 JavaScript 中访问该组件的实例,可以在组件上使用this.$refs.username来获取该输入框的引用。
  • v-model="loginForm.username":将该输入框的值与Vue实例中的loginForm.username属性进行双向绑定。当输入框的值发生变化时,loginForm.username的值也会相应地更新。
  • placeholder="请输入用户名":在输入框中显示占位符文本,为用户提供输入提示。
  • name="username"name="password":设置该输入框的名称属性,这个属性在表单提交时会作为字段的名称。
  • type="text":指定输入框的类型为文本类型。
  • tabindex="1"tabindex="2":为该输入框设置一个tab键的顺序,用于指定当用户按下 tab 键时,该输入框的焦点将移动到哪个输入框或其他元素。
  • auto-complete="on":指定浏览器启用自动完成功能,可以让浏览器记住用户在该输入框中输入的值,并在以后的输入中为用户提供选择。
  • @keyup.enter.native="handleLogin" - 它使用 Vue 的事件监听器语法,当用户在组件中按下回车键时,会调用组件的handleLogin方法。@符号表示这是一个事件监听器,keyup.enter.native表示监听回车键的keyup事件,.native表示监听原生的 DOM 事件而非 Vue 的封装事件。
属性说明
type类型(text,textarea 和其他 原生 input 的 type 值
v-model数据双向绑定
maxlength最大输入长度
minlength最小输入长度
name名称属性
auto-complete自动补全(on/off)
readonly是否只读(false/true)
tabindex给输入框设置一个tab键的顺序
1.2.3 Select 选择器(列表框)
<el-select v-model="loginForm.isadmin" placeholder="请选择" style="width: 418px">
          <el-option :key="1" label="管理员" :value="1"></el-option>
          <el-option :key="0" label="读者" :value="0"></el-option>
</el-select>
  • v-model="loginForm.isadmin":这个属性将el-select组件的选择结果绑定到loginForm.isadmin变量上,当用户选择一个选项时,这个变量的值会被更新。这里的loginForm是一个对象,isadmin是它的一个属性。
  • placeholder="请选择":这个属性指定了在下拉框没有选择任何选项时显示的提示文字。
  • style="width: 418px":这个属性指定了下拉框的宽度。
  • :key="1":key="0":这个属性用于指定每个el-option组件的唯一标识符。在这里,我们使用了:key指令,将10这两个值绑定到了每个组件的key属性上。这样做的好处是可以提高组件的渲染效率。
  • label="管理员"label="读者":这个属性指定了每个选项在下拉框中显示的文本。
  • :value="1":value="0":这个属性指定了每个选项对应的值。当用户选择一个选项时,v-model指令绑定的变量的值会被更新为这个值。在这里,我们将管理员的值设置为1,将读者的值设置为0

◼ select 属性

属性说明
v-model绑定值
multiple是否多选(false/true)
multiple-limit多选时用户最多可以选择的项目数,为 0 则不限制
disabled是否禁用(false/true)
clearable是否可以清空选项(false/true)
filterable是否可搜索(false/true)
allow-create是否允许用户创建新条目,需配合 filterable 使用
remote是否为远程搜索(false/true)

◼ option 属性

属性说明
value选项的值
label选项的标签,若不设置则默认与 value 相同
disabled是否禁用该选项(false/true)

使用el-option-group对备选项进行分组,它的label属性为分组名

<el-option-group label="分组">
    <el-option> </el-option>
    ....
</el-option-group>
1.2.4 Button 按钮
<el-button :loading="loading" type="primary" style="width: 48%; float: left;" @click.native.prevent="handleLogin">登录</el-button>

<el-button :loading="loading" type="success" style="width: 48%; float: right;" @click.native.prevent="handleRegister">注册</el-button>
  • :loading="loading":这是用于将loading变量的值绑定到按钮的loading属性上。在这种情况下,loading变量决定了按钮是否处于加载状态。

  • type="primary"type="success":这是按钮的类型属性,决定了按钮的颜色和样式。在这种情况下,第一个按钮的类型为“primary”,第二个按钮的类型为“success”。

  • style="width: 48%; float: left;"style="width: 48%; float: right;":设置按钮的宽度和浮动位置。在这种情况下,第一个按钮的宽度为父元素的48%,并浮动到左侧,第二个按钮的宽度为父元素的48%,并浮动到右侧。

  • @click.native.prevent="handleLogin"@click.native.prevent="handleRegister":事件绑定,用于在点击按钮时调用一个特定的函数。第一个按钮被点击时调用handleLogin函数,第二个按钮被点击时调用handleRegister函数。@click.native表示该事件不需要经过组件的事件处理器就可以直接触发,.prevent表示在触发事件时阻止默认的行为。

属性说明
disabled是否禁用状态(false/true)
icon图标类名
loading是否加载中状态(false/true)
size尺寸(medium / small / mini)
type类型(primary / success / warning / danger / info / text)
plain是否朴素按钮(false/true)
round是否圆角按钮(false/true)
circle是否圆形按钮(false/true)

使用<el-button-group>标签来嵌套你的按钮。

<el-button-group>
    <el-button> </el-button>
    ...
</el-button-group>
1.3 与后台交互

◼ view > login > index.vue

handleLogin() { //登录(113~129行)
    this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true
          this.$store.dispatch('user/login', this.loginForm).then(() => { //向后台请求
            this.$router.push({ path: '/' })  //请求成功,进首页
            this.loading = false
          }).catch((message) => {  //请求失败,捕获错误信息
            this.$message.error(message)
            this.loading = false
          })
        } else {
          console.log('不允许提交!')
          return false
        }
    })
}
handleRegister() { //注册(130~133行)
    console.log("注册按钮")
    this.$router.push({ path: '/register' })  // 进注册页面
}
  • handleLogin()首先调用了$refs.loginForm.validate方法验证表单数据的有效性,该方法接收一个回调函数valid作为参数,valid 参数表示表单数据是否有效。如果表单数据有效,将 loading 标志变量设为 true ,接着调用$store.dispatch方法触发’user/login’ action 进行登录请求,并在请求成功后导航到首页。如果请求失败,则弹出错误提示,最后将 loading 标志变量设为 false 。如果表单数据无效,则在控制台输出"不允许提交!"信息,并返回 false 。

  • $store.dispatch方法返回一个Promise对象,用于处理异步操作的结果。可以通过then方法处理请求成功的结果,或者通过catch方法处理请求失败的结果。在Vue组件中,可以通过组件的$store属性访问store对象,并使用​$store.dispatch方法触发action。

// 在Vue组件中触发action
this.$store.dispatch('fetchUser', payload对象).then(user => {
// 请求成功后的处理逻辑
}).catch(error => {
// 请求失败后的处理逻辑
})
  • $router.push方法接收一个路由对象作为参数,该对象包含了要导航到的路由的路径、参数、查询参数等信息。在Vue组件中,可以通过组件的$router属性访问Vue Router实例,并使用$router.push方法进行页面跳转。
// 在Vue组件中跳转到/about路由
this.$router.push('/about')

// 在Vue组件中跳转到/about路由,并通过query属性传递了一个id参数
this.$router.push({ path: '/about', query: { id: 123 }})

api > user.js (前后端交互的关键)

import request from '@/utils/request'
// 向后端发起登录和注册请求
// 登录(4~10行)
export function login(data) {
  return request({
    url: '/user/login',      //请求的URL
    method: 'post',          //请求的方法
    data                     //请求的参数
  })
}
// 注册(31~37行)
export function register(params) {
  return request({
    url: '/user/register',
    method: 'post',
    params
  })
}
  • request()函数:使用了 request 函数来发起请求,request 函数是在 @/utils/request 中定义的,是一个 Axios 实例或封装的 Ajax 请求,可以看做是发送 HTTP 请求的工具函数。因为该函数返回的是一个 Promise 对象,因此可以使用 then 方法来处理请求成功时的逻辑,使用 catch 方法来处理请求失败时的逻辑。

  • login()函数:在这个函数中,最终使用了 request 函数发起了一个 POST 请求,请求的数据是 data,它包含了用户的登录信息,比如用户名和密码。服务器会根据这些信息验证用户身份,并返回相应的登录状态。函数的返回值是一个 Promise 对象,表示异步操作的结果。当 Promise 对象被成功地解析时,我们可以得到服务器返回的数据。当 Promise 对象被拒绝时,我们可以得到一个错误对象,它包含了错误信息。

rooter > index.js (路由和页面的映射关系)

import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/layout'
Vue.use(Router)

export const constantRoutes = [
    {
        //主页界面(52~62行)
        path: '/',       //路由路径
        component: Layout,   //导入主页面布局组件
        redirect: '/dashboard',
        children: [{    //在其内部嵌套了一个子路由
            path: 'dashboard',
            name: 'Dashboard',
            component: () => import('@/views/dashboard/index'),   //导入主页组件
            meta: { title: '首页', icon: 'dashboard' }  //路由元信息
         }]
    },
    {
        //注册界面(40~44行)
        path: '/register',     //路由路径
        component: () => import('@/views/register/index'),   //导入注册组件
        hidden: true
    }
]
  • **path:**表示该路由的访问路径。
  • **component:**表示该路由对应的组件,即访问该路径时将会渲染该组件。
  • **redirect:**表示路由重定向,即访问该路由路径时,将会被重定向到指定的路径。
  • **children:**表示该路由下嵌套的子路由。
  • **name:**表示该路由的名称,用于在程序中进行路由跳转。
  • **meta:**表示该路由的元信息,可以在页面中使用该信息来展示不同的样式或其他效果。
  • **hidden:**表示该路由是否在菜单栏中显示。若为 true,则不会在菜单栏中显示。

◼ 后端配置(application.properties)

image-20230301111332661

◼ 前端配置(request.js)

image-20230301111408066


2. Vue 常见属性和生命周期

2.1 属性
2.1.1 data
  • 功能:用于定义组件内部的数据。
  • 场景:当需要在组件内部定义数据时,可以使用 data 属性。
<div>{{ message }}</div> 
data: function () {
    return {
      message: 'Hello, Vue!'
    }
}
2.1.2 props
  • 功能:用于从父组件向子组件传递数据。
  • 场景:当需要从一个父组件向它的子组件传递数据时,可以使用 props 属性。
<MyTest message="hello"/>   <!--父组件-->
name:"MyTest",
props: ["message"]    //子组件
2.1.3 computed
  • 功能:用于定义计算属性。
  • 场景:当需要根据现有的数据动态计算新的数据时,可以使用 computed 属性。
<div>{{ reversedMessage }} </div> 
computed: {
    reversedMessage() {
      return this.message.split('').reverse().join('')
    }
}
2.1.4 methods
  • 功能:用于定义组件内部的方法。
  • 场景:当需要在组件内部定义一些方法时,可以使用 methods 属性。这些方法可以在模板中使用v-on指令来调用
<button v-on:click="reverseMessage">Reverse Message</button> 
 methods: {
    reverseMessage () {
      this.message = this.message.split('').reverse().join('')
    }
 }
2.1.5 watch
  • 功能:用于监听数据的变化并执行相应的回调函数。
  • 场景:当需要在数据发生变化时执行一些操作时,可以使用 watch 属性。
<div>{{ message }}</div>
<button @click="reverseMessage">Reverse Message</button>
watch: {
    message(newVal,oldVal) {
        console.log('The message has changed from ' + oldVal + ' to ' + newVal)
    }
}
2.1.6 filters
  • 功能:用于定义可复用的文本转换函数。
  • 场景:当需要对文本进行过滤或格式化时,可以使用 filters 属性。
<div>{{ message | capitalize }}</div>
data: {
    message: 'hello world'
}, 
filters: {
    capitalize(value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)  //Hello world
    }
}

message 属性后面使用符号 ‘|’ 来调用过滤器函数

2.1.7 directives
  • 功能:用于自定义指令,可以修改 DOM 的行为。
  • 场景:当需要自定义一些指令来修改 DOM 的行为时,可以使用 directives 属性。
<div id="app">
  <input v-focus>   <!--使用自定义指令-->
</div>
el: '#app',
directives: {
    focus: {  //自定义指令
        inserted: function (el) {
            el.focus();
        }
    }
}

**定义一个名为 focus 的自定义指令,并为它指定了一个钩子函数 inserted 。**inserted 函数将在元素插入到DOM中时调用。在这个例子中,我们在inserted函数中调用了元素的 focus 方法,以使该元素获得焦点。使用 v-focus 指令将这个自定义指令应用到了一个输入框元素上。最终,在页面上渲染出的输入框元素将自动获得焦点,用户可以直接在输入框中输入内容。

2.2 生命周期

image-20230301152422649

2.2.1 beforeCreate
  • 功能:会在实例初始化完成、props 解析之后、data()computed 等选项处理之前立即调用。(在实例初始化之后、数据观测之前被调用。)
  • 场景:当需要在实例被创建之前执行一些操作时,可以使用 beforeCreate 生命周期方法。
<p>{{ message }}</p>
beforeCreate() {
    console.log("组件实例被创建之前");
    this.message = "组件实例被创建之前";   //data()还没调用,message 数据还没有被初始化
},
data() {
    return {
      message: "Hello, Vue.js",
    };
}

image-20230301154930816

2.2.2 created
  • 功能:在实例创建完成后被立即调用,实例已完成以下的配置:数据观测,属性和方法的运算,watch/event 事件回调。
  • 场景:当需要在实例创建之后执行一些操作时,可以使用 created 生命周期方法。
<p>{{ message }}</p>
created() {
    console.log("组件实例已经被创建");
    this.message = "组件实例已经被创建";
},
data() {
    return {
      message: "Hello, Vue.js",
    };
}

image-20230301155540497

2.2.3 beforeMount
  • 功能:组件实例即将被挂载到页面上之前被调用:相关的 render 函数首次被调用。
  • 场景:当需要在组件挂载到 DOM 之前执行一些操作时,可以使用 beforeMount 生命周期方法。
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  beforeMount() {
    console.log("组件即将被挂载到页面上");
  },
  data() {
    return {
      message: "Hello, Vue.js",
    };
  },
};
</script>
2.2.4 mounted
  • 功能:在实例挂载后被调用,这时候组件 DOM 已经渲染完成。
  • 场景:当需要在组件挂载到 DOM 之后执行一些操作时,可以使用 mounted 生命周期方法。
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  mounted() {
    console.log("组件已经被挂载到页面上");
  },
  data() {
    return {
      message: "Hello, Vue.js",
    };
  },
};
</script>
2.2.5 beforeUpdate
  • 功能:在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁之前。
  • 场景:当需要在数据更新之前执行一些操作时,可以使用 beforeUpdate 生命周期方法。
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="updateMessage">更新消息</button>
  </div>
</template>

<script>
export default {
  beforeUpdate() {
    console.log("组件即将被更新");
  },
  data() {
    return {
      message: "Hello, Vue.js",
    };
  },
  methods: {
    updateMessage() {
      this.message = "Hello, World!";
    },
  },
};
</script>
2.2.6 updated
  • 功能:在数据更新之后被调用,发生在虚拟 DOM 重新渲染和打补丁之后。
  • 场景:当需要在数据更新之后执行一些操作时,可以使用 updated 生命周期方法。
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="updateMessage">更新消息</button>
  </div>
</template>

<script>
export default {
  updated() {
    console.log("组件已经更新完毕");
  },
  data() {
    return {
      message: "Hello, Vue.js",
    };
  },
  methods: {
    updateMessage() {
      this.message = "Hello, World!";
    },
  },
};
</script>

image-20230301162329275

2.2.7 activated
  • 功能:被 keep-alive 缓存的组件激活时调用。
  • 场景:当需要在 keep-alive 缓存的组件激活时执行一些操作时,可以使用 activated 生命周期方法。
2.2.8 deactivated
  • 功能:被 keep-alive 缓存的组件停用时调用。
  • 场景:当需要在 keep-alive 缓存的组件停用时执行一些操作时,可以使用 deactivated 生命周期方法。
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: "Hello, Vue.js",
      timer: null,
    };
  },
  mounted() {
    this.timer = setInterval(() => {
      this.message = new Date().toLocaleTimeString();
    }, 1000);
  },
  activated() {
    console.log("组件被激活");
    this.timer = setInterval(() => {
      this.message = new Date().toLocaleTimeString();
    }, 1000);
  },
  deactivated() {
    console.log("组件被停用");
    clearInterval(this.timer);
  },
};
</script>
2.2.9 beforeDestroy
  • 功能:在实例销毁之前调用。在这一步,实例仍然完全可用。
  • 场景:当需要在实例销毁之前执行一些操作时,可以使用 beforeDestroy 生命周期方法。
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: "Hello, Vue.js",
      timer: null,
    };
  },
  mounted() {
    this.timer = setInterval(() => {
      this.message = new Date().toLocaleTimeString();
    }, 1000);
  },
  beforeDestroy() {
    console.log("组件即将被销毁");
    clearInterval(this.timer);
  },
};
</script>
2.2.10 destroyed
  • 功能:在实例销毁之后调用。这个时候,实例已经被完全销毁,无法访问。
  • 场景:当需要在实例销毁之后执行一些操作时,可以使用 destroyed 生命周期方法。
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: "Hello, Vue.js",
    };
  },
  mounted() {
    this.timer = setInterval(() => {
      this.message = new Date().toLocaleTimeString();
    }, 1000);
  },
  destroyed() {
    console.log("组件已被销毁");
    clearInterval(this.timer);
  },
};
</script>
2.2.11 errorCaptured
  • 功能:当捕获一个来自子孙组件的错误时被调用。
  • 场景:当需要捕获来自子孙组件的错误时,可以使用 errorCaptured 生命周期方法。
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="throwError">Throw Error</button>
    <child-component></child-component>
  </div>
</template>

<script>
import ChildComponent from "@/components/ChildComponent";

export default {
  components: {
    ChildComponent,
  },
  data() {
    return {
      message: "Hello, Vue.js",
    };
  },
  methods: {
    throwError() {
      throw new Error("An error occurred in the parent component");
    },
  },
  errorCaptured(error, vm, info) {
    console.log("子组件发生了错误:", error);
    console.log("错误信息:", info);
    return false; // 防止错误继续向上传递
  },
};
</script>

3. 自定义事件的设计与后端接口

view > bookinfo > index.vue

<template slot-scope="scope">
    <el-button v-permission="['admin']" 
               @click="handleUpdate(scope.row)" 
               type="primary" size="small">编辑
    </el-button>
</template>

<el-dialog :title="formTitle" :visible.sync="dialogFormVisible" width="40%">
    <div> 表单框(略)</div>
</el-dialog>
// 点击编辑记录(334~355行)
handleUpdate(row) {
    // 从服务器获取所有的图书类型
    queryBookTypes().then(res => {   
      // res存储queryBookTypes()的返回值,即从服务器获取的所有图书类型
      console.log('图书类型获取成功',res)
      this.typeData = res
    })
    // 表单是编辑状态
    this.formType = 1
    // 将行数据置入form
    this.form = {
      bookid: row.bookid,
      bookname: row.bookname,
      bookauthor: row.bookauthor,
      bookprice: row.bookprice,
      booktypeid: row.booktypeid,
      bookdesc: row.bookdesc,
      isborrowed: row.isborrowed,
      bookimg: row.bookimg
    }
    // 显示表单框
    this.dialogFormVisible = true
}

image-20230302112659424
api > booktype.js

// 查询所有图书类型(12~17行)
export function queryBookTypes() {
    return request({  // 用 request 向后台发起请求
        // 请求的 URL
        url: '/bookType/queryBookTypes',   
        //请求的方法
        method: 'get'  
    })
}

utils > request.js

import axios from 'axios'
import { Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'

// 创建axios实例
const service = axios.create({
  baseURL: 'http://localhost:8092/BookManager/',// url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
})

// 请求拦截器
service.interceptors.request.use(
  config => {
    // 在发送请求之前做一些操作
    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['X-Token'] = getToken()
    }
    return config
  },
  error => {
    // 处理请求错误
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
  */

  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  response => {
    const res = response.data
    return res
  },
  error => {
    console.log('err' + error) // for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

export default service
  • **import 语句:**用于导入需要的模块和函数。这里分别导入了 Axios 库、element-ui 中的 Message 组件、一个自定义的 store 对象以及一个名为 getToken 的自定义函数。
  • **axios.create() 方法:**用于创建一个 Axios 实例,其中的配置选项将应用于该实例的所有请求。在这个例子中,baseURL 设置为 http://localhost:8092/BookManager/,这意味着所有请求的 URL 都将以这个字符串为前缀。timeout 设置为 5000,表示如果请求超过 5 秒未返回,则请求将被中断。
  • **service.interceptors.request.use() 方法:**用于注册一个请求拦截器函数。这个函数将在每个请求发送之前被调用,用于检查是否存在 token 并将其添加到请求头中,以便在服务器端验证身份。如果请求发送时出现错误,请求拦截器将使用 Promise.reject() 将错误传递给响应拦截器。
  • **service.interceptors.response.use() 方法:**用于注册一个响应拦截器函数。这个函数将在每个响应被接收时被调用,用于检查响应数据中的状态码,如果存在错误,则会使用 Message 组件将错误信息显示在界面上。如果没有错误,则响应拦截器将解析响应并将其返回。
  • **export default service语句 :**将创建的 Axios 实例导出,以便在其他文件中使用该实例发送 HTTP 请求。
;