原本想直接使用nuxt3的,但是跟着官网写了写发现还不完善,而且官网也说了nuxt3要到6月份才会发布生产版本,暂时还选用nuxt2。
Nuxt目录结构
assets 资源目录
该 assets 目录包含您未编译的资产,例如 Stylus 或 Sass 文件、图像或字体
在您的 vue 模板中,如果您需要链接到您的 assets 目录,请~/assets/your_image.png在资产前使用斜杠。
使用例子:
<template>
<img src="~/assets/your_image.png" />
</template>
background: url('~assets/banner.svg');
使用scss
yarn add --dev sass sass-loader@10
有报错:
this.getOptions is not a function
解决方法
sass-loader 版本太高和wabpack4 不兼容
yarn add sass-loader@10.1.1 -D
components 组件目录
该components目录包含您的 Vue.js 组件。组件构成了页面的不同部分,可以重复使用并导入到页面、布局甚至其他组件中。nuxt会默认导入,再vue中直接使用。
动态导入
要动态导入组件,也称为延迟加载组件,您只需Lazy在模板中添加前缀即可。
<template>
<div>
<TheHeader />
<Nuxt />
<LazyTheFooter />
</div>
</template>
使用惰性前缀,您还可以在触发事件时动态导入组件。
<template>
<div>
<h1>Mountains</h1>
<LazyMountainsList v-if="show" />
<button v-if="!show" @click="show = true">Show List</button>
</div>
</template>
<script>
export default {
data() {
return {
show: false
}
}
}
</script>
嵌套目录
如果您在嵌套目录中有组件,例如:
components/
base/
foo/
CustomButton.vue
组件名称将基于其自己的路径目录和文件名。因此,组件将是:
<BaseFooCustomButton />
layouts 布局目录
当您想要更改 Nuxt 应用程序的外观和感觉时,布局非常有用。无论您是想包含侧边栏还是为移动设备和桌面提供不同的布局。
默认布局
layouts/default.vue 您可以通过添加文件来扩展主布局 。它将用于所有没有指定布局的页面。确保 在创建布局时添加组件以实际包含页面组件。
您在布局中只需要三行代码即可呈现页面组件。
<template>
<Nuxt />
</template>
您可以在此处添加更多组件,例如导航、页眉、页脚等。
<template>
<div>
<TheHeader />
<Nuxt />
<TheFooter />
</div>
</template>
自定义布局
目录中的每个文件(顶级) layouts 都将创建一个自定义布局,该布局可通过 layout 页面组件中的属性访问。
假设我们要创建一个博客布局并将其保存到 layouts/blog.vue:
<template>
<div>
<div>My blog navigation bar here</div>
<Nuxt />
</div>
</template>
然后你必须告诉页面使用你的自定义布局
<script>
export default {
layout: 'blog',
// OR
layout (context) {
return 'blog'
}
}
</script>
错误页面 error.vue
错误页面是一个 页面组件 ,在发生错误时始终显示(不在服务器端抛出)。
虽然这个文件被放置在 layouts 文件夹中,但它应该被视为一个页面。
如上所述,此布局很特殊,您不应将其包含 在其模板中。您必须将此布局视为发生错误时显示的组件(404、 500等)。与其他页面组件类似,您也可以按照通常的方式为错误页面设置自定义布局。
您可以通过添加 layouts/error.vue 文件来自定义错误页面:
<template>
<div class="container">
<h1 v-if="error.statusCode === 404">Page not found</h1>
<h1 v-else>An error occurred</h1>
<NuxtLink to="/">Home page</NuxtLink>
</div>
</template>
<script>
export default {
props: ['error'],
layout: 'blog' // you can set a custom layout for the error page
}
</script>
页面目录 pages
该 pages 目录包含您的应用程序视图和路由。Nuxt 读取 .vue 此目录中的所有文件并自动为您创建路由器配置。
每个 Page 组件都是一个 Vue 组件,但 Nuxt 添加了特殊的属性和功能,以使您的通用应用程序的开发尽可能简单。
<template>
<h1 class="red">Hello {{ name }}!</h1>
</template>
<script>
export default {
// page properties go here
}
</script>
<style>
.red {
color: red;
}
</style>
动态页面
当您不知道页面名称时,可以创建动态页面,因为它来自 API,或者您不想一遍又一遍地创建相同的页面。要创建动态页面,如果您希望目录是动态的,则需要在 .vue 文件名或目录名称之前添加下划线。您可以为文件或目录命名任何您想要的名称,但您必须在其前面加上下划线。
如果您_slug.vue在 pages 文件夹中定义了一个名为的文件,则可以使用带有 params.slug 的上下文访问该值
<template>
<h1>{{ this.slug }}</h1>
</template>
<script>
export default {
async asyncData({ params }) {
const slug = params.slug // When calling /abc the slug will be "abc"
return { slug }
}
}
</script>
如果您在名为_slug.vue的文件夹中定义了一个名为的文件,_book则可以使用上下文访问该值params.slugparams.book
<template>
<h1>{{ this.book }} / {{ this.slug }}</h1>
</template>
<script>
export default {
async asyncData({ params }) {
const book = params.book
const slug = params.slug
return { book, slug }
}
}
</script>
asyncData 请求数据
每次加载组件之前都会调用 asyncData。它可以是异步的并接收上下文作为参数。返回的对象将与您的数据对象合并。
export default {
asyncData(context) {
return { name: 'World' }
}
}
fetch
每次需要获取异步数据时,都可以使用 fetch。渲染路由时在服务器端调用 Fetch,在导航时在客户端调用。
<script>
export default {
data() {
return {
posts: []
}
},
async fetch() {
this.posts = await fetch('https://api.nuxtjs.dev/posts').then(res =>
res.json()
)
}
}
</script>
head
为当前页面设置特定 标签。Nuxt 用于vue-meta更新应用程序的文档头和元属性。
export default {
head() {
title: 'Home page',
meta: [
{
hid: 'description',
name: 'description',
content: 'Home page description'
}
],
}
}
布局
指定布局目录中定义的布局。也就是说不使用默认布局
export default {
layout: 'blog'
}
加载
如果设置为 false,则防止页面在this.loading.finish() 您进入和 this.loading.start() 离开时自动调用,允许您手动控制行为,如 本示例 所示。
export default {
loading: false
}
过渡
定义页面的特定转换。
export default {
transition: 'fade'
}
滚动到顶部
该scrollToTop属性允许您告诉 Nuxt 在呈现页面之前滚动到顶部。默认情况下,当您转到另一个页面时,Nuxt 会滚动到顶部,但是对于子路由,Nuxt 会保持滚动位置。如果你想告诉 Nuxt 在渲染你的子路由时滚动到顶部,设置 scrollToTop 为 true
export default {
scrollToTop: true
}
中间件
定义此页面的中间件。在渲染页面之前将调用中间件。
export default {
middleware: 'auth'
}
plugins 插件目录
该 plugins 目录包含您要在实例化根 Vue.js 应用程序之前运行的 Javascript 插件。也就是我们之前写在main.js 中的使用第三方组件的 Vue.use
这是添加 Vue 插件和注入函数或常量的地方。每次需要使用 Vue.use()时,都应该在 in 中创建一个文件, plugins/ 并将其路径添加到 plugins in 中 nuxt.config.js。
使用npm 包 举例axios
首先安装
yarn add @nuxtjs/axios
例如,您可以配置 axios 拦截器以对跨应用程序的 API 调用可能出现的错误作出反应。在此示例中,当我们从 API 收到 500 状态错误时,我们将用户重定向到名为“抱歉”的自定义错误页面。
export default function ({ $axios, redirect }) {
$axios.onError(error => {
if (error.response.status === 500) {
redirect('/sorry')
}
})
}
最后但同样重要的是,将模块和新创建的插件添加到项目配置中。
module.exports = {
modules: ['@nuxtjs/axios'],
plugins: ['~/plugins/axios.js']
}
然后我们可以直接在你的页面组件中使用它:
<template>
<h1>{{ post.title }}</h1>
</template>
<script>
export default {
async asyncData ({ $axios, params }) {
const post = await $axios.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { post }
}
}
</script>
不安装模块的另一种使用方法是直接在标签中axios导入。axios
<script>
import axios from 'axios'
export default {
async asyncData ({ params }) {
const { data: post } = await axios.get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { post }
}
}
</script>
static 静态目录
该 static 目录直接映射到服务器根 () 并包含可能不会更改的文件。 所有包含的文件都将由 Nuxt 自动提供,并可通过您的项目根 URL 访问。
/static/robots.txt 将在http://localhost:3000/robots.txt
/static/favicon.ico 将在 http://localhost:3000/favicon.ico
此选项对 robots.txt, sitemap.xml 或 CNAME (这对于 GitHub Pages 部署很重要)之类的文件很有帮助。
\
如果您不想使用 assets 目录中的 Webpack 资产,可以将图像添加到静态目录。
然后,在您的代码中,您可以相对于根 ( /) 引用这些文件:
<!-- Static image from static directory -->
// static 用法
<img src="/my-image.png" />
<!-- webpacked image from assets directory -->
// assets 用法
<img src="~/assets/my-image-2.png" />
store vuex目录
该 store 目录包含您的 Vuex Store 文件。Vuex Store 自带 Nuxt,但默认禁用。在此目录中创建index.js 文件启用存储。
Nuxt 生命周期
nuxt 中可以使用的vue生命周期 只有 beformCreate created,记住nuxt中没用windos对象,无法操作dom元素。
@nuxt/axios 使用
安装
将@nuxtjs/axios依赖项添加到您的项目:
yarn add @nuxtjs/axios
然后将其添加到modules您的部分nuxt.config.js:
modules: ['@nuxtjs/axios']
配置
向您添加一个axios对象以nuxt.config.js配置将应用于所有请求的全局选项:
export default {
modules: [
'@nuxtjs/axios',
],
axios: {
// proxy: true
}
}
用法
asyncData
async asyncData({ $axios }) {
const ip = await $axios.$get('http://icanhazip.com')
return { ip }
}
$
Axios 插件还支持带有$前缀方法的快捷方式来直接获取数据:
// Normal usage with axios
let data = (await $axios.get('...')).data
// Fetch Style
let data = await $axios.$get('...')
环境变量
如果在生产环境中使用环境变量,则必须使用运行时配置,否则,这些值将在构建期间被硬编码并且不会改变。
支持的选项:
- baseURL
- browserBaseURL
export default {
modules: [
'@nuxtjs/axios'
],
axios: {
baseURL: 'http://localhost:4000', // Used as fallback if no runtime config is provided
},
publicRuntimeConfig: {
axios: {
browserBaseURL: process.env.BROWSER_BASE_URL
}
},
privateRuntimeConfig: {
axios: {
baseURL: process.env.BASE_URL
}
},
}
https
- 默认:false
如果设置为true,http://在两者中baseURL和browserBaseURL都会更改为https://.
retry
- 默认:false
使用axios-retry自动拦截失败的请求并在可能的时候重试它们。
默认情况下,重试次数将为3 次,如果retry值设置为true. 您可以通过传递带有内联重试子选项的选项来更改它,如下所示:
axios: {
retry: { retries: 3 }
}
代理 proxy
需要安装依赖
yarn add @nuxtjs/proxy
记得要添加到modules
{
modules: [
'@nuxtjs/axios'
],
axios: {
proxy: true // Can be also an object with default options
},
proxy: {
'/api/': 'http://api.example.com',
'/api2/': 'http://api.another-website.com'
}
}
注意: 不需要手动注册@nuxtjs/proxy模块,但它确实需要在您的依赖项中。
注意: 在代理模块中,/api/会将所有请求添加到 API 端点。如果您需要删除它,请使用以下 pathRewrite选项:
proxy: {
'/api/': { target: 'http://api.example.com', pathRewrite: {'^/api/': ''} }
}
示例代码
nuxt.config.js
<template>
<div>
新闻列表页面
<ul>
<li>
<nuxt-link :to="{ path: '/news/3223231' }">新闻1</nuxt-link>
</li>
</ul>
<br />
<div>
ssr 服务端渲染的数据
<ul>
<li v-for="item of dataList" :key="item.id" @click="gotoPage(item)">
<h1>{{ item.title }}</h1>
<p>{{ item.description }}</p>
<img :src="item.image" alt="" />
</li>
</ul>
</div>
<br />
<div>
客服端渲染的数据
<!-- <ul>
<li v-for="item of dataList" :key="item.id">
<h1>{{ item.title }}</h1>
<p>{{ item.description }}</p>
<img :src="item.image" alt="" />
</li>
</ul> -->
</div>
</div>
</template>
<script>
export default {
name: 'NewsPage',
async asyncData({ params, $axios }) {
const dataList = await $axios.$get(`https://api.nuxtjs.dev/posts`)
return { dataList }
},
data() {
return {
list: [],
}
},
mounted() {
this.$axios.$get('/api/posts').then((res) => {
this.list = res
})
},
methods: {
gotoPage(item) {
this.$router.push({
path: `/news/${item.id}`,
})
},
},
}
</script>
<style lang="scss"></style>
pages/news
<template>
<div>
新闻列表页面
<ul>
<li>
<nuxt-link :to="{ path: '/news/3223231' }">新闻1</nuxt-link>
</li>
</ul>
<br />
<div>
ssr 服务端渲染的数据
<ul>
<li v-for="item of dataList" :key="item.id" @click="gotoPage(item)">
<h1>{{ item.title }}</h1>
<p>{{ item.description }}</p>
<img :src="item.image" alt="" />
</li>
</ul>
</div>
<br />
<div>
客服端渲染的数据
<!-- <ul>
<li v-for="item of dataList" :key="item.id">
<h1>{{ item.title }}</h1>
<p>{{ item.description }}</p>
<img :src="item.image" alt="" />
</li>
</ul> -->
</div>
</div>
</template>
<script>
export default {
name: 'NewsPage',
async asyncData({ params, $axios }) {
const dataList = await $axios.$get(`https://api.nuxtjs.dev/posts`)
return { dataList }
},
data() {
return {
list: [],
}
},
mounted() {
this.$axios.$get('/api/posts').then((res) => {
this.list = res
})
},
methods: {
gotoPage(item) {
this.$router.push({
path: `/news/${item.id}`,
})
},
},
}
</script>
<style lang="scss"></style>
pages/news/_id.vue
<template>
<div>
新闻详情页面 {{ data.id }}
<h1>{{ data.title }}</h1>
<h2>{{ data.description }}</h2>
<h3>height:{{ data.height }}</h3>
<img :src="data.image" alt="" />
</div>
</template>
<script>
export default {
name: 'DetailPage',
async asyncData({ params, $axios }) {
const data = await $axios.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { data }
},
}
</script>
<style lang="scss"></style>