Nuxt.js使用详细说明
这篇文章主要向大家介绍Nuxt爬坑,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。
https://www.shangmayuan.com/a/dcd382c2e24d427bae7df0f1.html
静态部署:Nuxt.js学习(九) --- 静态应用部署、单页应用程序部署丶Java教程网-IT开发者们的技术天堂
第一节:nuxt.js相关概述
nuxt.js简单的说是Vue.js的通用框架,最经常使用的就是用来做SSR(服务器端渲染).Vue.js是开发SPA(单页应用)的,Nuxt.js这个框架,用Vue开发多页应用,并在服务端完成渲染,能够直接用命令把咱们制做的vue项目生成为静态html。javascript
1.那服务器端渲染到底有什么好处呢?
主要的缘由时SPA(单页应用)不利于搜索引擎的SEO操做,Nuxt.js适合做新闻、博客、电影、咨询这样的须要搜索引擎提供流量的项目。若是你要做移动端的项目,就不必使用这个框架了。css
2.什么是SSR?
在认识SSR以前,首先对CSR与SSR之间作个对比。html
首先看一下传统的web开发,传统的web开发是,客户端向服务端发送请求,服务端查询数据库,拼接HTML字符串(模板),经过一系列的数据处理以后,把整理好的HTML返回给客户端,浏览器至关于打开了一个页面。这种好比咱们常常据说过的jsp,PHP,aspx也就是传统的MVC的开发。前端
SPA应用,到了Vue、React,单页面应用优秀的用户体验,逐渐成为了主流,页面总体式javaScript渲染出来的,称之为客户端渲染CSR。SPA渲染过程。由客户端访问URL发送请求到服务端,返回HTML结构(可是SPA的返回的HTML结构是很是的小的,只有一个基本的结构,如第一段代码所示)。客户端接收到返回结果以后,在客户端开始渲染HTML,渲染时执行对应javaScript,最后渲染template,渲染完成以后,再次向服务端发送数据请求,注意这里时数据请求,服务端返回json格式数据。客户端接收数据,而后完成最终渲染。vue
SPA虽然给服务器减轻了压力,可是也是有缺点的:
- 首屏渲染时间比较长:必须等待JavaScript加载完毕,而且执行完毕,才能渲染出首屏。
- SEO不友好:爬虫只能拿到一个div元素,认为页面是空的,不利于SEO。
为了解决如上两个问题,出现了SSR解决方案,后端渲染出首屏的DOM结构返回,前端拿到内容带上首屏,后续的页面操做,再用单页面路由和渲染,称之为服务端渲染(SSR)。node
SSR渲染流程是这样的,客户端发送URL请求到服务端,服务端读取对应的url的模板信息,在服务端作出html和数据的渲染,渲染完成以后返回html结构,客户端这时拿到的以后首屏页面的html结构。因此用户在浏览首屏的时候速度会很快,由于客户端不须要再次发送ajax请求。并非作了SSR咱们的页面就不属于SPA应用了,它仍然是一个独立的spa应用。android
SSR是处于CSR与SPA应用之间的一个折中的方案,在渲染首屏的时候在服务端作出了渲染,注意仅仅是首屏,其余页面仍是须要在客户端渲染的,在服务端接收到请求以后而且渲染出首屏页面,会携带着剩余的路由信息预留给客户端去渲染其余路由的页面。webpack
Nuxt.js是特色(优势):ios
- 基于Vue
- 自动代码分层
- 服务端渲染
- 强大的路由功能,支持异步数据
- 静态文件服务
- EcmaScript6和EcmaScript7的语法支持
- 打包和压缩JavaScript和Css
- HTML头部标签管理
- 本地开发支持热加载
- 集成ESLint
- 支持各类样式预编译器SASS、LESS等等
- 支持HTTP/2推送
第二节:Nuxt环境搭建
1.nuxt.js安装
在使用npm前你须要安装Node到系统中。若没有安装参考此连接 www.cnblogs.com/zhouyu2017/…
(1)用npm来安装vue-cli这个框架。
npm install vue-cli -g 复制代码
安装完成后可使用vue -V 来测试是否安装成功。(注意:这里要使用大写的V,小写无效)。
(2)使用vue安装 nuxt
安装好vue-cli后,就可使用init命令来初始化Nuxt.js项目。
vue init nuxt/starter 复制代码
这时候他会在github上下载模版,而后会询问你项目的名称叫什么,做者什么的,这些彻底能够根据本身的爱好填写。
(3)使用npm install安装依赖包
npm install 复制代码
这个过程是要等一会的,若是你这个过程安装失败,能够直接诶删除项目中的node_modules文件夹后,从新npm install进行安装。
(4)使用npm run dev 启动服务
(5)在浏览器输入 localhost:3000,能够看到结果,以下:
2.第一个Nuxt应用程序安装
npm i create-nuxt-app -g
create-nuxt-app my-nuxt-demo
cd my-nuxt-demo
npm run dev
安装向导:
Project name // 项目名称
Project description // 项目描述
Use a custom server framework // 选择服务器框架
Choose features to install // 选择安装的特性
Use a custom UI framework // 选择UI框架
Use a custom test framework // 测试框架
Choose rendering mode // 渲染模式
Universal // 渲染全部链接页面
Single Page App // 只渲染当前页面
3.Nuxt 渲染流程
一个完整的服务器请求到渲染的流程
经过上面的流程图能够看出,当一个客户端请求进入的时候,服务端有经过nuxtServerInit这个命令执行在Store的action中,在这里接收到客户端请求的时候,能够将一些客户端信息存储到Store中,也就是说能够把在服务端存储的一些客户端的一些登陆信息存储到Store中。以后使用了中间件机制,中间件其实就是一个函数,会在每一个路由执行以前去执行,在这里能够作不少事情,或者说能够理解为是路由器的拦截器的做用。而后再validate执行的时候对客户端携带的参数进行校验,在asyncData与fetch进入正式的渲染周期,asyncData向服务端获取数据,把请求到的数据合并到Vue中的data中,
第三节 :Nuxt目录结构
一个完整的服务器请求到渲染的流程
经过上面的流程图能够看出,当一个客户端请求进入的时候,服务端有经过nuxtServerInit这个命令执行在Store的action中,在这里接收到客户端请求的时候,能够将一些客户端信息存储到Store中,也就是说能够把在服务端存储的一些客户端的一些登陆信息存储到Store中。以后使用了中间件机制,中间件其实就是一个函数,会在每一个路由执行以前去执行,在这里能够作不少事情,或者说能够理解为是路由器的拦截器的做用。而后再validate执行的时候对客户端携带的参数进行校验,在asyncData与fetch进入正式的渲染周期,asyncData向服务端获取数据,把请求到的数据合并到Vue中的data中,
第三节 :Nuxt目录结构
# 目录结构介绍
└─my-nuxt-demo
├─.nuxt // Nuxt自动生成,临时的用于编辑的文件,build
├─assets // 用于组织未编译的静态资源如LESS、SASS或JavaScript,对于不须要经过 Webpack 处理的静态资源文件,能够放置在 static 目录中
├─components // 用于本身编写的Vue组件,好比日历组件、分页组件
├─layouts // 布局目录,用于组织应用的布局组件,不可更改⭐
├─middleware // 用于存放中间件
├─node_modules
├─pages // 用于组织应用的路由及视图,Nuxt.js根据该目录结构自动生成对应的路由配置,文件名不可更改⭐
├─plugins // 用于组织那些须要在 根vue.js应用 实例化以前须要运行的 Javascript 插件。
├─static // 用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。 服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下。文件夹名不可更改。⭐
└─store // 用于组织应用的Vuex 状态管理。文件夹名不可更改。⭐
├─.editorconfig // 开发工具格式配置
├─.eslintrc.js // ESLint的配置文件,用于检查代码格式
├─.gitignore // 配置git忽略文件
├─nuxt.config.js // 用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置。文件名不可更改。⭐
├─package-lock.json // npm自动生成,用于帮助package的统一设置的,yarn也有相同的操做
├─package.json // npm 包管理配置文件
├─README.md
# 配置文件
const pkg = require('./package')
module.exports = {
mode: 'universal', // 当前渲染使用模式
head: { // 页面head配置信息
title: pkg.name, // title
meta: [ // meat
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [ // favicon,若引用css不会进行打包处理
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
loading: { color: '#fff' }, // 页面进度条
css: [ // 全局css(会进行webpack打包处理)
'element-ui/lib/theme-chalk/index.css'
],
plugins: [ // 插件
'@/plugins/element-ui'
],
modules: [ // 模块
'@nuxtjs/axios',
],
axios: {},
build: { // 打包
transpile: [/^element-ui/],
extend(config, ctx) { // webpack自定义配置
}
}
}
# Nuxt运行命令
{
"scripts": {
// 开发环境
"dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
// 打包
"build": "nuxt build",
// 在服务端运行
"start": "cross-env NODE_ENV=production node server/index.js",
// 生成静态页面
"generate": "nuxt generate"
}
}
第四节:Nuxt经常使用配置项
1.配置IP和端口
开发中常常会遇到端口被占用或者指定IP的状况。咱们须要在根目录下的package.json里对config项进行配置。好比如今咱们想把IP配置成127.0.0.1,端口设置1000。
//package.json
"config":{
"nuxt":{
"host":"127.0.0.1",
"port":"1000"
}
},
配置好后,咱们在终端中输入npm run dev,而后你会看到服务地址改成了127.0.0.1:1000.
2.配置全局CSS
在开发多页项目时,都会定义一个全局的CSS来初始化咱们的页面渲染,好比把padding和margin设置成0,网上也有很是出名的开源css文件normailze.css。要定义这些配置,须要在nuxt.config.js里进行操做。
好比如今咱们要把页面字体设置为红色,就能够在assets/css/common.css文件,而后把字体设置为红色。
/assets/css/common.css
html{ color:red; }
/nuxt.config.js
css:['~assets/css/normailze.css'],
设置好后,在终端输入npm run dev 。而后你会发现字体已经变成了红色。
3.配置webpack的loader
在nuxt.config.js里是能够对webpack的基本配置进行覆盖的,好比如今咱们要配置一个url-loader来进行小图片的64位打包。就能够在nuxt.config.js的build选项里进行配置,相关可参照此连接www.cnblogs.com/ssh-007/p/7…
build: {
loaders:[
{
test:/\.(png|jpe?g|gif|svg)$/,
loader:"url-loader",
query:{
limit:10000,
name:'img/[name].[hash].[ext]'
}
}
],
/*
** Run ESLint on save
*/
extend (config, { isDev, isClient }) {
if (isDev && isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
}
}
4.全局修改seo的head信息
nuxt.config.js文件中,修改title为wfaceboss:
head: {
title: 'wfaceboss',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'Nuxt.js project' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
修改后重启服务,即运行 npm run dev,效果以下
第五节:Nuxt的路由配置和参数传递
Nuxt.js的路由并不复杂,它给咱们进行了封装,让咱们节省了不少配置环节。
1.基本路由
Nuxt.js 依据 pages 目录结构自动生成 vue-router 模块的路由配置。
假设 pages 的目录结构以下
└─pages
├─index.vue
└─user
├─index.vue
├─one.vue
那么,Nuxt.js 自动生成的路由配置以下:
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'user',
path: '/user',
component: 'pages/user/index.vue'
},
{
name: 'user-one',
path: '/user/one',
component: 'pages/user/one.vue'
}
]
}
2.页面跳转
- 不要写成a标签,由于是从新获取一个新的页面,并非SPA
- <nuxt-link to="/users"></nuxt-link>
- this.$router.push('/users')
3.动态路由
- 在 Nuxt.js 里面定义带参数的动态路由,须要建立对应的如下划线做为前缀的 Vue 文件 或 目录。
- 获取动态参数{{$route.params.id}}
4.跳转路由传递参数而且取值
路由常常须要传递参数,咱们能够简单的使用params来进行传递参数,咱们如今向新闻页面(news)传递个参数,而后在新闻页面进行简单的接收。
(1)使用nuxt传递参数
<template>
<div>
<ul>
<li><nuxt-link :to="`informa/${item.newsCode}-${item.newsType}`"></li>
</ul>
</div>
</template>
注意:name其实指向的是路由(文件夹或文件名),而路由死活区分大小写的 , 因此to后面区分大小写!!!建议文件夹都写成小写的。
(2)使用nuxt接收参数
async asyncData(context) {
let newsCode = context.route.params.code.split('-')[0]
let newsType = context.route.params.code.split('-')[1]
},
(3)使用this.$router.push的params传递参数
传递参数 -- this.$router.push({path: ' 路由 ', query: {key: value}}) 参数取值 -- this.$route.query.key 注: 使用这种方式,传递参数会拼接在路由后面,出如今地址栏
(4)使用this.$router.push的params传递参数
传递参数 -- this.$router.push({name: ' 路由的name ', params: {key: value}}) 参数取值 -- this.$route.params.key 注: 使用这种方式,参数不会拼接在路由后面,地址栏上看不到参数 注意: 因为动态路由也是传递params的,因此在 this.$router.push() 方法中 path不能和params一块儿使用,不然params将无效。须要用name来指定页面。 复制代码
4.项目需求url优化
this.$route.query.key的方式参数显示在地址栏上, 可是并非咱们想要的, :id?id=``?
因此建议仍是尽可能使用router-link来实现跳转来解决地址栏的变化,更方便网站的优化
5.路由参数校验
Nuxt.js 可让你在动态路由对应的页面组件中配置一个validate方法用于校验动态路由参数的有效性。该函数有一个布尔类型的返回值,若是返回true则表示校验经过,若是返回false则表示校验未经过。
export default {
// nuxt中使用validate方法进行路由参数校验,这个方法必须返回一个布尔值,为true表示校验经过,为false表示校验失败。注意validate不能写到methods属性中。
validate(obj) {
// console.log(obj);
// return true
return /^\d+$/.test(obj.params.id)
}
}
6.嵌套路由
- 添加一个Vue文件,做为父组件
- 添加一个与父组件同名的文件夹来存放子视图组件
- 在父文件中,添加组件,用于展现匹配到的子视图
第六节:Nuxt的路由动画效果
路由的动画效果,也叫做页面的更换效果。Nuxt.js提供两种方法为路由提供动画效果,一种是全局的,一种是针对单独页面制做。
1.全局路由动画
全局动画默认使用page来进行设置,例如如今咱们为每一个页面都设置一个进入和退出时的渐隐渐现的效果。咱们能够先在根目录的assets/css下创建一个normailze.css文件。
(1)添加样式文件
/assets/css/normailze.css(没有请自行创建)
.page-enter-active, .page-leave-active {
transition: opacity 2s;
}
.page-enter, .page-leave-active {
opacity: 0;
}
(2)文件配置
而后在nuxt.config.js里加入一个全局的css文件就能够了。
css:['assets/css/main.css'], 复制代码
这时候在页面切换的时候就会有2秒钟的动画切换效果了,可是你会发现一些页面是没有效果的,这是由于你没有是组件来制做跳转连接。你须要进行更改。
好比咱们上节课做的动态路由新闻页,你就须要改为下面的连接。
<li><nuxt-link :to="{name:'news-id',params:{id:123}}">News-1</nuxt-link></li>
改过以后你就会看到动画效果了。
2.单独设置页面动效
想给一个页面单独设置特殊的效果时,咱们只要在css里改变默认的page,而后在页面组件的配置中加入transition字段便可。例如,咱们想给about页面加入一个字体放大而后缩小的效果,其余页面没有这个效果。
(1)在全局样式assets/main.css 中添加如下内容
.test-enter-active, .test-leave-active {
transition: all 2s;
font-size:12px;
}
.test-enter, .test-leave-active {
opacity: 0;
font-size:40px;
}
(2)而后在about/index.vue组件中设置
export default {
transition:'test'
}
这时候就有了页面的切换独特动效了。
总结:在须要使用的页面导入便可。
第七节:Nuxt的默认模版和默认布局
在开发应用时,常常会用到一些公用的元素,好比网页的标题是同样的,每一个页面都是如出一辙的标题。这时候咱们有两种方法,第一种方法是做一个公用的组件出来,第二种方法是修改默认模版。这两种方法各有利弊,好比公用组件更加灵活,可是每次都须要本身手动引入;模版比较方便,可是只能每一个页面都引入。
1.默认模板
Nuxt为咱们提供了超简单的默认模版订制方法,只要在根目录下建立一个app.html就能够实现了。如今咱们但愿每一个页面的最上边都加入“ 学习nuxt.js” 这几个字,咱们就可使用默认模版来完成。
app.html中:
<!DOCTYPE html>
<html lang="en">
<head>
{{ HEAD }}
</head>
<body>
<p>学习nuxt.js</p>
{{ APP }}
</body>
</html>
这里的{{ HEAD }}读取的是nuxt.config.js里的信息,{{APP}} 就是咱们写的pages文件夹下的主体页面了。须要注意的是HEAD和APP都须要大写,若是小写会报错的。
注意:若是你创建了默认模板后,记得要重启服务器,不然显示不会成功;可是默认布局是不用重启服务器的。
2.默认布局
默认模板相似的功能还有默认布局,可是从名字上你就能够看出来,默认布局主要针对于页面的统一布局使用。它在位置根目录下的layouts/default.vue。须要注意的是在默认布局里不要加入头部信息,只是关于标签下的内容统一订制。
需求:咱们在每一个页面的最顶部放入“学习nuxt.js” 这几个字,看一下在默认布局里的实现。
<template>
<div>
<p>学习nuxt.js</p>
<nuxt/>
</div>
</template>
这里的就至关于咱们每一个页面的内容,你也能够把一些通用样式放入这个默认布局里,但会增长页面的复杂程度。
总结:要区分默认模版和默认布局的区别,模版能够订制不少头部信息,包括IE版本的判断;模版只能定制里的内容,跟布局有关系。在工做中修改时要看状况来编写代码。
第八节:Nuxt插件的使用
1.ElementUI使用
下载npm i element-ui -S
- 在plugins文件夹下面,建立ElementUI.js文件
import Vue from 'vue' import ElementUI from 'element-ui' Vue.use(ElementUI)
- 在nuxt.config.js中添加配置
css: [ 'element-ui/lib/theme-chalk/index.css' ], plugins: [ {src: '~/plugins/ElementUI', ssr: true } ], build: { vendor: ['element-ui'] }
2.axios的使用
- 安装npm install --save axios
- 使用
import axios from 'axios' asyncData(context, callback) { axios.get('http://localhost:3301/in_theaters') .then(res => { console.log(res); callback(null, {list: res.data}) }) }
- 为防止重复打包,在nuxt.config.js中配置
module.exports = { build: { vendor: ['axios'] } }
第九节:Nuxt的错误页面和个性meta设置
当用户输入路由错误的时候,咱们须要给他一个明确的指引,因此说在应用程序开发中404页面是必不可少的。Nuxt.js支持直接在默认布局文件夹里创建错误页面。
1.创建错误页面
在根目录下的layouts文件夹下创建一个error.vue文件,它至关于一个显示应用错误的组件。
<template>
<div>
<h2 v-if="error.statusCode==404">404页面不存在</h2>
<h2 v-else>500服务器错误</h2>
<ul>
<li><nuxt-link to="/">HOME</nuxt-link></li>
</ul>
</div>
</template>
<script>
export default {
props:['error'],
}
</script>
代码用v-if进行判断错误类型,须要注意的是这个错误是你须要在<script>
里进行声明的,若是不声明程序是找不到error.statusCode的。
这里我也用了一个<nuxt-link>的简单写法直接跟上路径就能够了。
2.个性meta设置
页面的Meta对于SEO的设置很是重要,好比你如今要做个新闻页面,那为了搜索引擎对新闻的收录,须要每一个页面对新闻都有不一样的title和meta设置。直接使用head方法来设置当前页面的头部信息就能够了。咱们如今要把New-1这个页面设置成个性的meta和title。
1.咱们先把pages/news/index.vue页面的连接进行修改一下,传入一个title,目的是为了在新闻具体页面进行接收title,造成文章的标题。
/pages/news/index.vue
<li><nuxt-link :to="{name:'news-id',params:{id:123,title:'nuxt.com'}}">News-1</nuxt-link></li>
2.第一步完成后,咱们修改/pages/news/_id.vue,让它根据传递值变成独特的meta和title标签。
<template>
<div>
<h2>News-Content [{{$route.params.id}}]</h2>
<ul>
<li><a href="/">Home</a></li>
</ul>
</div>
</template>
<script>
export default {
validate ({ params }) {
// Must be a number
return /^\d+$/.test(params.id)
},
data(){
return{
title:this.$route.params.title,
}
},
//独立设置head信息
head(){
return{
title:this.title,
meta:[
{hid:'description',name:'news',content:'This is news page'}
]
}
}
}
</script>
注意:为了不子组件中的meta标签不能正确覆盖父组件中相同的标签而产生重复的现象,建议利用 hid 键为meta标签配一个惟一的标识编号。
第十节:asyncData方法获取数据
Nuxt.js贴心的为咱们扩展了Vue.js的方法,增长了anyncData,异步请求数据。
1.造假数据
(1)建立远程数据
在这里制做一些假的远程数据,我选择的网站是myjson.com,它是一个json的简单仓库,学习使用是很是适合的。 咱们打开网站,在对话空中输入JSON代码,这个代码能够随意输入,key和value均采用字符串格式建立。
{
"name": "Nuxt",
"age": 18,
"interest": "I love coding!"
}
输入后保存,网站会给你一个地址,这就是你这个JSON仓库的地址了。api.myjson.com/bins/1ctwlm
(2)安装Axios
Vue.js官方推荐使用的远程数据获取方式就Axios,因此咱们安装官方推荐,来使用Axios。这里咱们使用npm 来安装 axios。 直接在终端中输入下面的命令:
npm install axios --save
2.ansycData的promise方法
咱们在pages下面新建一个文件,叫作ansyData.vue。而后写入下面的代码:
<script>
import axios from 'axios'
export default {
data(){
return {
name:'hello World',
}
},
asyncData(){
return axios.get('https://api.myjson.com/bins/1ctwlm')
.then((res)=>{
console.log(res)
return {info:res.data}
})
}
}
</script>
这时候咱们能够看到,浏览器中已经能输出结果了。asyncData的方法会把值返回到data中。是组件建立(页面渲染)以前的动做,因此不能使用this.info,
# return的重要性
必定要return出去获取到的对象,这样就能够在组件中使用,这里返回的数据会和组件中的data合并。这个函数不光在服务端会执行,在客户端一样也会执行。 复制代码
3.ansycData的promise并发应用
async asyncData(context) {
let [newDetailRes, hotInformationRes, correlationRes] = await Promise.all([
axios.post('http://www.huanjingwuyou.com/eia/news/detail', {
newsCode: newsCode
}),
axios.post('http://www.huanjingwuyou.com/eia/news/select', {
newsType: newsType, // 资讯类型: 3环评资讯 4环评知识
start: 0, // 从第0条开始
pageSize: 10,
newsRecommend: true
}),
axios.post('http://www.huanjingwuyou.com/eia/news/select', {
newsType: newsType, // 资讯类型: 3环评资讯 4环评知识
start: 0, // 从第0条开始
pageSize: 3,
newsRecommend: false
})
])
return {
newDetailList: newDetailRes.data.result,
hotNewList: hotInformationRes.data.result.data,
newsList: correlationRes.data.result.data,
newsCode: newsCode,
newsType: newsType
}
},
4.ansycData的await方法
固然上面的方法稍显过期,如今都在用ansyc…await来解决异步,改写上面的代码。
<script>
import axios from 'axios'
export default {
data(){
return {
name:'hello World',
}
},
async asyncData(){
let {data}=await axios.get('https://api.myjson.com/bins/8gdmr')
return {info: data}
}
}
</script>
复制代码
5.注意事项+生命周期:
- asyncData 方法会在组件(限于页面组件)每次加载以前被调用
- asyncData 能够在服务端或路由更新以前被调用
- 第一个参数被设定为当前页面的上下文对象
- Nuxt会将 asyncData 返回的数据融合到组件的data方法返回的数据一并返回给组件使用
- 对于 asyncData 方式实在组件初始化前被调用的,因此在方法内饰没办法经过this来引用组件的实例对象
第十一节:静态资源和打包
1.静态资源
(1)直接引入图片 在网上任意下载一个图片,放到项目中的static文件夹下面,而后可使用下面的引入方法进行引用
<div><img src="~static/logo.png" /></div>
“~”就至关于定位到了项目根目录,这时候图片路径就不会出现错误,就算打包也是正常的。
(2)CSS引入图片 若是在CSS中引入图片,方法和html中直接引入是同样的,也是用“~”符号引入。
<style>
.diss{
width: 300px;
height: 100px;
background-image: url('~static/logo.png')
}
</style>
这时候在npm run dev 下是彻底正常的。
2.打包
用Nuxt.js制做完成后,你能够打包成静态文件并放在服务器上,进行运行。
在终端中输入:
npm run generate
而后在dist文件夹下输入live-server就能够了。
总结:Nuxt.js框架很是简单,由于大部分的事情他都为咱们作好了,咱们只要安装它的规则来编写代码。
第十二节:nuxt的跨域解决+拦截器
安装axios
npm install @nuxtjs/axios --save-dev
安装完成后更改配置信息:
nuxt.config.js
module.exports = {
modules: [
// Doc: https://axios.nuxtjs.org/usage
'@nuxtjs/axios',
],
axios: {
proxy:true // 代理
},
axios: {
proxy: true,
prefix: '/api', // baseURL
credentials: true,
},
proxy: {
"/eia/":"http://192.168.0.97:8181/", // key(路由前缀):value(代理地址)
changeOrigin: true, // 是否跨域
pathRewrite: {
'^/api': '' //路径重写
}
}
}
既然说到了axios,就不得不提到的一个东西就是拦截器,非常有用在项目开发过程当中必不可少的。
举个例子:
npm install @nuxtjs/axios @nuxtjs/proxy --save
module.expores{
plugins: [
{
src: "~/plugins/axios",
ssr: false
},
],
modules: [
// Doc: https://axios.nuxtjs.org/usage
'@nuxtjs/axios',
],
}
plugins/axios.js
export default ({ $axios, redirect }) => {
$axios.onRequest(config => {
console.log('Making request to ' + config.url)
})
$axios.onError(error => {
const code = parseInt(error.response && error.response.status)
if (code === 400) {
redirect('/400')
}
})
}
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 => {})
}
第十三节:爬坑
1.NuxtServerError connect ECONNREFUSED 127.0.0.1:80
缘由: asyncData方法异步请求数据时,觉得/api/${params.id}这个接口的网址是 127.0.0.1:80, 因此将请求发送给了127.0.0.1:80,而个人接口服务器并无跑在80端口上,因此报错。
解决方法:
将node服务器端口改为 127.0.0.1:80
将接口服务器端口改为 127.0.0.1:80
将asyncData方法使用的请求url加上域名+端口,以下所示
export default {
asyncData ({ params }) {
return axios.get(`https://127.0.0.1:3000/api/${params.id}`)
.then((res) => {
return { title: res.data.title }
})
}
}
1. 如何在 head 里面引入js文件?
背景: 在<head>标签中,以inline的形式引入flexible.js文件。本项目主要为移动端项目,引入flexible.js 实现移动端适配问题。
Nuxt.js 经过 vue-meta 实现头部标签管理,经过查看文档发现,能够按照以下方式配置:
head: {
script: [{ innerHTML: require('./assets/js/flexible'), type: 'text/javascript', charset: 'utf-8'}],
__dangerouslyDisableSanitizers: ['script']
}
2.nuxt使用less,sass等预处理器
背景:在组件中的<template>, <script> 或 <style> 上使用各类预处理器,加上处理器后,控制台报错。
更换安装源:
npm config set sass_binary_site=https://npm.taobao.org/mirrors/node-sass
npm install --save-dev node-sass sass-loader
可是解决过程并非很顺利的,在阅读中文文档时,忽略版本号,按照上面的提示进行操做,发现不能成功,后来各类debug,最后发现了该解决方案。后知后觉的发现了中文文档的版本号太低,若是须要查看文档,必定要看最新版本的英文文档!
3. 如何使用px2rem
背景:在css中,写入px,经过px2rem loader,将px转换成rem
在之前的项目中,是经过 px2rem loader实现的,可是在Nuxt.js项目下,添加 css loader 仍是很费力的,由于涉及到vue-loader。
想到了一个其余方案,可使用 postcss 处理。能够在 nuxt.config.js 文件中添加配置,也能够在postcss.conf.js文件中添加。
build: {
postcss: [
require('postcss-px2rem')({
remUnit: 75 // 转换基本单位
})
]
},
4. 如何拓展 webpack 配置
背景:给 utils 目录添加别名
刚刚说到,Nuxt.js内置了 webpack 配置,若是想要拓展配置,能够在 nuxt.config.js 文件中添加。同时也能够在该文件中,将配置信息打印出来。
extend (config, ctx) {
console.log('webpack config:', config)
if (ctx.isClient) {
// 添加 alias 配置
Object.assign(config.resolve.alias, {
'utils': path.resolve(__dirname, 'utils')
})
}
}
5. 如何添加 vue plugin
背景:本身封装了一个 toast vue plugin,因为 vue 实例化的过程没有暴露出来,不知道在哪一个时机注入进去。
能够在 nuxt.config.js 中添加 plugins 配置,这样插件就会在 Nuxt.js 应用初始化以前被加载导入。
module.exports = {
plugins: ['~plugins/toast']
}
~plugins/toast.js 文件:
import Vue from 'vue'
import toast from '../utils/toast'
import '../assets/css/toast.css'
Vue.use(toast)
6.如何修改环境变量 NODE_ENV
背景:在项目中,设置 3个 NODE_ENV 的值,来对应不一样的版本。development,本地开发;release,预发布版本;production,线上版本。其中,预发布版本比production版本,多出vconsole。
// package.json
"scripts": {
"buildDev": "cross-env NODE_ENV=release nuxt build && backpack build",
"startDev": "cross-env NODE_ENV=release PORT=3000 node build/main.js"
},
打印 process.env.NODE_ENV 依旧是,production。
在 backpack 的源码中,找到了答案,在 执行 backpack build 命令时,会把 process.env.NODE_ENV 修改成 production,而且是写死的不可配置的......
无奈下,只能在 process.env 下,添加 __ENV 属性,表明 NODE_ENV
这时,在页面中打印出来的信息 process.env.__ENV undefined,可是能够打印出 process.env.NODE_ENV。
能够经过配置 nuxt.config.js 中的,env属性,解决该问题。
env: {
__ENV: process.env.__ENV
}
复制代码
7. Window 或 Document 对象未定义?
背景: 在引入第三方插件,或者直接在代码中写 window 时,控制台会给出警告,window 未定义。
发生在这个问题的缘由时,node服务端并无window 或 document 对象。解决方法,经过 process.browser 来区分环境。
if (process.browser) {
// 引入第三方插件
require('***')
// 或者修改window对象下某一属性
window.mbk = {}
}
8.按需引入(UI框架等等)
例如使用UI框架:element-ui
我找了不少相关文章,并无详细说明该如何引入。因此我要拿出来将他说明:
先来看下,若是不按需引入vendor.js的体积大小为:
第一步,下载依赖:
# 先下载element-ui
npm install element-ui --save
# 若是使用按需引入,必须安装babel-plugin-component(官网有须要下载说明,此插件根据官网规则不一样,安装插件不一样)
npm install babel-plugin-component --save-dev
安装好之后,按照nuxt.js中的规则,你须要在 plugins/ 目录下建立相应的插件文件
在文件根目录建立(或已经存在)plugins/目录,建立名为:element-ui.js的文件,内容以下:
import Vue from 'vue'
import { Button } from 'element-ui' //引入Button按钮
export default ()=>{
Vue.use(Button)
}
第二步,引入插件
在nuxt.config.js中,添加配置为:plugins
css:[
'element-ui/lib/theme-chalk/index.css'
],
plugins:[
'~/plugins/element-ui'
]
默认为:开启SSR,采用服务端渲染,也能够手动配置关闭SSR,配置为:
css:[
'element-ui/lib/theme-chalk/index.css'
],
plugins:[
{
src:'~/plugins/element-ui',
ssr:false //关闭ssr
}
]
第三步,配置babel选项
在nuxt.config.js中,配置在build选项中,规则为官网规则:
build: {
babel:{ //配置按需引入规则
"plugins":[
[
"component",
{
"libraryName":"element-ui",
"styleLibraryName":"theme-chalk"
}
]
]
},
/*
** Run ESLINT on save
*/
extend (config, ctx) {
if (ctx.isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
}
}
此时,咱们在观察打包之后文件体积大小,如图:
此时,咱们成功完成了按需引入配置。
9.不想服务端渲染的地方
(1)
<no-ssr>
插件或者组件
</no-ssr>
(2)
nuxt.config.js里ssr改成false
plugins: [
{src: '~/plugins/ElementUI', ssr: false }
],
10.nuxt必须在接口地址前加上访问域名
解决: 可使用axios的baseURL来代理
import Vue from 'vue'
import axios from 'axios'
// axios.defaults.baseURL = "http://www.huanjingwuyou.com/"
axios.defaults.baseURL = "http://localhost:3000/"
// axios.defaults.baseURL = "http://test.huanjingwuyou.com/"
export default axios
第十四节:Nuxt爬坑更新- 判断设备进行跳转手机端
nuxt是没有index.html页面的, 我们应该在哪里写js代码来判断设备呢, 下面请看个人代码吧
1. 引入middleware中间件
在nuxt.config.js里经过router来引入middleware中间件
nuxt.config.js代码以下
export default {
router: {
middleware: ["device"],
},
}
2. 在根目录新建utils文件而且新建文件deviceType.js
deviceType.js文件代码以下
/**
*
* @param {*} UA ,就是userAgent
* @returns type: 设备类型
* env: 访问环境(微信/微博/qq)
* masklayer: 就是给外部拿到判断是否显示遮罩层的,一些特殊环境要引导用户到外部去打开访问
*/
function isWechat(UA) {
return /MicroMessenger/i.test(UA) ? true : false;
}
function isWeibo(UA) {
return /Weibo/i.test(UA) ? true : false;
}
function isQQ(UA) {
return /QQ/i.test(UA) ? true : false;
}
function isMoible(UA) {
return /(Android|webOS|iPhone|iPod|tablet|BlackBerry|Mobile)/i.test(UA) ?
true :
false;
}
function isIOS(UA) {
return /iPhone|iPad|iPod/i.test(UA) ? true : false;
}
function isAndroid(UA) {
return /Android/i.test(UA) ? true : false;
}
export function deviceType(UA) {
if (isMoible(UA)) {
if (isIOS(UA)) {
if (isWechat(UA)) {
return {
type: "ios",
env: "wechat",
masklayer: true,
};
}
if (isWeibo(UA)) {
return {
type: "ios",
env: "weibo",
masklayer: true,
};
}
if (isQQ(UA)) {
return {
type: "ios",
env: "qq",
masklayer: true,
};
}
return {
type: "ios",
};
}
if (isAndroid(UA)) {
if (isWechat(UA)) {
return {
type: "android",
env: "wechat",
masklayer: true,
};
}
if (isWeibo(UA)) {
return {
type: "android",
env: "weibo",
masklayer: true,
};
}
if (isQQ(UA)) {
return {
type: "android",
env: "qq",
masklayer: true,
};
}
return {
type: "android",
};
}
return {
type: "mobile",
};
} else {
return {
type: "pc",
};
}
}
3. 在middleware里添加device.js文件
device.js代码以下
// @ts-nocheck
import { deviceType } from "~/utils/deviceType";
export default function(context) {
// @ts-ignore
context.userAgent = process.server ?
context.req.headers["user-agent"] :
navigator.userAgent;
// 给全局上下文添加一个属性来保存咱们返回的匹配信息
context.deviceType = deviceType(context.userAgent);
// 这里注入到store,是由于我部分页面须要判断机型请求不一样的数据,
// 大家没有用到的话能够移除
// context.store.commit("SetDeviceType", context.deviceType);
// 如果判断UA非移动端的,就在这里作处理了..
// context.redirect(status,url) 这个能够重定向到外部网站
// 如果内部访问能够直接用router对象push
if (context.deviceType.type === "pc") {
// context.redirect(302,'www.huanjingwuyou.com') //301是永久重定向,若是你想随着设备类型改变一直变,请改成302
} else {
context.redirect(302,'m.huanjingwuyou.com') //301是永久重定向,若是你想随着设备类型改变一直变,请改成302
}
}
心得:
0. nuxt渲染页面分为两个阶段, 服务端渲染和浏览器渲染
1. nuxt能够用服务端渲染阶段asyncData来提早获取到数据, 数据自动存放到data中, 浏览器渲染时直接拿data数据
2. asyncData方法会在组件(限于页面组件)每次会在刷新加载页面或者切换路由时被调用,顺序比beforeCreate和created以前
3. nuxt服务端渲染时生命周期只有两个钩子函数created和beforeCreate两个钩子函数,
4. async作并发请求
5. 设置head来提升SEO, 局部须要return {}
6. 每次调用接口的时候须要在接口前面加上访问域名, 能够经过axios配置axios.defaults.baseURL
7. nuxt用proxy来代理
8. 跳到详情页用nuxt-link来跳转, 这样url地址参数更有利于seo, 跳转时域名都是本身拼接上去的
9. 写一个错误页面, 路由调用失败或者代码出现bug, 会跳到错误页面去
10. 公共的静态页面能够写在assets里, 而后nuxt.config.js里引入
11. 发布线上时须要将.nuxt, assets, package.json, nuxt.config.js, static放到Nginx里进行代理
BUG
如何在组件中使用异步数据?
若是组件不是和路由绑定的页面组件,原则上是不可使用异步数据的。由于 Nuxt.js 仅仅扩展加强了页面组件的 data 方法,使得其能够支持异步数据处理。
对于非页面组件,有两种方式能够实现数据的异步获取:
在组件的 mounted 方法里面实现异步获取数据的逻辑,以后设置组件的数据,限制是:不支持服务端渲染。
在页面组件的asyncData或fetch方法中进行API调用,并将数据做为props传递给子组件。服务器渲染工做正常。缺点:asyncData或页面提取可能不太可读,由于它正在加载其余组件的数据。 总之,使用哪一种方法取决于你的应用是否须要支持子组件的服务端渲染。
为何 Nuxt.js 应用的页面会出现闪烁?
这是由于在开发模式下,为了经过 Webpack 实现热加载,CSS代码是打包在 JavaScript 代码中,并动态打到页面中去,从而元素重绘引发了闪烁。
不用担忧,在生产模式下,CSS代码会单独打包至独立的文件并置于head标签内,不会出现页面闪烁的现象。
如何编辑主机和端口配置?
做为命令参数直接传递
nuxt --hostname myhost --port 3333
或
"scripts": {
"dev": "nuxt --hostname myhost --port 3333"
}
在 nuxt.config.js 中配置:
在 nuxt.config.js 添加:
export default {
server: {
port: 8000, // default: 3000
host: '0.0.0.0', // default: localhost
},
// other configs
}
使用 NUXT_HOST 和 NUXT_PORT env 变量
与 HOST 和 PORT 相似,但更具体,以防您须要添加其余东西。
"scripts": {
"dev": "NUXT_HOST=0.0.0.0 NUXT_PORT=3333 nuxt"
}
注意: 为了更好的跨平台开发支持,您可使用 cross-env 依赖包。
安装依赖:
npm install --save-dev cross-env
配置cross-env:
"scripts": {
"dev": "cross-env NUXT_HOST=0.0.0.0 NUXT_PORT=3333 nuxt"
}
使用HOST和PORT env变量
"scripts": {
"dev": "HOST=0.0.0.0 PORT=3333 nuxt"
}
在 package.json 中配置 nuxt :
在您的 package.json 文件中添加:
"config": {
"nuxt": {
"host": "0.0.0.0",
"port": "3333"
}
},
"scripts": {
"dev": "nuxt"
}