玖叶教程网

前端编程开发入门

VUE-武装你的项目(vue自带webpack)

1. 接口模块处理

1.1 axios二次封装

这里封装的依据是后台传的JWT,已封装好的请跳过。

import axios from 'axios'
import router from '../router'
import {MessageBox, Message} from 'element-ui'
let loginUrl = '/login'
// 根据环境切换接口地址
axios.defaults.baseURL = process.env.VUE_APP_API
axios.defaults.headers = {'X-Requested-With': 'XMLHttpRequest'}
axios.defaults.timeout = 60000
// 请求拦截器
axios.interceptors.request.use(
 config => {
 if (router.history.current.path !== loginUrl) {
 let token = window.sessionStorage.getItem('token')
 if (token == null) {
 router.replace({path: loginUrl, query: {redirect: router.currentRoute.fullPath}})
 return false
 } else {
 config.headers['Authorization'] = 'JWT ' + token
 }
 }
 return config
 }, error => {
 Message.warning(error)
 return Promise.reject(error)
 })

紧接着的是响应拦截器(即异常处理)

axios.interceptors.response.use(
 response => {
 return response.data
 }, error => {
 if (error.response !== undefined) {
 switch (error.response.status) {
 case 400:
 MessageBox.alert(error.response.data)
 break
 case 401:
 if (window.sessionStorage.getItem('out') === null) {
 window.sessionStorage.setItem('out', 1)
 MessageBox.confirm('会话已失效! 请重新登录', '提示', {confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning'}).then(() => {
 router.replace({path: loginUrl, query: {redirect: router.currentRoute.fullPath}})
 }).catch(action => {
 window.sessionStorage.clear()
 window.localStorage.clear()
 })
 }
 break
 case 402:
 MessageBox.confirm('登陆超时 !', '提示', {confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning'}).then(() => {
 router.replace({path: loginUrl, query: {redirect: router.currentRoute.fullPath}})
 })
 break
 case 403:
 MessageBox.alert('没有权限!')
 break
 // ...忽略
 default:
 MessageBox.alert(`连接错误${error.response.status}`)
 }
 return Promise.resolve(error.response)
 }
 return Promise.resolve(error)
})

这里做的处理分别是会话已失效和登陆超时,具体的需要根据业务来作变更。

最后是导出基础请求类型封装。

export default {
 get (url, param) {
 if (param !== undefined) {
 Object.assign(param, {_t: (new Date()).getTime()})
 } else {
 param = {_t: (new Date()).getTime()}
 }
 return axios({method: 'get', url, params: param})
 },
 // 不常更新的数据用这个
 getData (url, param) {
 return axios({method: 'get', url, params: param})
 },
 post (url, param, config) {
 return axios.post(url, param, config)
 },
 put: axios.put,
 _delete: axios.delete
}

其中给get请求加上时间戳参数,避免从缓存中拿数据。 除了基础请求类型,还有很多类似下载、上传这种,需要特殊的的请求头,此时可以根据自身需求进行封装。

浏览器缓存是基于url进行缓存的,如果页面允许缓存,则在一定时间内(缓存时效时间前)再次访问相同的URL,浏览器就不会再次发送请求到服务器端,而是直接从缓存中获取指定资源。

1.2 请求按模块合并

模块的请求:import http from '@/utils/request'
export default {
 A (param) { return http.get('/api/', param) },
 B (param) { return http.post('/api/', param) }
 C (param) { return http.put('/api/', param) },
 D (param) { return http._delete('/api/', {data: param}) },
}

utils/api/index.js:

import http from '@/utils/request'
import account from './account'
// 忽略...
const api = Object.assign({}, http, account, \*...其它模块*\)
export default api

1.3 global.js中的处理

在global.js中引入:

import Vue from 'vue'
import api from './api/index'
// 略...
const errorHandler = (error, vm) => {
 console.error(vm)
 console.error(error)
}
Vue.config.errorHandler = errorHandler
export default {
 install (Vue) {
 // 添加组件
 // 添加过滤器
 })
 // 全局报错处理
 Vue.prototype.$throw = (error) => errorHandler(error, this)
 Vue.prototype.$http = api
 // 其它配置
 }
}

写接口的时候就可以简化为:

async getData () {
 const params = {/*...key : value...*/}
 let res = await this.$http.A(params)
 res.code === 4000 ? (this.aSata = res.data) : this.$message.warning(res.msg)
}

2. Vue组件动态注册

我们写组件的时候通常需要引入另外的组件:

<template>
 <BaseInput v-model="searchText" @keydown.enter="search"/>
 <BaseButton @click="search">
 <BaseIcon name="search"/>
 </BaseButton>
</template>
<script>
 import BaseButton from './baseButton'
 import BaseIcon from './baseIcon'
 import BaseInput from './baseInput'
 export default {
 components: { BaseButton, BaseIcon, BaseInput }
 }
</script>

写小项目这么引入还好,但等项目一臃肿起来...啧啧。 这里是借助webpack,使用 require.context() 方法来创建自己的模块上下文,从而实现自动动态require组件。

这个方法需要3个参数:

  • 要搜索的文件夹目录
  • 是否还应该搜索它的子目录
  • 一个匹配文件的正则表达式。

在你放基础组件的文件夹根目录下新建componentRegister.js:

import Vue from 'vue'
/**
 * 首字母大写
 * @param str 字符串
 * @example heheHaha
 * @return {string} HeheHaha
 */
function capitalizeFirstLetter (str) {
 return str.charAt(0).toUpperCase() + str.slice(1)
}
/**
 * 对符合'xx/xx.vue'组件格式的组件取组件名
 * @param str fileName
 * @example abc/bcd/def/basicTable.vue
 * @return {string} BasicTable
 */
function validateFileName (str) {
 return /^\S+\.vue$/.test(str) &&
 str.replace(/^\S+\/(\w+)\.vue$/, (rs, $1) => capitalizeFirstLetter($1))
}
const requireComponent = require.context('./', true, /\.vue$/)
// 找到组件文件夹下以.vue命名的文件,如果文件名为index,那么取组件中的name作为注册的组件名
requireComponent.keys().forEach(filePath => {
 const componentConfig = requireComponent(filePath)
 const fileName = validateFileName(filePath)
 const componentName = fileName.toLowerCase() === 'index'
 ? capitalizeFirstLetter(componentConfig.default.name)
 : fileName
 Vue.component(componentName, componentConfig.default || componentConfig)
})

最后我们在main.js中

import 'components/componentRegister.js'

我们就可以随时随地使用这些基础组件,无需手动引入了。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言