Nuxt开发经验分享

本文章基于starter-template模板进行讲解,面向有vue-cli开发经验的宝宝

vue init nuxt-community/starter-template
 
 

Nuxt

官方文档

简单来说,Nuxt就是基于Vue的一个应用框架,采用服务端渲染,让你的SPA应用(Vue)也可以拥有SEO

生命周期

众所周知,Vue的生命周期全都跑在客户端(浏览器),而Nuxt的生命周期有些在服务端(Node),客户端,甚至两边都在:

 
 

生命周期流程图,红框内的是Nuxt的生命周期(运行在服务端),黄框内同时运行在服务端&&客户端上,绿框内则运行在客户端


实战经验

1. 红框、黄框内的周期都不存在Window对象

<script>
export default {
asyncData() {
console.log(window) // 服务端报错
},
fetch() {
console.log(window) // 服务端报错
},
created () {
console.log(window) // undefined
},
mounted () {
console.log(window) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
}
}
</script>

2. 配置错误页面

你可以通过编辑 layouts/error.vue 文件来定制化错误页面.

<template>
<div class="container">
<h1 v-if="error.statusCode === 404">页面不存在</h1>
<h1 v-else>应用发生错误异常</h1>
<nuxt-link to="/">首 页</nuxt-link>
</div>
</template> <script>
export default {
props: ['error'],
layout: 'blog' // 你可以为错误页面指定自定义的布局
}
</script>

3. 自定义Loading页面

nuxt.config.js

module.exports = {
loading: '~components/loading.vue'
}

loading.vue

<template lang="html">
<div class="loading-page" v-if="loading">
<p>Loading...</p>
</div>
</template> <script>
export default {
data: () => ({
loading: false
}),
methods: {
start () {
this.loading = true
},
finish () {
this.loading = false
}
}
}
</script>

4. 校验参数

如果校验失败,则自动跳转到错误页面

<script>
export default {
validate({ params, query }) {
return /^d+$/.test(params.id) // must be number
}
}
</script>

5. Header、Footer等公共组件放哪?

大家都知道,vue-cli入口文件是app.vue,在nuxt开发当中则是./layout/default.vue

<template>
<div id="app">
<!-- 公共头部组件 -->
<xxx-header></xxx-header>
<!-- 路由视图,相当于router-view -->
<nuxt/>
<!-- 公共底部组件 -->
<xxx-footer></xxx-footer>
</div>
</template>

6. 没有keep-alive

由于是服务端渲染,所以不支持组件的keep-alive,那自然activated、deactivated这两个生命周期也没了

7. 配置插件

所有插件都写在/plugins目录下,这里以vue-lazyload为例

plugins/lazy-load.js

import Vue from 'vue'
import VueLazyLoad from 'vue-lazyload' Vue.use(VueLazyLoad, {
loading: require('~/assets/images/loading.jpg'),
error: require('~/assets/images/error.jpg')
})

nuxt.config.js

module.expors = {
plugins = [
{
src: "~/plugins/lazy-load",
ssr: false
}
]
}

8. 使用Axios,并配置全局拦截器,处理跨域

starter-template模板,推荐使用@nuxtjs/axios、@nuxtjs/proxy,不需要在plugins配置

安装依赖

npm install @nuxtjs/axios @nuxtjs/proxy --save

使用、处理跨域

// nuxt.config.js
module.exports = {
modules: [ '@nuxtjs/axios' ], // 不需要加入@nuxtjs/proxy
axios: {
proxy: true,
prefix: '/api', // baseURL
credentials: true,
},
proxy: {
'/api/': {
target: 'http://127.0.0.1:2001', // 代理地址
changeOrigin: true,
pathRewrite: {
'^/api': ''
},
},
}
}

组件中使用

<script>
export default {
fetch ({ app }) {
console.log(app.$axios)
},
asyncData ({ app }) {
console.log(app.$axios)
},
created () {
console.log(this.$axios)
}
}
</script>

到此为止,我们并不需要在plugins配置axios,但是如果要设置全局拦截器,那么就要新建一个/plugins/axios.js

export default function (app) {
let axios = app.$axios;
// 基本配置
axios.defaults.timeout = 10000
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded' // 请求回调
axios.onRequest(config => {}) // 返回回调
axios.onResponse(res => {}) // 错误回调
axios.onError(error => {})
}

然后在plugins配置它

module.exports = {
plugins = [
{
src: "~/plugins/axios",
ssr: false
},
]
}

9. 默认Meta标签

nuxt.config.js

module.exports = {
head: {
title: 'your project title',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
],
link: [
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Roboto' }
]
}
}
nuxt.config.js

module.exports = {
head: {
title: 'your project title',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
],
link: [
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Roboto' }
]
}
}

10. 页面组件特有的Meta标签

