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. (5)全局异常捕捉【从零开始学Spring Boot】

    在一个项目中的异常我们我们都会统一进行处理的,那么如何进行统一进行处理呢? 新建一个类GlobalDefaultExceptionHandler, 在class注解上@ControllerAdvice ...

  2. oracle导入expdp、导出impdp数据库用户

    仅限oracle服务器上执行:把172.16.251.136:1521/orcl的AMI4_2用户导入到192.168.2.30:1521/orclss中的AMI1用户:  关于导入导出更详细的见文章 ...

  3. BA-BACnet对象

    BACNET协议有多少个对象呢,拿出西门子教程中的看看一下,居然有48个,其中的大部分都没有用到:

  4. java cocurrent包

    1. java.util.concurrent - Java 并发工具包 Java 5 添加了一个新的包到 Java 平台,java.util.concurrent 包.这个包包含有一系列能够让 Ja ...

  5. PowerDesigner16 破解

    近期开发项目,涉及到实体设计这块的时候,用的是PowerDesigner16,使用是挺方便的,可是存在一个问题.那就是PowerDesigner16存在一个试用期的问题,过期就打不开了. 之前好多同学 ...

  6. [Tailwind] Get started with Tailwindcss

    In this lesson, we learn how to generate CSS utility classes from Tailwind's JavaScript config file. ...

  7. Autodesk 举办的 Revit 2015 二次开发速成( 1.5 天),教室培训, 地点武汉

    2014年8月26日9:00 – 17:00 2014年8月27日9:00 – 12:00 培训地点: Ø 湖北工业大学 实训楼605教室 Ø 地址:武汉市武昌区南湖李家墩一村一号 Ø 交通路线说明: ...

  8. hdu2767 Proving Equivalences,有向图强联通,Kosaraju算法

    点击打开链接 有向图强联通,Kosaraju算法 缩点后分别入度和出度为0的点的个数 answer = max(a, b); scc_cnt = 1; answer = 0 #include<c ...

  9. angularjs1-7,供应商

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  10. HDU 5863 cjj's string game (矩阵乘法优化递推)

    题目大意:用k种字符构建两个长度为n的字符串(每种字符有无限多个),要求对应位置字符相同的连续子串最长长度为m,问方法数. 其中k,n,m是输入,n(1<=n<=1000000000), ...