springboot+vue网站开发02-前端页面的渲染代码展示!经过上面2个小节的分享,我们已经准备好了前端渲染所需要的数据接口了。可以给大家正常返回新闻分类的信息了。
下面给大家看看,前端vue网站开发的代码,已经渲染的业务流程是什么。
如图,我们查看了package.json内容,里面告诉我们,该前端项目,调用了哪些插件。
比如大家熟悉的,路由,以及状态管理插件vuex。前端布局ui插件element-ui,前端http请求插件axios等等。
路由里设置的,默认调用了Home.vue插件,渲染我们的首页信息。
<!-- 首页 -->
<template>
<div>
<sg-navbar></sg-navbar>
<div class="container">
<el-row :gutter="30">
<el-col :sm="24" :md="16" style="transition:all .5s ease-out;margin-bottom:30px;">
<sg-articlelist></sg-articlelist>
</el-col>
<el-col :sm="24" :md="8" >
<sg-rightlist></sg-rightlist>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
import header from '../components/header.vue'
import articlelist from '../components/articlelist.vue'
import rightlist from '../components/rightlist.vue'
export default {
name:'Home',
data() { //选项 / 数据
return {
}
},
methods: { //事件处理器
},
components: { //定义组件
'sg-navbar':header,
'sg-articlelist':articlelist,
'sg-rightlist':rightlist,
},
created() { //生命周期函数
}
}
</script>
<style>
</style>
里面写了2个组件,分别对应,导航组件,新闻列表组件,右侧热点新闻 组件。三个组件,给它起了一个别名:映射。在模板代码里就可以使用这个别名来当做标签使用了。
这个项目的代码风格是传统的风格(vue2,选项式编码风格。)
<el-submenu index="/Share">
<template slot="title"><i class="fa fa-wa fa-archive"></i> 分类</template>
<el-menu-item v-for="(item,index) in classListObj" :key="'class1'+index" :index="'/Share?classId='+item.id">{{item.name}}</el-menu-item>
</el-submenu>
在header头部组件内,有我们想要的导航栏信息,使用了是elementUI的标签。
elementUI对这个嵌套菜单的样式设计,渲染的时候有要求。比如:<!-- index 和key 必须要转成字符串,不然控制台会报错-->
这都是vue2选项式开发风格,不再过多的介绍了。看不懂的话,可以去看我的vue2专栏学习一下。
import request from '@/utils/request'
// 查询分类列表
export function getCategoryList() {
return request({
url: '/category/getCategoryList',
headers: {
isToken: false
},
method: 'get'
})
}
业务请求api接口封装好了,在一个
里面,调用了axios的信息完成统一请求风格。
如图所示,后端的控制器内部路径设置,和前端请求路径信息保持一致。即可。
axios里面,关于服务器基础地址baseURL.我之前学习时犯了错,这个必须严格按照官方要求写好,大小写字母不允许自己乱改,只能是这个样子的。
import axios from 'axios'
import { Notification, MessageBox, Message } from 'element-ui'
import router from '@/router'
import store from '../store'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: store.state.baseURL,
// 超时
timeout: 10000
})
// request拦截器
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
if (getToken() && !isToken) {
config.headers['token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?'
for (const propName of Object.keys(config.params)) {
const value = config.params[propName]
var part = encodeURIComponent(propName) + '='
if (value !== null && typeof (value) !== 'undefined') {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
if (value[key] !== null && typeof (value[key]) !== 'undefined') {
const params = propName + '[' + key + ']'
const subPart = encodeURIComponent(params) + '='
url += subPart + encodeURIComponent(value[key]) + '&'
}
}
} else {
url += part + encodeURIComponent(value) + '&'
}
}
}
url = url.slice(0, -1)
config.params = {}
config.url = url
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
if (code === 401) {
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
localStorage.setItem('logUrl', router.currentRoute.fullPath);
router.push({
path: '/Login?login=1'
});
}).catch(() => { })
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
Message({
message: msg,
type: 'error'
})
return Promise.reject(new Error(msg))
} else if (code !== 200) {
Notification.error({
title: msg
})
return Promise.reject('error')
} else {
// 把字符串total 转换成 数字 total
if (res.data.data && res.data.data.total) {
res.data.data.total = parseInt(res.data.data.total)
}
return res.data.data
}
},
error => {
console.log('err' + error)
let { message } = error
if (message === 'Network Error') {
message = '后端接口连接异常'
} else if (message.includes('timeout')) {
message = '系统接口请求超时'
} else if (message.includes('Request failed with status code')) {
message = '系统接口' + message.substr(message.length - 3) + '异常'
}
Message({
message: message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service
可以看见,把基础地址封装到了状态管理里面去了。
import Vue from 'vue'
import Vuex from 'vuex'
// import * as getters from './getters.js'
Vue.use(Vuex)
/** 状态定义 */
export const state = {
loading: false,
themeObj: 0,//主题
keywords:'',//关键词
errorImg: 'this.onerror=null;this.src="' + require('../../static/img/tou.jpg') + '"',
baseURL:'http://localhost:7777/'
}
export default new Vuex.Store({
state,
})
里面还写了一些认证的内容,不做过多的介绍了。
到此为止,我们就已经完成了前端页面请求后端接口,渲染前端页面分类导航栏信息的目的了。