<script>
export default {
head () {
return {
meta:
[
{
name: 'keywords',
content: '最强王者,今晚吃鸡'
},
]
}
}
}
</script>

11. 动态路由的Meta标签填充

游戏详情页面举例子,由于数据是异步获取的,我们需要把数据获取写在asyncData钩子,待数据获取成功才会渲染该页面组件

<script>
export default {
async asyncData ({ app, params }) {
let data = await app.$axios.get(`/appinfo/${params.id}`);
return {
appname: data.appinfo.appname
}
},
head () {
return {
meta:
[
{
name: 'keywords',
content: `${this.appname},无限宝石,无限元宝`
},
]
}
}
}
</script>

12. 使用Vuex

nuxt自己集成了vuex,所以不需要安装在/store目录下新建index.js即可使用

import Vuex from 'vuex'

let store = () => new Vuex.Store({
state: {
token: ''
},
mutations: {
setToken (state, token) {
state.token = token
}
}
}) export default store

13. 登录状态?

vue-cli项目中,我们可以用vuex-persistedstate,它可以使vuex的状态持久化,页面刷新都不会丢失,原理当然是localStorage啦!当然我更喜欢用vue-cookies进行保存token,问题来了,nuxt项目怎么保存登录状态呢?当然上面这两种方法我们都可以使用,但是有个问题,由于在created钩子中不存在window对象(获取cookie、localStorage都需要window对象),当你需要判断是否存在token的时候,你必须要在mounted进行操作,这说明页面进来的一瞬间你无法得知是否已经登录了,这会导致显示用户名、组件显示于隐藏都慢半拍


nuxt非常友好,它提供了fetch钩子,还有nuxtServerInit,这两个钩子都运行在服务端并且我们能很快速地操作store

14. fetch的使用

如果页面组件设置了fetch方法,它会在组件每次加载前被调用(在服务端或切换至目标路由之前),此方法需要跟服务端的人员配合

<script>
export default {
async fetch ({ app, store, params }) {
let { data } = app.$axios.get('/token');
store.commit('setToken', data.token);
}
}
</script>

15. nuxtServerInit

终极无敌方法

import Vuex from 'vuex'

let store = () => new Vuex.Store({
state: {
token: ''
},
mutations: {
setToken (state, token) {
state.token = token
}
},
actions: {
nuxtServerInit({ commit }, { req }) {
let cookie = req.headers.cookie; // 将cookie转成json对象(自己实现该方法)
let token = cookieparse(cookie).token;
commit('setToken', token);
},
}
}) export default store

16. 封装属于自己的全局方法

 let xielikang = function () {

  /**
* @method 打印信息方法
* @param {String} msg 信息
*/
let message = function (msg) {
msg && console.log(msg)
} let otherfn = function (msg) {} return {
message,
otherfn
} } Vue.prototype.$kang= xielikang

组件调用

<script>
export default {
created() {
this.$kang.message('小老弟,你怎么回事')
}
}
</script>

对了,别忘了在plugins中配置,可以回到第7小节查看配置

17. 全局样式

nuxt.config.js

module.exports = {
css: ['~/assets/stylesheets/main.min.css']
}

18. 使用Element-UI

还是plugins文件夹新建element-ui.js

// 全局引入
import Vue from 'vue'
import ElementUI from 'element-ui' Vue.use(ElementUI) // 按需引入
import { Button, Loading, MessageBox } from 'element-ui' Vue.use(Button)
Vue.prototype.$loading = Loading.service
Vue.prototype.$msgbox = MessageBox

nuxt.config.js

module.exports = {
css: ['element-ui/lib/theme-chalk/index.css'],
plugins: [
{
src: "~/plugins/element",
ssr: true
}
]
}

18. 如何使用sass预处理器

安装依赖

npm install node-sass sass-loader --save

组件中使用(不需要其他的配置了)

<style lang="scss" scoped>

</style>

19. fetch、asyncData、validate使用范围

只能在页面组件使用,也就是pages目录下的组件,而不是components目录下的组件,要有所区分

20. 传统部署

npm run build && npm run start

21. pm2部署

它允许您永久保持应用程序活跃,无需停机即可重新加载它们,并不需要传统部署的.nuxt文件夹,该部署方法也跟生产环境一样含热更新

npm install pm2 -g
npm run build
pm2 start ./node_modules/nuxt/bin/nuxt-start
 
 
 
 
 
参考:
作者:daydreammoon
链接:https://www.jianshu.com/p/840169ba92e6

