VUE SSR服务器端渲染NUXT采坑总结
web-慰尘 人气:0初始化创建项目
yarn create nuxt-app <项目名>
css预编译
安装 yarn add node-sass scss-loader sass-loader --save-dev
路由管理
在nuxt中路由已经被集成到框架中,所以不需要再单独引入配置,而且当页面文件创建后, router会生成响应的路由,路由文件在.nuxt/router.js文件,用法上基本不变, 与vue-router用法不同部分记录如下
跳转与传参
- nuxt路由跳转同样是分为两种方式(声明式和编程式),不同的是在nuxt中用跳转标签nuxt-link而不是router-link
- 传参demo如下
1 <nuxt-link :to="{name:'home',params:{newsId:3306}}">home1</nuxt-link> 2 接收参数 3 asyncData({ params }) { 4 console.log('home1', params); 5 }, 6 <nuxt-link :to="{path:'home',query:{newsId:3306}}">home2</nuxt-link> 7 接收参数 8 asyncData({ query }) { 9 console.log('home2', query); 10 },
页面切换动效
路由动效分为全局动效和单独页面动效
- 创建动效文件,在asset文件下创建动效样式文件(这里定义文件名changePage.css)
- 定义动画效果,这里定义简单的淡入淡出效果
// 页面默认的页面切换类名为page-enter、page-enter-active、page-leave-active .page-enter-active, .page-leave-active { transition: opacity 1s; } .page-enter, .page-leave-active { opacity: 0; }
引入定义的动效文件,在nuxt.config.js文件中配置中引入该css文件
定义单独页面动效
- 在页面文件中定义样式类名
1 export default { 2 transition: 'home' 3 }
在css文件中定义动画效果
.home-enter-active, .home-leave-active { transition: all 2s; font-size: 12px; } .home-enter, .home-leave-active { opacity: 0; font-size: 40px; }
嵌套路由
开发业务中,有时难免会遇到需要二级甚至多层路由嵌套,官方文档中的二级路由介绍也是过于简单,为此又多掉了几根头发 这里就拿官网文档的例子作为讲解
1 第一:假设要创建一个user的二级路由,文件结构如: 2 3 pages/ 4 --| users/ //2、最容易创建与user.vue文件同名的文件夹,这样nuxt就会识别出我们的意图,原来是要创建嵌套路由 5 //假如文件夹与user.vue不同名,那么该文件夹下的文件同样被生成一级路由 6 -----| _id.vue 7 -----| index.vue 8 --| users.vue // 1、首先要有user.vue文件 9 10 第二:Nuxt.js 自动生成的路由配置如下: 11 router: { 12 routes: [ 13 { 14 path: '/users', 15 component: 'pages/users.vue', 16 children: [ 17 { 18 path: '', 19 component: 'pages/users/index.vue', 20 name: 'users' 21 }, 22 { 23 path: ':id', 24 component: 'pages/users/_id.vue', 25 name: 'users-id' 26 } 27 ] 28 } 29 ] 30 } 31 第三:在一级页面中显示二级页面 32 <template> 33 <div class="page-me"> 34 <div>一级页面的相关内容、、、</div> 35 <nuxt-child /> //二级页面的视图窗口,相当于Vue Router的<router-view></router-view> 36 </div> 37 </template>
路由拦截/鉴权
nuxt的路由拦截与Vue Router不同,需要引入中间件 的概念,好在文档介绍比较容易理解,现梳理如下
- 需要在指定的文件夹middleware/ 下创建路由拦截文件(文件不限数量)
- 一个中间件接收 context 作为第一个参数,context包含了包括vuex等在内相关数据信息,以此通过数据执行相关逻辑
export default function (context) { context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent }
在nuxt.config.js为全局页面定义路由拦截
module.exports = { router: { middleware: 'stats'//中间件文件名 } }
当然不想全局定义路由拦截也可以为单独的页面定义路由拦截
//具体的页面 export default { middleware: 'stats' }
错误页设置
一个完成项目,404或其他错误页面总是要有的,对此nuxt已经封装了404页面跳转,在layouts文件夹下创建error.vue文件(文件名必须是error.vue),组件接收error对象参数,通过参数的状态码判断页面错误原因
<template> <div class="container"> <h2 v-if="error.statusCode == 404">这是404页面</h2> <h2 v-else>这是500页面</h2> </div> </template> <script> export default { props: ['error'], //nuxt已经封装好返回的 mounted() { console.log('error', this.error); } }; </script>
接口请求
安装
- 安装:yarn add @nuxtjs/axios
- 同正常的axios用法相同,不做详细解释
本地代理
- npm i @nuxtjs/proxy -D
- 在 nuxt.config.js 配置文件中添加对应的模块,并设置代理
- 配置了代理,本地开发时axios就不能使用baseURL(打包时,baseURL还是需要放开)
1 modules: ['@nuxtjs/axios','@nuxtjs/proxy'], 2 axios: { 3 proxy: true 4 }, 5 proxy: {//代理可以设置多个 6 '/api': {// /api是指真实接口域名后的一个层级 7 target: 'http://example.com',//真实接口域名 8 pathRewrite: { 9 '^/api' : '/'// "/api"与上面的api相同 10 } 11 } 12 }
axios API封装
- axios的封装与常规vue项目相同,不同的区别是需要在配置文件中将封装文件引入
plugins: ["@/plugins/element-ui", "~/plugins/api.js"]
api访问本地开发
通过设置IP地址,这样就可以通过IP访问本地项目环境
//package.json中配置 "devDependencies": {}, "config": { "nuxt": { "host": "0.0.0.0", "port": "5000" } }
asyncData
用于服务端或路由更新之前被调用(如果这里进行接口请求,页面会等接口返回结果后才发生跳转),方法的第一个参数被设定为当前页面的上下文对象(即包含路由、参数等等的一些列信息),可用于请求一个或多个接口,并将返回的数据融合到组件的data中,改方法与mounted函数同级,只在页面模块的文件内生效,在组件模块文件内不生效,由于asyncData方法是在组件 初始化 前被调用的,所以在方法内是没有办法通过 this 来引用组件的实例对象。
写法一 asyncData(context) { return ( axios.get('https://api.myjson.com/bins/8gdmr1').then(res => { return { info: res.data }; //注意,return返回的最好是key:value对象,直接return导致不利于从实例data中查找使用,如: //return (res.data),因为没有设定key,返回的数据虽然融合到实例的data上,但没有key则没法通过key值查找使用 }), axios.get('https://api.myjson.com/bins/8gdmr').then(res => { return { info: res.data }; }) ); }, 写法二 async asyncData({ params }) { const { data } = await axios.get('https://api.myjson.com/bins/8gdmr'); return { info: data }; },
Vuex
nuxt中集成了vuex,不需要新安装插件,Nuxt.js 会尝试找到应用根目录下的 store 目录,并引用 vuex 模块,将 vuex 模块 加到 vendors 构建配置中去,设置 Vue 根实例的 store 配置项。
以上是官方文档原话,大白话翻译就是:nuxt已经集成了vuex不需要手动安装,nuxt会直接找到vuex文件,并把vuex配置到项目中,然后就想正常vue一样使用即可
创建与使用
- 1、vuex不需要新创建实例,即不需要new Vuex.Store({})
- 2、state的值应该始终是function,为了避免返回引用类型,会导致多个实例相互影响,即
//正确写法 export const state = () => ({ counter: 0 }) //错误写法 export const state = { counter: 0 }
数据持久化
为避免页面刷新数据状态丢失,需要对vuex数据持久化,nuxt的vuex数据持久化与vue项目稍有不同,这里推荐的是nuxt-vuex-localstorage
- 安装
- 配置文件引入
//nuxt.config文件中引入 modules: ["nuxt-vuex-localstorage"]
欢迎大佬指教
项目中虽然在使用vuex,但遇到的问题依然很多,使用起来总是磕磕绊绊,欢迎留言指教
部分配置介绍
meta标签设置
既然是为了SEO优化,那么总是少不了mate标签关键字设定,mate标签分为定义全局和单个页面配置
- 配置文件定义全局
head: { title: process.env.npm_package_name || "", meta: [ { charset: "utf-8" }, { name: "viewport", content: "width=device-width, initial-scale=1" }, { hid: "description", name: "description", content: process.env.npm_package_description || "" } ], link: [{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" }] },
设置页面独有关键字
export default { data () { return { title: 'Hello World!' } }, head () { return { title: this.title, meta: [ { hid: 'description', name: 'description', content: 'My custom description' } ] } } }
加载全部内容