SPA(single page web application)单页 Web 应用,Web 不再是一张张页面,而是一个整体的应用,一个由路由系统、数据系统、页面(组件)系统等等,组成的应用程序。
我们之前学习的Vue就是SPA中的佼佼者。
SEO:搜索引擎优化(Search Engine Optimization), 通过各种技术(手段)来确保,我们的Web内容被搜索引擎最大化收录,最大化提高权重,最终带来更多流量。
非常明显,SPA程序不利于SEO
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WuScEyK4-1639401759526)(assets/image-20210428084608523.png)]
SEO解决方案:提前将页面和数据
进行整合
服务端渲染(Server Side Render),即:网页是通过服务端渲染生成后输出给客户端。
如果爬虫获得html页面,就可以启动处理程序,处理页面内容,最终完成SEO操作。
SPA单页应用程序 | SSR服务器端渲染 | |
---|---|---|
优势 | 1.页面内容在客户端渲染 2. 只关注View层,与后台耦合度低,前后端分离 3.减轻后台渲染画面的压力 |
1.更好的SEO,搜索引擎工具可以直接查看完全渲染的画面 2.更快的内容到达时间 (time-to-content),用户能更快的看到完整渲染的画面 |
劣势 | 1.首屏加载缓慢 2.SEO(搜索引擎优化)不友好 |
1.更多的服务器端负载 2.涉及构建设置和部署的更多要求,需要用Node.js渲染 3.开发条件有限制,一些生命周期将失效 4.一些常用的浏览器API无法使用 |
Nuxt.js 提供了脚手架工具 create-nuxt-app
create-nuxt-app
需要使用 npx
npx 命令为 NPM版本5.2.0默认安装组件
npx create-nuxt-app
npx create-nuxt-app demo_nuxt02
npm run dev
~~~ ![在这里插入图片描述](https://img-blog.csdnimg.cn/665f892dcecc43be842e5901841215b5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAenpsbF9mb3JldmVy,size_14,color_FFFFFF,t_70,g_se,x_16)
## 2.4 访问
http://localhost:3000
![在这里插入图片描述](https://img-blog.csdnimg.cn/4799e1797bed4c60aa052222b14ed110.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAenpsbF9mb3JldmVy,size_20,color_FFFFFF,t_70,g_se,x_16)
# 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 | 项目配置文件 |
![在这里插入图片描述](https://img-blog.csdnimg.cn/8b432d2de4324d26a9f5b101649e85ec.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAenpsbF9mb3JldmVy,size_20,color_FFFFFF,t_70,g_se,x_16)
## 3.2 别名
* assets 资源的引用:~ 或 @
// HTML 标签
// CSS
background-image: url(~assets/13.jpg);
background-image: url(~/assets/13.jpg);
background-image: url(@/assets/13.jpg);
* static 目录资源的引用:/ 直接引用
//html标签
//css
background-image: url(/12.jpg);
* 实例
~~~vue
标签。标签名 | 描述 |
---|---|
|
nuxt.js中切换路由 |
|
nuxt.js的路由视图 |
|
vue默认切换路由 |
|
vue默认路由视图 |
路径 | 组件位置及其名称 | 规则 |
---|---|---|
/ | 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
文件路由中路径匹配 | 组件位置及其名称 |
---|---|
/ | pages/index.vue |
/user/:id | pages/user/_id.vue |
/:slug | pages/_slug/index.vue |
/:slug/comments | pages/_slug/comments.vue |
user/_id.vue
查询详情 {{this.$route.params.id}}
第2新闻
第3新闻
路径 | 组件位置及其名称 |
---|---|
不匹配的路径 | pages/_.vue |
创建嵌套子路由,你需要添加一个 父组件Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。
显示子视图内容pages/
--| book/ //同名文件夹
-----| _id.vue
-----| index.vue
--| book.vue //父组件
步骤1:编写父组件 pages/child/book.vue
书籍列表 |
书籍详情 |
步骤2:编写子组件 pages/child/book/list.vue
书籍列表
步骤3:编写子组件 pages/child/book/_id.vue
书籍详情{{$route.params.id}}
创建嵌套子路由,你需要添加一个 父组件Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。
显示子视图内容pages/
--| book/ //同名文件夹
-----| _id.vue
-----| index.vue
--| book.vue //父组件
步骤1:编写父组件 pages/child/book.vue
书籍列表 |
书籍详情 |
步骤2:编写子组件 pages/child/book/list.vue
书籍列表
步骤3:编写子组件 pages/child/book/_id.vue
书籍详情{{$route.params.id}}
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'
]
}
如果想给某个页面自定义过渡特效的话,只要在该页面组件中配置 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'
}
定制化默认的 html 模板,只需要在应用根目录下创建一个 app.html 的文件。
默认模板:
DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
head>
<body {{ BODY_ATTRS }}>
{{ APP }}
body>
html>
修改模板,对低版本IE浏览器进行支持(兼容IE浏览器)
DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
head>
<body {{ BODY_ATTRS }}>
{{ APP }}
body>
html>
布局:Nuxt.js根据布局,将不同的组件进行组合。
模板:html页面,是布局后所有组件挂载的基础。
layouts/default.vue
首页 |
登录 |
详情 |
默认页 |
async |
在layouts目录下创建组件:layouts/blog.vue
开头
结束
在需要的视图中使用 blog布局
layouts/error.vue
页面,实现个性化错误页面
404 页面不存在 {{error.message}}
应用程序错误
首 页
_.vue
(先执行)~/layouts/error.vue
特殊配置项 | 描述 |
---|---|
asyncData | SSR进行异步数据处理,也就是服务器端ajax操作区域。 |
fetch | 在渲染页面之前获取数据填充应用的状态树(store) |
head | 配置当前页面的 Meta 标签 |
layout | 指定当前页面使用的布局 |
transition | 指定页面切换的过渡动效 |
scrollToTop | 布尔值,默认: false。 用于判定渲染页面前是否需要将当前页面滚动至顶部。 |
Hello {{ name }}!
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 等内容。
详情页 {{$route.params.id}}
"dependencies": {
"@nuxtjs/axios": "^5.13.1",
},
步骤2:安装
npm install
步骤3:nuxt.config.js 以模块的方式添加axios
modules: [ // https://go.nuxtjs.dev/axios ‘@nuxtjs/axios’, ],
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
baseURL:'http://localhost:10010/'
},
在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;
});
export default {
async asyncData( context ) { //context就相当于其他地方的this
//发送ajax
let { data } = await context.$axios.get('路径','参数')
// 返回结果
return {变量: 查询结果从data获取 }
},
}
实例
{{echo}}
语法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
}
},
}
实例
{{echo}} {{echo2}}
fetch 方法用于在渲染页面前填充应用的状态树(store)数据, 与 asyncData 方法类似,不同的是它不会设置组件的数据。
步骤1:创建store/index.js
export const state = () => ({
str: 0
})
export const mutations = {
setData (state, value) {
state.str = value
}
}
步骤2:测试页面
{{$store.state.str}}
步骤一:在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)
}
步骤一:配置服务端插件,设置 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)
}
//方式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', //前端客户端 + 前端服务端
]
步骤一:创建 store/index.js
添加一个 counter变量,并可以继续累加操作
export const state = () => ({
counter: 0
})
export const mutations = {
increment (state) {
state.counter++
}
}
步骤二:在页面中,使用
首页 {{counter}}
步骤一:创建其他模块 store/book.js
export const state = () => ({
money: 0
})
export const mutations = {
addmoney (state) {
state.money += 5
}
}
步骤二:使用指定模块中的数据
首页 {{money}}
// 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
}