nuxt
是基于 VUE 的 ssr 服务端渲染的框架
CSR(客服端选取)
当用户发送请求返回页面时,此时只是一个模板页面,浏览器解析代码通过 JS 根据接口去请求数据,得到数据后根据模板来进行渲染。
优点
减轻服务器端压力达到前后端分离开发
SSR(服务器端渲染)
SPA(单页应用)不利于搜索引擎的 SEO 操作,特别是百度根本没法抓取到 SPA 的内容页面
服务器端渲染有哪些好处:
- 更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面
- 对于缓慢的网络或运行缓慢的设备,可以提供网页速度,有良好的用户体验。
- ssr 会减少对服务器的请求,普通的页面先获取文件,再读取内容。读取到 ajax 的 js 的时候,再向服务器发送请求,获取内容。这就是至少两次对服务器的请求了。 如果是 ssr,直接就是再服务器端渲染为完整的页面,发送到浏览器
优点:
- 基于 Vue.js
- 自动代码分成
- 服务端渲染
- 强大的路由功能,支持异步数据
- 静态文件服务
- 打包和压缩 JS 和 CSS
- HTML 头部标签管理
- 本地支持热加载
- 集成 ESLint
- 支持各种样式预处理器:SASS、LESS、Stylus 等等
基础
目录结构
名称 | 解释 |
assets | 未编译的静态资源(LESS、SASS、JavaScript) |
static | 存放应用的静态文件,不会被webpack构建编译,服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下 |
components | 组织应用的 Vue.js 组件,但Nuxt不会拓展该目录下的组件 |
layouts | 组织应用的布局组件 |
middleware | 应用的中间件 |
pages | 组织应用的路由及视图,根据该目录下的.vue文件自动生成对于的路由配置 |
plugins | 组织需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。 |
store | 组织应用的 Vuex 状态树 文件 |
nuxt.config.js | Nuxt.js 应用的个性化配置,以便覆盖默认配置。 |
配置
- 设置端口号和 ip
在 package.json 中添加:
"config":{
"nuxt":{
"host":"xxx",
"port":"xxx"
}
}
在 nuxt.config.js 中修改:
- 全局引入css
其中~
匹配根目录
css:['~assets/css/normailze.css']
- 打包
在 build 中:
build:{
loaders:[{
test:/\.(png|jpe?g|gif|svg)$/,
loader:"url-loader",
query:{
limit:10000,
name:'img/[name].[hash].[ext]'
}
}]
}
流程图
服务器请求到渲染的过程:
- nuxtServerInit:在这里可以做一些,如果后续还要请求会从中间件中继续开始
- middleware:运行自定义的函数,可以运行在全局、某个布局或组件应用之前,可以在如图上的三种文件中配置,文件名的名称将成为中间件名称 (middleware/auth.js将成为 auth 中间件)
- 中间件执行流程顺序:
- uxt.config.js
- 配布局
- 配页面
- BOM对象和this 不能在服务器端的钩子函数中调用
- 服务端通过 context 上下文信息去抓取内容,而不使用this,因为 this 指向的是 undefined
- beforecreate 和 created 是运行在客户端和服务端的
路由
- Nuxt.js 依据 pages 目录结构自动生成 vue-router 模块的路由配置。
- 建议使用
<nuxt-link>
标签。 - 定义带参数的
动态
路由,需要创建对应的以下划线
作为前缀的 Vue 文件 或 目录。 - 设置为
必选
的路由,需要在 下划线
作为前缀的目录内创建一个 index.vue 文件。 - 可以在动态路由组件中定义
参数校验
方法。 -
嵌套
路由(父组件[.vue]文件,子组件同名目录)在父组件内增加 <nuxt-child/>
用于显示子视图内容。 - 展示区层级,当定义在pages下的路由都为一级路由,二级路由如果想要在一级显示,就将 pages 下的删掉,写入同名文件夹的 index 中
路由守卫
- 前置
- 依赖中间件 middleware,插件
- 全局守卫:nuxt.config 指向 middleware
layouts 定义中间件
- 组件独享守卫:middleware
- 插件全局前置守卫(router.beforeEach)
- 后置
- 使用 vue 的 beforeRouteLeave 钩子
- 插件全局后置守卫(router.afterEach)
过渡和动画
- 使用
<transition>
组件来实现路由切换时的过渡动效 - 默认使用的过渡效果名称为 page
/* 全局 */
.page-enter-active,
.page-leave-active {
transition: opacity 0.5s;
}
.page-enter,
.page-leave-active {
opacity: 0;
}
/* 页面 */
/* 将页面组件中的 transition 属性的值设置为 test
export default {
transition: 'test'
}
*/
.test-enter-active,
.test-leave-active {
transition: opacity 0.5s;
}
.test-enter,
.test-leave-active {
opacity: 0;
}
视图
默认模板和默认布局
- 在根目录中创建的html页面默认会被认为是默认模板或者是在 src 文件夹下创建 app.html,在默认模板中可以使用
{{大写}}
来引入,需要重新启动服务器 - 在 layouts/default 中 ,不需要重启服务器,记得在布局文件中添加 <nuxt/> 组件用于显示页面的主体内容。
- 也可以在页面中使用
layout
属性来使用自定义布局
页面
页面组件实际上是 Vue 组件,只不过 Nuxt.js 为这些组件添加了一些特殊的配置项(对应 Nuxt.js 提供的功能特性)以便你能快速开发通用应用。
- 自定义错误页面:layouts/error.vue 文件来定制化错误页面,不需要包含 <nuxt/> 标签
export default {
// 运行在页面层级 可以指向外部auth 也可以自己定义
// middleware:'auth',
middleware(){
console.log('页面层级middleware');
},
// 参数的有效性
validate({req,res}){
// 检验业务
console.log('校验参数');
return true;
// 返回失败会去error页面
},
// 读取数据返回给组件
asyncData() {
console.log('asyncData执行啦');
// 异步业务逻辑,读取服务器端的数据
return {
msg:'word'
}
},
// 读取数据返回给 vuex
fetch({store}) {
console.log('fetch执行啦');
// 异步业务逻辑,读取服务器端的数据提交给vuex
store.commit('setMsg', 'word');
}
// 设置头部信息
head () {},
}
属性名 | 描述 |
asyncData | 最重要的一个键, 支持 异步数据处理,另外该方法的第一个参数为当前页面组件的 上下文对象。 |
fetch | 与 asyncData 方法类似,用于在渲染页面之前获取数据填充应用的状态树(store)。不同的是 fetch 方法不会设置组件的数据。详情请参考 关于 fetch 方法的文档。 |
head | 配置当前页面的 Meta 标签, 详情参考 页面头部配置 API。 |
layout | 指定当前页面使用的布局(layouts 根目录下的布局文件)。详情请参考 关于 布局 的文档。 |
loading | 如果设置为false,则阻止页面自动调用this.$nuxt.$loading.finish()和this.$nuxt.$loading.start(),您可以手动控制它,请看例子,仅适用于在 nuxt.config.js 中设置loading的情况下。请参考API 配置 loading 文档。 |
transition | 指定页面切换的过渡动效, 详情请参考 页面过渡动效。 |
scrollToTop | 布尔值,默认: false。 用于判定渲染页面前是否需要将当前页面滚动至顶部。这个配置用于 嵌套路由的应用场景。 |
validate | 校验方法用于校验 动态路由的参数。 |
middleware | 指定页面的中间件,中间件会在页面渲染之前被调用, 请参考 路由中间件。 |
数据交互与跨域
数据交互
- npm 安装这两个依赖:@nuxtjs/axios、@nuxtjs/proxy
- 添加到项目的 nuxt.config 的 modules 中
- 添加完成后服务的获取的上下文中就会多出一个
$axios
,通过 $axios 就可以进行数据的交互
跨域
- 在 nuxt.config 中配置 axios 和 proxy
axios: {
// 开启跨域
proxy: true,
// 添加需要跨域的 baseUrl
prefix: '/api'
},
proxy: {
'/api':{
// 代理转发的地址
target:'http://10.10.35.19:3000',
changeOrigin:true,
pathRewirte:{
// '^api':''
}
}
},
使用vuex
- 模块方式
store
目录下的每个 .js
文件会被转换成状态树,index 是根模块
- classic 方式 (不推荐)
store/index.js
返回创建 Vuex.Store 实例的方法
- state 必须是函数,mutation、 actions 可以是对象
装饰器
- 安装依赖:vuex-class
- 可以从其中拿到 state、getter、action、mutation等
// 装饰一个实例属性 msg 引用到 state.msg
// 类似于 在计算属性中:...mapState(['msg'])
@State msg:boolean | undefined;
// 抓取 state 里面的数据
// ...mapState({home:state=>state.home.data})
@State(state=>state.home.data) home?:object[];
// 外部 state.user 做组件内部的 data 使用
// ...mapState('user',['data'])
@State('user') data!:object;
// 抓取 getters 的 key,作为组件实例属性使用
// ...mapGetter(['getNav'])
// 属性一致可以省略 没有参数可以省略括号
@Getter getNav!:string
// ...mapActions('user',['A_UPDATE_USER'])
@Action('user/A_UPDATE_USER') A_UPDATE_USER!:(payload:object)=>void
// ...mapMutations('user',['M_UPDATE_USER'])
@Mutation('user/A_UPDATE_USER') M_UPDATE_USER!:(payload:object)=>void
全局拦截器、token 携带
- 可以通过编写插件的形式进行全局拦截器的编写
- 可以进行请求拦截、响应拦截、错误拦截、对axios进行基本配置等
- token携带:在拦截的时候对请求进行拦截并在头部添加
export default ({ $axios, store, redirect, route }) => {
// 基本配置
$axios.defaults.timeout = 10000;
// 请求拦截
$axios.onRequest(config=>{
console.log('请求拦截处理');
config.headers.token = '添加token'
return config
})
// 响应拦截
$axios.onResponse(res=>{
// 像 token 过期等 根据服务器端返回的错误码进行处理
if(res.data.error === 2 && route.pullPath !== '/') {
redirect('/?path =' + route.fullPath)
}
return res
})
// 错误处理
$axios.onError(error=>{
// 处理
// ...
// 返回
return error
})
};
状态持久化和 token 校验
- 安装模块: cookie-universal-nuxt --save
- 持久化:在登陆时,同步 vuex 和 cookie,用户在强制刷新后,请求发送到服务端 触发 nuxtServerInit 钩子,在里面取出 cookies,然后去同步 vuex,在 axios 拦截器中读取 vuex
// 登陆后 服务端返回
this.$axios({}).then(res=>{
// 同步 vuex 和 cookie
this.$cookies.set(‘user’,res.data)
this.$store.commit('user/M_UPDATE_USER',res.data)
})