nuxt.js简单的说是Vue.js的通用框架,最经常使用的就是用来做SSR(服务器端渲染).Vue.js是开发SPA(单页应用)的,Nuxt.js这个框架,用Vue开发多页应用,并在服务端完成渲染,能够直接用命令把咱们制做的vue项目生成为静态html。javascript
主要的缘由时SPA(单页应用)不利于搜索引擎的SEO操做,Nuxt.js适合做新闻、博客、电影、咨询这样的须要搜索引擎提供流量的项目。若是你要做移动端的项目,就不必使用这个框架了。css
在认识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
虽然给服务器减轻了压力,可是也是有缺点的:java
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
推送在使用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,能够看到结果,以下:
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 // 只渲染当前页面 复制代码
一个完整的服务器请求到渲染的流程
经过上面的流程图能够看出,当一个客户端请求进入的时候,服务端有经过nuxtServerInit
这个命令执行在Store
的action
中,在这里接收到客户端请求的时候,能够将一些客户端信息存储到Store
中,也就是说能够把在服务端存储的一些客户端的一些登陆信息存储到Store
中。以后使用了中间件
机制,中间件其实就是一个函数,会在每一个路由执行以前去执行,在这里能够作不少事情,或者说能够理解为是路由器的拦截器的做用。而后再validate
执行的时候对客户端携带的参数进行校验,在asyncData
与fetch
进入正式的渲染周期,asyncData
向服务端获取数据,把请求到的数据合并到Vue
中的data
中,
└─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自定义配置 } } } 复制代码
{ "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" } } 复制代码
开发中常常会遇到端口被占用或者指定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.
在开发多页项目时,都会定义一个全局的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 。而后你会发现字体已经变成了红色。
在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)/
})
}
}
}
复制代码
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.js的路由并不复杂,它给咱们进行了封装,让咱们节省了不少配置环节。
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' } ] } 复制代码
<nuxt-link to="/users"></nuxt-link>
路由常常须要传递参数,咱们能够简单的使用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来指定页面。 复制代码
this.$route.query.key的方式参数显示在地址栏上, 可是并非咱们想要的, :id?id=``?
因此建议仍是尽可能使用router-link来实现跳转来解决地址栏的变化,更方便网站的优化
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) } } 复制代码
路由的动画效果,也叫做页面的更换效果。Nuxt.js提供两种方法为路由提供动画效果,一种是全局的,一种是针对单独页面制做。
全局动画默认使用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秒钟的动画切换效果了,可是你会发现一些页面是没有效果的,这是由于你没有是<nuxt-link>
组件来制做跳转连接。你须要进行更改。
好比咱们上节课做的动态路由新闻页,你就须要改为下面的连接。
<li><nuxt-link :to="{name:'news-id',params:{id:123}}">News-1</nuxt-link></li> 复制代码
改过以后你就会看到动画效果了。
想给一个页面单独设置特殊的效果时,咱们只要在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为咱们提供了超简单的默认模版订制方法,只要在根目录下建立一个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都须要大写,若是小写会报错的。
注意:若是你创建了默认模板后,记得要重启服务器,不然显示不会成功;可是默认布局是不用重启服务器的。
默认模板相似的功能还有默认布局,可是从名字上你就能够看出来,默认布局主要针对于页面的统一布局使用。它在位置根目录下的layouts/default.vue。须要注意的是在默认布局里不要加入头部信息,只是关于<template>
标签下的内容统一订制。
需求:咱们在每一个页面的最顶部放入“学习nuxt.js” 这几个字,看一下在默认布局里的实现。
<template> <div> <p>学习nuxt.js</p> <nuxt/> </div> </template> 复制代码
这里的<nuxt/>
就至关于咱们每一个页面的内容,你也能够把一些通用样式放入这个默认布局里,但会增长页面的复杂程度。
总结:要区分默认模版和默认布局的区别,模版能够订制不少头部信息,包括IE版本的判断;模版只能定制<template>
里的内容,跟布局有关系。在工做中修改时要看状况来编写代码。
下载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']
}
复制代码
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}) }) } 复制代码
module.exports = {
build: {
vendor: ['axios']
}
}
复制代码
当用户输入路由错误的时候,咱们须要给他一个明确的指引,因此说在应用程序开发中404页面是必不可少的。Nuxt.js支持直接在默认布局文件夹里创建错误页面。
在根目录下的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>
的简单写法直接跟上路径就能够了。
页面的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标签配一个惟一的标识编号。
Nuxt.js贴心的为咱们扩展了Vue.js的方法,增长了anyncData,异步请求数据。
(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
复制代码
咱们在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出去获取到的对象,这样就能够在组件中使用,这里返回的数据会和组件中的data合并。这个函数不光在服务端会执行,在客户端一样也会执行。 复制代码
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 } }, 复制代码
固然上面的方法稍显过期,如今都在用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> 复制代码
this
来引用组件的实例对象(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 下是彻底正常的。
用Nuxt.js制做完成后,你能够打包成静态文件并放在服务器上,进行运行。
在终端中输入:
npm run generate
复制代码
而后在dist文件夹下输入live-server就能够了。
总结:Nuxt.js框架很是简单,由于大部分的事情他都为咱们作好了,咱们只要安装它的规则来编写代码。
安装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 => {}) } 复制代码
缘由: asyncData方法异步请求数据时,觉得/api/${params.id}这个接口的网址是 127.0.0.1:80, 因此将请求发送给了127.0.0.1:80,而个人接口服务器并无跑在80端口上,因此报错。
解决方法:
export default { asyncData ({ params }) { return axios.get(`https://127.0.0.1:3000/api/${params.id}`) .then((res) => { return { title: res.data.title } }) } } 复制代码
背景: 在
<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'] } 复制代码
背景:在组件中的
<template>
,<script>
或<style>
上使用各类预处理器,加上处理器后,控制台报错。
npm install --save-dev node-sass sass-loader
复制代码
可是解决过程并非很顺利的,在阅读中文文档时,忽略版本号,按照上面的提示进行操做,发现不能成功,后来各类debug,最后发现了该解决方案。后知后觉的发现了中文文档的版本号太低,若是须要查看文档,必定要看最新版本的英文文档!
背景:在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 // 转换基本单位 }) ] }, 复制代码
背景:给 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') }) } } 复制代码
背景:本身封装了一个 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) 复制代码
背景:在项目中,设置 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
}
复制代码
背景: 在引入第三方插件,或者直接在代码中写
window
时,控制台会给出警告,window
未定义。
发生在这个问题的缘由时,node服务端并无window
或 document
对象。解决方法,经过 process.browser
来区分环境。
if (process.browser) { // 引入第三方插件 require('***') // 或者修改window对象下某一属性 window.mbk = {} } 复制代码
例如使用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)/ }) } } } 复制代码
此时,咱们在观察打包之后文件体积大小,如图:
此时,咱们成功完成了按需引入配置。
(1) <no-ssr> 插件或者组件 </no-ssr> (2) nuxt.config.js里ssr改成false plugins: [ {src: '~/plugins/ElementUI', ssr: false } ], 复制代码
解决: 可使用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是没有index.html页面的, 我们应该在哪里写js代码来判断设备呢, 下面请看个人代码吧
nuxt.config.js
里经过router
来引入middleware
中间件nuxt.config.js
代码以下
export default { router: { middleware: ["device"], }, } 复制代码
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", }; } } 复制代码
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 } } 复制代码
asyncData
方法会在组件(限于页面组件)每次会在刷新加载页面或者切换路由时被调用,顺序比beforeCreate和created以前访问域名
, 能够经过axios配置axios.defaults.baseURL
.nuxt
, assets
, package.json
, nuxt.config.js
, static
放到Nginx里进行代理若是组件不是和路由绑定的页面组件,原则上是不可使用异步数据的。由于 Nuxt.js 仅仅扩展加强了页面组件的 data
方法,使得其能够支持异步数据处理。
对于非页面组件,有两种方式能够实现数据的异步获取:
mounted
方法里面实现异步获取数据的逻辑,以后设置组件的数据,限制是:不支持服务端渲染。asyncData
或fetch
方法中进行API调用,并将数据做为props
传递给子组件。服务器渲染工做正常。缺点:asyncData
或页面提取可能不太可读,由于它正在加载其余组件的数据。 总之,使用哪一种方法取决于你的应用是否须要支持子组件的服务端渲染。这是由于在开发模式下,为了经过 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" } 复制代码