Nuxt开发经验分享的更多相关文章

  1. 钱包开发经验分享:ETH篇

    # 钱包开发经验分享:ETH篇 [TOC] ## 开发前的准备 > 工欲善其事,必先利其器 一路开发过来,积累了一些钱包的开发利器和网站,与大家分享一下.这些东西在这行开发过的人都知道,只是给行 ...

  2. 【Meetup回顾】Apache DolphinScheduler在联通的实践和二次开发经验分享

    在由 openLooKeng 社区主办,Apahce DolphinScheduler社区.Apache Pulsar 社区.示说网协办的联合 Meetup 上,来自联通数字科技的王兴杰老师分享了Do ...

  3. 安卓开发经验分享:资源、UI、函数库、测试、构建一个都不能少(转)

    除了高超的武艺,每位黑忍者还需要装备最好的武器.在软件开发的世界里,好的工具能让我们的生活变得更轻松,在更短的时间里写出更棒的代码. 时光回到2008年,那时安卓还很年轻.只有几个相关的博客和谷歌官方 ...

  4. java开发经验分享(三)

    三. 项目开发 1. 需求: 1) 需求最终需要开发人员在产品中实现,开发不合理的设计会浪费时间,开发技术无法实现的设计带来最大的痛苦:失败.所以,开发人员要重视需求以及需求评审,提出自己能够想到的所 ...

  5. TCP/IP和Socket开发经验分享

    当前与网络相关的业务主要是基于tcp/ip或http,熟悉j2ee的同学一定会对http场景下的开发比较了解.但是,精通tcp/ip以及如何构建一个直接基于tcp/ip层通讯的知识却不太多见.恰巧,最 ...

  6. 【转】安卓开发经验分享:资源、UI、函数库、测试、构建一个都不能少

    本文由 ImportNew - 唐尤华 翻译自 gigavoice.如需转载本文,请先参见文章末尾处的转载要求. 除了高超的武艺,每位黑忍者还需要装备最好的武器.在软件开发的世界里,好的工具能让我们的 ...

  7. uni-app开发经验分享二十一: 图片滑动解锁插件制作解析

    在开发用户模块的时候,相信大家都碰到过一个功能,图片滑动解锁后发送验证码,这里分享我用uni-app制作的一个小控件 效果如下: 需要如下图片资源 template <template> ...

  8. uni-app开发经验分享十九: uni-app对接微信小程序直播

    uni-app对接微信小程序直播 1.登录微信小程序后台-点击>设置->第三方设置->添加直播插件 2.添加直播组件后->点击<详情>      记录这两个参数直播 ...

  9. uni-app开发经验分享十七: 开发微信公众号(H5)JSSDK 的使用方式

    因为这个jssdk被uni-app坑了好多天,作者说支持1.4版本,但是我用1.4的两个分享的新方法一直不支持. 最后只能放弃了,期待什么时候能更新上. 基本的使用方法:第一步 - 下载使用方式下载地 ...

随机推荐

  1. Spring学习总结(15)——Spring AOP 拦截器的基本实现

    一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...

  2. 2015 Multi-University Training Contest 6 hdu 5357 Easy Sequence

    Easy Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  3. 专访Bruce Douglass,谈嵌入式经验

     Bruce:表面上看,编程就是想要实现什么就写什么代码:但事实是,敲代码只是软件开发过程中很小的一部分,程序员的工作还包括安全分析.责任分析.产品验证.产品分析等.      =========== ...

  4. 使用Eclipse进行远程调控

    什么是远程调试,就是在A机器上利用Eclipse单步跟踪调试B机器上的Web应用,当然调试A机器上Web应用也是没有问题的,90%我都是调试本机的Web应用,远程调试的意义我想我不用说了,大家都会想到 ...

  5. python的urlencode与urldecode

    ```python3.x中urlencode在urllib.parse模块中``` 当url地址含有中文,或者参数有中文的时候,这个算是很正常了,但是把这样的url作为参数传递的时候(最常见的call ...

  6. Spring进阶之路(10)-Advice简单介绍以及通过cglib生成AOP代理对象

    Advice简单介绍 1. Before:在目标方法运行之前运行织入.假设Before的处理中没有进行特殊的处理.那么目标方法终于会运行,可是假设想要阻止目标方法运行时.能够通过抛出一个异常来实现.B ...

  7. [CortexM0--stm32f0308]Low Power Mode

    问题描写叙述 stm32f0308正常是运行在Run mode下.这样的mode是在reset之后的默认模式.Low Power Mode.即低功耗模式.用于在IC空暇时能够考虑选择进入.使系统耗能减 ...

  8. hdu 5335 Walk Out (2015 Multi-University Training Contest 4)

    Walk Out                                                                         Time Limit: 2000/10 ...

  9. android 检測右滑的WebView

    今天产品出新花样非得要右滑....检測到右滑手势后事件不做处理放在Activity中做对应的处理即可了. import android.app.Activity; import android.con ...

  10. h5-注册

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAWYAAAIpCAIAAAAeogVlAAAgAElEQVR4nOy9W1gb6Z3/OTd7s9d7t8 ...