1. Nuxt.js 概述
1.1 我们一起做过的SPA
-
SPA(single page web application)单页 Web 应用,Web 不再是一张张页面,而是一个整体的应用,一个由路由系统、数据系统、页面(组件)系统等等,组成的应用程序。
-
SPA 应用广泛用于对SEO要求不高的场景中
1.2 什么是SEO
-
SEO:搜索引擎优化(Search Engine Optimization), 通过各种技术(手段)来确保,我们的Web内容被搜索引擎最大化收录,最大化提高权重,最终带来更多流量。
-
非常明显,SPA程序不利于SEO
-
SEO解决方案:提前将
页面和数据
进行整合- 前端:采用SSR
- 后端:页面静态化 (freemarker 、thymeleaf、velocity)
1.3 什么是SSR技术
- 服务端渲染(Server Side Render),即:网页是通过服务端渲染生成后输出给客户端。
- 在SSR中,前端分成2部分:前端客户端、前端服务端
- 前端服务端,用于发送ajax,获得数据
- 前端客户端,用于将ajax数据和页面进行渲染,渲染成html页面,并响应给调用程序(浏览器、爬虫)
- 如果爬虫获得html页面,就可以启动处理程序,处理页面内容,最终完成SEO操作。
1.4 SPA和SSR对比
SPA单页应用程序 | SSR服务器端渲染 | |
---|---|---|
优势 | 1.页面内容在客户端渲染 2. 只关注View层,与后台耦合度低,前后端分离 3.减轻后台渲染画面的压力 | 1.更好的SEO,搜索引擎工具可以直接查看完全渲染的画面 2.更快的内容到达时间 (time-to-content),用户能更快的看到完整渲染的画面 |
劣势 | 1.首屏加载缓慢 2.SEO(搜索引擎优化)不友好 | 1.更多的服务器端负载 2.涉及构建设置和部署的更多要求,需要用Node.js渲染 3.开发条件有限制,一些生命周期将失效 4.一些常用的浏览器API无法使用 |
1.5 什么是Nuxt.js
- Nuxt.js 是一个基于 Vue.js 的通用应用框架。
- 通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI 渲染。
- Nuxt.js 预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置。
2 入门案例
2.1 create-nuxt-app 介绍
-
Nuxt.js 提供了脚手架工具
create-nuxt-app
-
create-nuxt-app
需要使用npx
-
npx 命令为 NPM版本5.2.0默认安装组件
2.2 安装
npx create-nuxt-app <project-name>
- 例如
npx create-nuxt-app demo_nuxt02
-
nuxtjs改善
2.3 启动
npm run dev
2.4 访问
http://localhost:3000
3. 目录结构
3.1 目录
目录名称 | 描述 |
---|---|
assets | 资源目录,用于存放需要编译的静态资源。例如:LESS、SASS等 默认情况下,Nuxt使用Webpack若干加载器处理目录中的文件 |
components | vue组件目录,Nuxt.js 不会增强该目录,及不支持SSR |
layouts | 布局组件目录 |
pages | 页面目录,所有的vue视图,nuxt根据目录结构自动生成对应的路由。 |
plugins | 插件目录 |
static | 静态文件目录,不需要编译的文件 |
store | vuex目录 |
nuxt.config.js | nuxt个性化配置文件,内容将覆盖默认 |
package.json | 项目配置文件 |
3.2 别名
-
assets 资源的引用:~ 或 @
// HTML 标签 <img src="~assets/13.jpg" style="height:100px;width:100px;" alt=""> <img src="~/assets/13.jpg" style="height:100px;width:100px;" alt=""> <img src="@/assets/13.jpg" style="height:100px;width:100px;" alt=""> // CSS background-image: url(~assets/13.jpg); background-image: url(~/assets/13.jpg); background-image: url(@/assets/13.jpg);
-
static 目录资源的引用:/ 直接引用
//html标签 <img src="/12.jpg" style="height:100px;width:100px;" alt=""> //css background-image: url(/12.jpg);
-
实例
<template> <div> <!-- 引用 assets 目录下经过 webpack 构建处理后的图片 --> <img src="~assets/13.jpg" style="height:100px;width:100px;" alt=""> <!-- 引用 static 目录下的图片 --> <img src="/12.jpg" style="height:100px;width:100px;" alt=""> <!-- css --> <div class="img1"></div> <div class="img2"></div> </div> </template> <script> export default { } </script> <style> .img1 { height: 100px; width: 100px; background-image: url(~assets/13.jpg); background-size: 100px 100px; display: inline-block; } .img2 { height: 100px; width: 100px; background-image: url(/12.jpg); background-size: 100px 100px; display: inline-block; } </style>
4 路由
4.1 路由概述
- Nuxt.js 依据 pages 目录结构自动生成 vue-router 模块的路由配置。
- 要在页面之间切换路由,我们建议使用
<nuxt-link>
标签。
标签名 | 描述 |
---|---|
<nuxt-link> | nuxt.js中切换路由 |
<Nuxt /> | nuxt.js的路由视图 |
<router-link> | vue默认切换路由 |
<router-view/> | vue默认路由视图 |
4.2 基础路由
- 自动生成基础路由规则
路径 | 组件位置及其名称 | 规则 |
---|---|---|
/ | pages/index.vue | 默认文件 index.vue |
/user | pages/user/index.vue | 默认文件 index.vue |
/user/one | pages/user/one.vue | 指定文件 |
-
实例
情况1:访问路径,由pages目录资源的名称组成(目录名称、文件的名称) - 资源位置: ~/pages/user/one.vue - 访问路径:http://localhost:3000/user/one 情况2:每一个目录下,都有一个默认文件 index.vue - 资源位置: ~/pages/user/index.vue - 访问路径:http://localhost:3000/user
-
思考:
/user
可以匹配几种文件?pages/user.vue
文件 【优先级高】pages/user/index.vue
文件
4.3 动态路由
- 在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录。
路由中路径匹配 | 组件位置及其名称 |
---|---|
/ | pages/index.vue |
/user/:id | pages/user/_id.vue |
/:slug | pages/_slug/index.vue |
/:slug/comments | pages/_slug/comments.vue |
- 实例1:获得id值,创建资源
user/_id.vue
<template>
<div>
查询详情 {{this.$route.params.id}}
</div>
</template>
<script>
export default {
transition: 'test',
mounted() {
console.info(this.$route)
},
}
</script>
<style>
</style>
4.4 动态命名路由
-
路径
/news/123
匹配_id.vue
还是_name.vue
? -
我们可以使用
<nuxt-link>
解决以上问题- 通过name 确定组件名称:“xxx-yyy”
- 通过params 给对应的参数传递值
<nuxt-link :to="{name:'news-id',params:{id:1002}}">第2新闻</nuxt-link>
<nuxt-link :to="{name:'news-name',params:{name:1003}}">第3新闻</nuxt-link>
4.5 默认路由
路径 | 组件位置及其名称 |
---|---|
不匹配的路径 | pages/_.vue |
- 404页面,可以采用 _.vue进行处理
4.6 嵌套路由(了解)
-
创建嵌套子路由,你需要添加一个 父组件Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。
- 要求:父组件 使用
<nuxt-child/>
显示子视图内容
- 要求:父组件 使用
pages/
--| book/ //同名文件夹
-----| _id.vue
-----| index.vue
--| book.vue //父组件
-
步骤1:编写父组件
pages/child/book.vue
<template> <div> <nuxt-link to="/child/book/list">书籍列表</nuxt-link> | <nuxt-link to="/child/book/123">书籍详情</nuxt-link> | <hr> <nuxt-child /> </div> </template> <script> export default { } </script> <style> </style>
-
步骤2:编写子组件
pages/child/book/list.vue
<template> <div>书籍列表</div> </template> <script> export default { } </script> <style> </style>
-
步骤3:编写子组件
pages/child/book/_id.vue
<template> <div>书籍详情{{$route.params.id}} </div> </template> <script> export default { } </script> <style> </style>
4.7 过渡动效(了解)
4.7.1 全局过渡动效设置
-
Nuxt.js 默认使用的过渡效果名称为 page
.page-enter-active
样式表示进入的过渡效果。.page-leave-active
样式表示离开的过渡效果。
-
步骤1:创建
assets/main.css
,编写如下内容:
.page-enter-active, .page-leave-active {
transition: opacity .5s;
}
.page-enter, .page-leave-active {
opacity: 0;
}
- 步骤2:nuxt.config.js 引入main.css文件
module.exports = {
css: [
'assets/main.css'
]
}
4.7.1 自定义动画
-
如果想给某个页面自定义过渡特效的话,只要在该页面组件中配置
transition
字段即可: -
步骤1:在全局样式
assets/main.css
中添加名称为test
的过渡效果
.test-enter-active, .test-leave-active {
transition: all 2s;
font-size:12px;
}
.test-enter, .test-leave-active {
opacity: 0;
font-size:40px;
}
- 步骤2:需要使用特效的vue页面编写如下:
export default {
transition: 'test'
}
5. 视图
5.1 默认模板(了解)
-
定制化默认的 html 模板,只需要在应用根目录下创建一个 app.html 的文件。
-
默认模板:
<!DOCTYPE html> <html {{ HTML_ATTRS }}> <head {{ HEAD_ATTRS }}> {{ HEAD }} </head> <body {{ BODY_ATTRS }}> {{ APP }} </body> </html>
-
修改模板,对低版本IE浏览器进行支持(兼容IE浏览器)
<!DOCTYPE html> <!--[if IE 9]><html lang="en-US" class="lt-ie9 ie9" {{ HTML_ATTRS }}><![endif]--> <!--[if (gt IE 9)|!(IE)]><!--><html {{ HTML_ATTRS }}><!--<![endif]--> <head {{ HEAD_ATTRS }}> {{ HEAD }} </head> <body {{ BODY_ATTRS }}> {{ APP }} </body> </html>
5.2 默认布局【掌握】
5.2.1 布局概述
-
布局:Nuxt.js根据布局,将不同的组件进行组合。
-
模板:html页面,是布局后所有组件挂载的基础。
5.2.2 布局分析
- layouts/default.vue 默认布局组件
- 访问路径根据路由,确定执行组件
- 组件具体显示的位置,有布局来确定
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oK655tTp-1639705695557)(assets/image-20210428225159898.png)]
5.2.3 公共导航
- 修改
layouts/default.vue
<template>
<div>
<nuxt-link to="/">首页</nuxt-link> |
<nuxt-link to="/user/login">登录</nuxt-link> |
<nuxt-link to="/user/123">详情</nuxt-link> |
<nuxt-link to="/about">默认页</nuxt-link> |
<nuxt-link to="/nuxt/async">async</nuxt-link> |
<hr/>
<Nuxt />
</div>
</template>
5.3 自定义布局
-
在layouts目录下创建组件:layouts/blog.vue
<template> <div> 开头<br/> <nuxt/> 结束<br/> </div> </template> <script> export default { } </script> <style> </style>
-
在需要的视图中使用 blog布局
<script> export default { layout: 'blog' //... } </script>
5.4 错误页面
- 编写
layouts/error.vue
页面,实现个性化错误页面
<template>
<div>
<div v-if="error.statusCode == 404">
404 页面不存在 {{error.message}}
</div>
<div v-else>
应用程序错误
</div>
<nuxt-link to="/">首 页</nuxt-link>
</div>
</template>
<script>
export default {
props: ['error']
}
</script>
<style>
</style>
- 解决问题: 404 、500、连接超时(服务器关闭)
- 总结:所学习的技术中,有2种方式处理错误页面
- 方式1:默认路径,
_.vue
(先执行) - 方式2:错误页面,
~/layouts/error.vue
- 方式1:默认路径,
5.5 Nuxt组件特殊配置
- 页面组件实际上是 Vue 组件,只不过 Nuxt.js 为这些组件添加了一些特殊的配置项
特殊配置项 | 描述 |
---|---|
asyncData | SSR进行异步数据处理,也就是服务器端ajax操作区域。 |
fetch | 在渲染页面之前获取数据填充应用的状态树(store) |
head | 配置当前页面的 Meta 标签 |
layout | 指定当前页面使用的布局 |
transition | 指定页面切换的过渡动效 |
scrollToTop | 布尔值,默认: false。 用于判定渲染页面前是否需要将当前页面滚动至顶部。 |
5.5.1 模板代码
<template>
<h1 class="red">Hello {{ name }}!</h1>
</template>
<script>
export default {
//异步处理数据, 每次加载之前被调用
asyncData (context) {
// called every time before loading the component
return { name: 'World' }
},
//用于在渲染页面之前获取数据填充应用的状态树(store)
fetch () {
// The fetch method is used to fill the store before rendering the page
},
//配置当前页面的 Meta 标签
head: {
// Set Meta Tags for this Page
},
// and more functionality to discover
...
}
</script>
<style>
.red {
color: red;
}
</style>
5.5.2 head
-
html模板代码
<html> <head> <meta charset="UTF-8" /> <title>我是标题</title> <link rel="stylesheet" type="text/css" href="css外部文件"/> <script src="js外部文件" type="text/javascript" charset="utf-8"></script> </head> <body> </body> </html>
-
通过nuxt提供head属性,可以给单个也是设置:标题、外部css、外部js 等内容。
<template>
<div>
详情页 {{$route.params.id}} <br/>
<div class="bg2"></div>
<div class="bg3"></div>
</div>
</template>
<script>
export default {
head: {
title: '详情页',
link: [
{rel:'stylesheet',href:'/style/img.css'},....
],
script: [
{ type: 'text/javascript', src: '/js/news.js' }
]
}
}
</script>
<style>
.bg2 {
background-image: url('~static/img/2.jpg');
width: 300px;
height: 300px;
background-size: 300px;
}
</style>
6. ajax操作
6.1 整合 axios
6.1.1 默认整合
-
在构建项目时,如果选择axios组件,nuxt.js将自动与axios进行整合
6.1.2 手动整合(可选)
-
步骤1:package.json有axios的版本
"dependencies": {
"@nuxtjs/axios": "^5.13.1",
},
- 步骤2:安装
npm install
-
步骤3:nuxt.config.js 以模块的方式添加axios
modules: [
// https://go.nuxtjs.dev/axios
'@nuxtjs/axios',
],
6.1.3 常见配置
-
修改 nuxt.config.js 进行baseURL的配置
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
baseURL:'http://localhost:10010/'
},
6.2 使用axios发送ajax
- 在vue页面中,通过 this. a x i o s . x x x ( ) 操 作 a j a x 。 t h i s . axios.xxx() 操作ajax。this. axios.xxx()操作ajax。this.axios 与之前 axios等效。
this.$axios.post("/search-service/search",this.searchMap).then( res => {
//获得查询结果
this.searchResult = res.data.data;
});
6.3 使用asyncData发送 ajax
- asyncData中的ajax将在“前端服务端执行”,在浏览器看到是数据,而不是ajax程序。
6.3.1 发送一次请求
- 语法:
export default {
async asyncData( context ) { //context就相当于其他地方的this
//发送ajax
let { data } = await context.$axios.get('路径','参数')
// 返回结果
return {变量: 查询结果从data获取 }
},
}
-
实例
<template> <div>{{echo}}</div> </template> <script> export default { async asyncData(context) { // 发送ajax let {data} = await context.$axios.get('/service-consumer/feign/echo/abc') // 返回数据 return { echo: data } }, } </script> <style> </style>
6.3.2 发送多次请求
- 语法1:
export default {
async asyncData( content ) {
let [结果1,结果2] = await Promise.all([ ajax请求1, ajax请求2])
return {
变量1: 结果1,
变量2: 结果2
}
},
}
- 语法2:
export default {
async asyncData( content ) {
let [{数据:别名1},{数据:别名2}] = await Promise.all([ ajax请求1, ajax请求2])
return {
变量1: 别名1,
变量2: 别名2
}
},
}
- 实例
<template>
<div>{{echo}} {{echo2}}</div>
</template>
<script>
export default {
async asyncData(context) {
// 发送ajax
let [{data:echo}, {data:echo2}] =
await Promise.all([
context.$axios.get('/service-consumer/feign/echo/abc'),
context.$axios.get('/service-consumer/client/echo/abc')
])
// 返回数据
return {
echo,
echo2
}
},
}
</script>
<style>
</style>
6.4 使用fetch发送 ajax
- fetch 方法用于在渲染页面前填充应用的状态树(store)数据, 与 asyncData 方法类似,不同的是它不会设置组件的数据。
- 步骤1:创建
store/index.js
export const state = () => ({
str: 0
})
export const mutations = {
setData (state, value) {
state.str = value
}
}
-
步骤2:测试页面
<template> <div> <!-- 显示数据 --> {{$store.state.str}} </div> </template> <script> export default { async fetch( {store, $axios} ) { // 发送ajax let { data } = await $axios.get('/service-consumer/feign/echo/abc') // 设置数据 store.commit('setData' , data ) } } </script> <style> </style>
6.5 插件:自定义axios
6.5.1 客户端
- 步骤一:在
nuxt.conf.js
中配置客户端插件,设置 mode 为 client
plugins: [
{ src: '~plugins/api.js', mode: 'client' }
],
- 步骤二:编写
plugins/api.js
对 内置的 $axios进行增强
//自定义函数
const request = {
test : (params) => {
return axios.get('/service-consumer/feign/echo/abc',{
params
})
},
}
var axios = null
export default ({ $axios }, inject) => {
//3) 保存内置的axios
axios = $axios
//4) 将自定义函数交于nuxt
// 使用方式1:在vue中,this.$request.xxx()
// 使用方式2:在nuxt的asyncData中,content.app.$request.xxx()
inject('request', request)
}
6.5.2 服务端
- 步骤一:配置服务端插件,设置 mode 为 server
plugins: [
{ src: '~plugins/api.js', mode: 'client' },
{ src: '~plugins/api.server.js', mode: 'server' },
],
-
步骤二:编写
plugins/api.server.js
对 内置的 $axios进行增强const request = { test : (params) => { return axios.get('/service-consumer/feign/echo/abc',{ params }) }, } var axios = null export default ({ $axios, redirect, process }, inject) => { //赋值 axios = $axios //4) 将自定义函数交于nuxt // 使用方式1:在vue中,this.$request.xxx() // 使用方式2:在nuxt的asyncData中,content.app.$request.xxx() inject('request', request) }
6.5.3 插件配置总结
//方式1:通过src设置文件,通过mode设置模式
plugins: [
{ src: '~/plugins/apiclient.js', mode: 'client' }, //前端客户端
{ src: '~/plugins/apiserver.js', mode: 'server' }, //前端服务端
{ src: '~/plugins/api.js' } //前端客户端 + 前端服务端
]
//方式2:通过命名来确定模式
plugins: [
'~/plugins/api.client.js', //前端客户端
'~/plugins/api.server.js', //前端服务端
'~/plugins/api.js', //前端客户端 + 前端服务端
]
7. Vuex 状态树
7.1 根模块数据操作
- 步骤一:创建
store/index.js
添加一个 counter变量,并可以继续累加操作
export const state = () => ({
counter: 0
})
export const mutations = {
increment (state) {
state.counter++
}
}
-
步骤二:在页面中,使用
<template> <div> 首页 {{counter}} <input type="button" value="+" @click="increment"/> </div> </template> <script> import { mapState,mapMutations } from 'vuex' export default { computed: { ...mapState(['counter']) }, methods: { ...mapMutations(['increment']) }, } </script> <style> </style>
7.2 其他模块数据操作
- 步骤一:创建其他模块
store/book.js
export const state = () => ({
money: 0
})
export const mutations = {
addmoney (state) {
state.money += 5
}
}
-
步骤二:使用指定模块中的数据
<template> <div> 首页 {{money}} <input type="button" value="+" @click="addmoney" /> </div> </template> <script> import { mapState,mapMutations } from 'vuex' export default { computed: { money () { return this.$store.state.book.money } }, methods: { ...mapMutations({ addmoney: 'book/addmoney' }) }, } </script> <style> </style>
7.3 完整vuex模板
// state为一个函数, 注意箭头函数写法
const state = () => ({
user: 'jack'
})
// mutations为一个对象
const mutations = {
setUser(state, value) {
state.counter = value
}
}
// action执行mutation
const actions = {
userAction (context,value){
// 可以发送ajax
context.commit('setUser',value)
}
}
// 获取数据
const getters = {
getUser (state) {
return state.user
}
}
export default {
namespace: true, // 命名空间
state,
mutations,
actions,
getters
}
8. nuxt流程总结
9. 综合练习
-
需求:查询学生列表信息
- 要求1:可以进行“班级”条件查询
- 要求2:对“班级”数据进行SEO
- 要求3:学生数据不进行SEO
-
表结构
#班级表
create table tab_class(
cid int primary key auto_increment,
cname varchar(50)
);
insert into tab_class(cid, cname) values(1,'Java56');
insert into tab_class(cid, cname) values(2,'Java78');
#学生表
create table tab_student(
sid int primary key auto_increment,
sname varchar(50),
cid int
);
insert into tab_student(sname,cid) values('张三',1);
insert into tab_student(sname,cid) values('李四',1);
insert into tab_student(sname,cid) values('王五',2);
insert into tab_student(sname,cid) values('赵六',2);
- 后端代码
- 代码结构
- controller/StudentController
- 代码结构
package com.czxy.student.controller;
import com.czxy.student.service.StudentService;
import com.czxy.student.vo.StudentVo;
import com.czxy.vo.BaseResult;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
private StudentService studentService;
@PostMapping("/condition/{pageSize}/{pageNum}")
public BaseResult condition(@PathVariable("pageSize") Integer pageSize,
@PathVariable("pageNum") Integer pageNum,
@RequestBody StudentVo studentVo){
PageInfo pageInfo = studentService.condition(pageNum,pageSize,studentVo);
return BaseResult.ok("查询成功",pageInfo);
}
}
- mapper/StudentMapper
package com.czxy.student.mapper;
import com.czxy.domain.Student;
import tk.mybatis.mapper.common.Mapper;
@org.apache.ibatis.annotations.Mapper
public interface StudentMapper extends Mapper<Student> {
}
- service/StudentService
package com.czxy.student.service;
import com.czxy.domain.Student;
import com.czxy.student.mapper.StudentMapper;
import com.czxy.student.vo.StudentVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.StringUtil;
import java.util.List;
@Service
@Transactional
public class StudentService {
@Autowired
private StudentMapper studentMapper;
public PageInfo condition(Integer pageNum, Integer pageSize, StudentVo studentVo) {
Example example = new Example(Student.class);
Example.Criteria criteria = example.createCriteria();
if (StringUtil.isNotEmpty(studentVo.getCid())){
criteria.andEqualTo("cid",studentVo.getCid());
}
if (StringUtil.isNotEmpty(studentVo.getSname())){
criteria.andLike("sname","%"+studentVo.getSname()+"%");
}
if (StringUtil.isNotEmpty(studentVo.getStartAge())){
criteria.andGreaterThanOrEqualTo("age",studentVo.getStartAge());
}
if (StringUtil.isNotEmpty(studentVo.getEndAge())){
criteria.andLessThanOrEqualTo("age",studentVo.getEndAge());
}
PageHelper.startPage(pageNum,pageSize);
List<Student> list = studentMapper.selectByExample(example);
return new PageInfo(list);
}
}
- vo/StudentVo
package com.czxy.student.vo;
import lombok.Data;
@Data
public class StudentVo {
private String cid;
private String sname;
private String startAge;
private String endAge;
}
- 启动器 —StudentServiceApplication
package com.czxy.student;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@SpringBootApplication
@EnableDiscoveryClient
public class StudentServiceApplication {
public static void main(String[] args) {
SpringApplication.run(StudentServiceApplication.class, args );
}
}
- 后端代码框架
- nuxt.config.js
plugins: [
{src: '@/plugins/api-client.js',mode:'client'},
{src: '@/plugins/api-server.js'}
],
axios: {
baseURL: 'http://localhost:10010/',
},
- plugins/api-client.js
//自定义函数
const request = {
//分页查询
condition(pageInfo,studentVo) {
var url = `/student-service/student/condition/${pageInfo.pageSize}/${pageInfo.pageNum}`
return axios.post(url, studentVo)
},
//模糊查询
query(pageInfo,studentVo){
var url = `/student-service/student/condition/${pageInfo.pageSize}/${pageInfo.pageNum}`
return axios.post(url, studentVo)
},
}
var axios = null
export default ({ $axios }, inject) => {
//3) 保存内置的axios
axios = $axios
//4) 将自定义函数交于nuxt
// 使用方式1:在vue中,this.$request.xxx()
// 使用方式2:在nuxt的asyncData中,content.app.$request.xxx()
inject('requestclient', request)
}
- plugins/api-server.js
//自定义函数
const request = {
//班级列表
list() {
var url = '/student-service/classes/list'
return axios.get(url)
},
}
var axios = null
export default ({ $axios }, inject) => {
//3) 保存内置的axios
axios = $axios
//4) 将自定义函数交于nuxt
// 使用方式1:在vue中,this.$request.xxx()
// 使用方式2:在nuxt的asyncData中,content.app.$request.xxx()
inject('requestServer', request)
}
- pages/student.vue
<template>
<div>
<hr />
请选择班级:
<select v-model="studentVo.cid" @click="query()">
<option value="" >--请选择班级--</option>
<option v-for="c in classesList" :key="c.index" :value="c.cid">
{{ c.cname }}
</option>
</select>
<br />
学生列表
<table border="1">
<tbody>
<tr>
<td>序号</td>
<td>姓名</td>
<td>班级</td>
<td>操作</td>
</tr>
<tr v-for="s in pageInfo.list" :key="s.index">
<td>{{ s.sid }}</td>
<td>{{ s.sname }}</td>
<td>{{ s.classes_test !=null ? s.classes_test.cname : s.cid }}</td>
<td>修改 删除</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
studentVo: {
cid: "",
},
pageInfo: {
pageSize:10,
pageNum:1,
},
};
},
methods: {
async conditionFn() {
let { data } = await this.$requestclient.condition(this.pageInfo,this.studentVo);
this.pageInfo = data.data;
},
async query() {
let { data } = await this.$requestclient.query(this.pageInfo,this.studentVo);
this.pageInfo = data.data;
},
},
async asyncData({ $requestServer }) {
let { data } = await $requestServer.list();
return {
classesList: data.data,
};
},
mounted() {
this.conditionFn();
},
};
</script>
<style>
</style>
- pages/index.vue
<template>
<div>
<a href="/student">学生列表</a>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
- layouts/default.vue
<template>
<div>
<!-- 导航条 -->
<nuxt-link to="/">首页</nuxt-link>
<!-- 视图 -->
<nuxt/>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>