零基础上手nuxt
最近抽空看了一下nuxt觉着挺有意思,于是打算写一篇文章总结,顺便说一些遇到的一些问题
官方介绍
- Nuxt.js 是一个基于 Vue.js 的通用应用框架。 通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI渲染。它的优点如下:
- 基于 Vue.js
- 自动代码分层
- 服务端渲染
- 强大的路由功能,支持异步数据
- 静态文件服务
- ES6/ES7 语法支持
- 打包和压缩 JS 和 CSS
- HTML头部标签管理
- 本地开发支持热加载
- 集成ESLint
- 支持各种样式预处理器: SASS、LESS、 Stylus等等
安装
- 如果没安装vue-cli,先安装cli
npm install vue-cli -g
- 初始化项目
vue init nuxt/starter
- 安装依赖
npm install
- 启动服务
npm run dev
目录结构
- 直接看结构
|-- .nuxt // Nuxt自动生成,临时的用于编辑的文件,build
|-- assets // 用于组织未编译的静态资源入LESS、SASS 或 JavaScript
|-- components // 用于自己编写的Vue组件,比如滚动组件,日历组件,分页组件
|-- layouts // 布局目录,用于组织应用的布局组件,不可更改。
|-- middleware // 用于存放中间件
|-- pages // 用于存放写的页面,我们主要的工作区域
|-- plugins // 用于存放JavaScript插件的地方
|-- static // 用于存放静态资源文件,比如图片
|-- store // 用于组织应用的Vuex 状态管理。
|-- .editorconfig // 开发工具格式配置
|-- .eslintrc.js // ESLint的配置文件,用于检查代码格式
|-- .gitignore // 配置git不上传的文件
|-- nuxt.config.json // 用于组织Nuxt.js应用的个性化配置,已覆盖默认配置
|-- package-lock.json // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作
|-- package-lock.json // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作
|-- package.json // npm包管理配置文件
常用配置
配置IP和端口
- 只需在 /package.json 中,配置完成后
npm run dev
重启项目。
"config":{
"nuxt":{
"host":"127.0.0.1",
"port":"1818"
}
},
配置全局CSS
- 全局css几乎每个项目都需要初始化,这时候我们可以先在
assets
文件夹中新建一个css文件夹,放入初始化css的文件,例如base.css
。然后打开nuxt.config.js
,配置一下:
css:['~assets/css/base.css'],
配置webpack的loader
- 在nuxt.config.js里是可以对webpack的基本配置进行覆盖的,比如现在我们要配置一个url-loader来进行小图片的64位打包。就可以在nuxt.config.js的build选项里进行配置。
build: {
//多个就是loaders
loader:[
{
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路由
简单路由
- 在
pages
中新建news.vue
和about.vue
,并且写入以下模版:
//news.vue
<template>
<div>
<h2>News page</h2>
<ul>
<li><a href="/">Home</a></li>
</ul>
</div>
</template>
//about
<template>
<div>
<h2>about page</h2>
<ul>
<li><a href="/">Home</a></li>
</ul>
</div>
</template>
- 在
index.vue
中加入a
标签
<li><a href="/about">ABOUT</a></li>
<li><a href="/news">NEWS</a></li>
- 这时候可以发现这样写也没啥问题,但
nuxt
不提倡使用这种方式进行转跳,它也为我们提供了<nuxt-link>
标签。
nuxt-link标签使用
- 我们把之前的
a
标签替换成<nuxt-link>
标签:
<nuxt-link :to="{name:'about'}">about</nuxt-link>
<nuxt-link :to="{name:'news'}">NEWS</nuxt-link>
- 也可以进行转跳,
nuxt.js
推荐我们使用<nuxt-link>
进行页面之间的跳转。
参数传递
- 在项目中经常会用到路由传参,在nuxt中我们可以使用
params
进行参数传递。直接看代码: - 在index.vue中给news加参数,传递一个newsId
<nuxt-link :to="{name:'news',params:{newsId:1234}}">NEWS</nuxt-link>
- 然后在news.vue中通过
$route.params
接收一下参数:
<li>传递过来的id为:{{$route.params.newsId}}</li>
动态路由
- 首先,先整理一下之前
pages
下的目录结构,我们新建立一个news
文件夹,然后把之前创建的news.vue
移入进去,改名字为index.vue
,接着在这个文件夹中建立_id.vue
文件,并且编辑模版如下:
<template>
<div>
<h2>新闻详情页面id为:[{{$route.params.id}}]</h2>
<ul>
<li><a href="/">Home</a></li>
</ul>
</div>
</template>
- 在
news
文件夹下的index.vue
中加入转跳:
<li><a href="/news/123">新闻1</a></li>
<li><a href="/news/456">新闻2</a></li>
- 这样动态路由就好了,在Nuxt.js里面定义带参数的动态路由,需要创建对应的以
下划线
作为前缀的 Vue文件或目录。
路由参数校验
- 进入一个页面,对参数传递的正确性校验是必须的,可以使用nuxt为我们提供的校验方法
validate()
。在上面创建的_id.vue
加入校眼:
export default {
validate ({ params }) {
// Must be a number
return /^d+$/.test(params.id)
}
}
- 我们使用了validate方法,并把params传递进去,然后用正则进行了校验,如果正则返回了true正常进入页面,如果返回false进入404页面。这里如果我们参数传递一个中文进去,就会进入到404页面。
错误页面配置
- 我们可以在
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>
- 接着在
news
文件夹下的index.vue
中加入一个错误转跳:
<li><a href="/news/你好">错误转跳</a></li>
- 这时候点击过去,就会跳转到错误页面。
过渡动画
- 路由的动画效果,也叫作页面的更换效果。Nuxt.js提供两种方法为路由提供动画效果,一种是全局的,一种是针对单独页面制作。
全局路由动画
- 我们在
/assets/css
文件夹中创建main.css
,加入以下css:
.page-enter-active, .page-leave-active {
transition: opacity 1s;
}
.page-enter, .page-leave-active {
opacity: 0;
}
- 然后在
nuxt.config.js
中加入全局css:
css:['~assets/css/base.css','~assets/css/main.css'],
- 这时候页面转跳就会有了1秒的过渡动画,但我们进入
about
页面中,点击返回却发现没有这个效果,因为返回home我们是用的a
标签进行转跳的,这时候我们可以改成<nuxt-link>
转跳:
<nuxt-link :to="{name:'index'}">返回首页</nuxt-link>
- 同样,之前的转跳到新闻详情页面也可以改一下:
<li><nuxt-link :to="{name:'news-id',params:{id:123}}">新闻1</nuxt-link></li>
<li><nuxt-link :to="{name:'news-id',params:{id:123}}">新闻2</nuxt-link></li>
局部动画
- 如果想加个字体先放大后缩小的效果,在之前的
main.css
文件中加入:
.test-enter-active, .test-leave-active {
transition: all 2s;
font-size:12px;
}
.test-enter, .test-leave-active {
opacity: 0;
font-size:40px;
}
- 然后在
about.vue
中设置:
export default {
transition:'test'
}
- 这时候就是单个页面有动画效果了,更多请看官网api:transition API
默认模版和默认布局
- 平时开发时候,有很多公共元素,我们可以把它做成组件,或者就是修改模版,nuxt中也提供了模版修改。
默认模版
- 直接在根目录下创建
app.html
,然后编辑一下:
<!DOCTYPE html>
<html lang="en">
<head>
{{HEAD}}
</head>
<body>
<h1 style="text-align: center;">默认模版就是这样</h6>
{{APP}}
</body>
</html>
- 其中
HEAD
就是nuxt.config.js
中配置的head
信息,必须大写,APP
就是/pages/
下的主体文件。 - 重新启动服务才可以生效。
默认布局
- 默认布局与默认模版类似,默认布局主要针对于页面的统一布局使用,在
layouts/default.vue
中可以进行修改,比如,我们加点东西看一下:
<template>
<div>
<p>LonJin</p>
<nuxt/>
</div>
</template>
- 再看一下其他页面,页面中出现了我们输入的内容。
个性meta设置
- 很多时候,网站某些meta并不少统一的,比如新闻页面,可能需要单独设置一下方便搜索引擎抓取。拿新闻页面举例子,打开之前的新闻列表页面,参数再多加一个
title
<li><nuxt-link :to="{name:'news-id',params:{id:123,title:'这是一篇新闻'}}">新闻2</nuxt-link></li>
- 然后在
/pages/news/_id.vue
中接收一下:
data(){
return{
title:this.$route.params.title,
}
},
//独立设置head信息
head(){
return{
title:this.title,
meta:[
{hid:'description',name:'news',content:'This is news page'}
]
}
}
asyncData获取数据
- 首先安装
axios
和proxy
:
npm install axios --save
npm i @nuxtjs/proxy -D
- 然后在
/nuxt.config.js
中配一下接口代理,因为我使用的是https://api.binstd.com/
这个网站的api,所以要进行接口代理。
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
axios: {
proxy: true,
prefix: '/api', // it only work when proxy is enabled
credentials: true,
},
proxy: {
'/api': {
target: 'https://api.binstd.com',
changeOrigin : true,
secure: true,
pathRewrite: {
'^/api' : ''
}
}
},
- 然后在
/pages/news/index.vue
里面测试一下接口:
import axios from 'axios'
export default {
data(){
return{
}
},
async asyncData () {
let { data } = await axios.get('/api/recipe/class?appkey=xxx')
console.log(data)
return { info: data }
},
}
- 然后送首页进入到这页面,没有什么问题,数据正常拿到
- 但是再刷新一下,就会报错:
connect ECONNREFUSED 127.0.0.1:80 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1113:14)
- 我发现如果页面没有使用async asyncData方法去请求后台地址刷新页面就没问题,如果使用了该方法去请求后台刷新页面就报上面的异常,看了网上一些回答,我一直怀疑我的代理配置的有问题,还有说请求接口的时候让
域名+端口+api
进行访问。但我进行了代理,讲道理不应该出现这种问题。 - 最后我是通过配置
package.json
中config
解决的。
"config": {
"nuxt": {
"host": "0.0.0.0",
"port": "80"
}
}
静态资源
- 静态资源引用需要注意要使用
~
符号,这个符号代表根目录,在css中引入同理
<div><img src="~static/lonjin.png" /></div>
.box{
width: 300px;
height: 100px;
background-image: url('~static/lonjin.png')
}
打包上线
- 只需输入一行命令即可:
npm run generate
总结
总体来说,
nuxt
还是很不错的,但是文档感觉不怎么样,在处理跨域时候遇到的第二次刷新页面返回的报错,查了半天资料,一直以为是配置的代理有问题导致的,后来才发现是修改package.json
中config
。本人也是尝试的看了一下nuxt,并没有太过深入的应用过nuxt.js
,如果不对,欢迎指正!