Nuxt.js 是一个基于 Vue.js 的通用应用框架,特别适用于需要服务端渲染的应用场景。本文将简要介绍 Nuxt.js 的安装步骤、常用配置项、路由配置、错误处理、插件使用、打包和一些额外的注意事项,帮助初学者快速上手。
一、Nuxt.js 简介及安装
Nuxt.js 是一个基于 Vue.js 的通用应用框架。通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI 渲染。目标是创建一个灵活的应用框架,你可以基于它初始化新项目的基础结构代码,或者在已有 Node.js 项目中使用 Nuxt.js,Nuxt.js 预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置。
作为框架,Nuxt.js 为 客户端/服务端
这种典型的应用架构模式提供了许多有用的特性,例如异步数据加载、中间件支持、布局支持等。
二、Nuxt.js 安装
一、安装
// 全局安装npx
npm install npx -g// 使用npx创建nuxt项目
npx create-nuxt-app 项目名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 // 只渲染当前页面
二、项目结构介绍
└─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
三、Nuxt.js 配置文件 nuxt.config.js
注意:
export default
在一个模块中只能有一个,当然也可以没有。export
在一个模块中可以有多个。export default
的对象、变量、函数、类,可以没有名字。export
的必须有名字。export default
对应的import
和export
有所区别。module
变量代表当前模块。这个变量是一个对象,module
对象会创建一个叫exports
的属性,这个属性的默认值是一个空的对象。
Node 为每个模块提供一个 exports
变量,指向 module.exports
,两个是相等的关系,但又不是绝对相当的关系,module.exports
可以直接导出一个匿名函数或者一个值,但是 export
的必须有名字,故不行,export default
或 export 名字
可以
const pkg = require('./package')
module.exports = {mode: 'universal', // 当前渲染使用模式,分为universal和spa,既然是nuxt开发,那就是universal// 全局页头配置 (https://go.nuxtjs.dev/config-head)head: { // 页面head配置信息title: pkg.name, // titlemeta: [ // meat{ charset: 'utf-8' },{ name: 'viewport', content: 'width=device-width, initial-scale=1' },{ hid: 'description', name: 'description', content: pkg.description }// 这里可以添加网站验证码信息// { name: 'google-site-verification', content: 'xxx' },// 实测百度无法通过验证,此问题还没解决// { name: 'baidu-site-verification', content: 'code-xxx' },],link: [ // favicon,若引用css不会进行打包处理{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]},// nuxt 加载进度条配置 (https://zh.nuxtjs.org/api/configuration-loading)loading: { color: '#fff' }, // 页面进度条// 全局css (https://go.nuxtjs.dev/config-css)css: [ // 全局css(会进行webpack打包处理)'element-ui/lib/theme-chalk/index.css' ],// 配置后,会在页面渲染之前加载 (https://go.nuxtjs.dev/config-plugins)plugins: [ // 插件'@/plugins/element-ui'],// 工具module (https://go.nuxtjs.dev/config-modules)modules: [ // 模块'@nuxtjs/axios',],// 如果添加了@nuxt/axios则会需要此配置来覆盖默认的一些配置 (https://go.nuxtjs.dev/config-axios)axios: {https: true, progress: true, // 是否显示加载进度条credentials: true, // 请求携带cookiebaseURL: 'https://www.abeille.top/api',proxy: true // 请求代理,开发中跨域问题解决方法},// 打包配置 (https://go.nuxtjs.dev/config-build)build: { // 打包transpile: [/^element-ui/],extend(config, ctx) { // webpack自定义配置}}
}
四、ofetch
介绍和与 Axios 的比较
1. ofetch
介绍
ofetch
是一个轻量级且高性能的 HTTP 客户端库,适用于多种前端框架,包括 Vue.js 和 Nuxt.js。它提供了简洁的 API,易于使用,并且支持 TypeScript,能够提供更好的类型支持和代码提示。ofetch
的设计目标是提供一个简单且强大的 HTTP 请求工具,同时保持较小的体积和较高的性能。
主要特点
-
简洁的 API:
import { ofetch } from 'ofetch'const response = await ofetch('https://api.example.com/data') console.log(response)
-
支持 TypeScript:
import type { FetchOptions } from 'ofetch' import { ofetch } from 'ofetch'const fetchData = async (options: FetchOptions) => {const response = await ofetch(options.url, options)return response }
-
内置拦截器:
import { ofetch, setup } from 'ofetch'setup({onRequest({ options }) {console.log('Making request to ' + options.url)},onResponse({ response }) {console.log('Received response from ' + response.url)},onError({ error }) {console.error('Request failed with error:', error)} })const response = await ofetch('https://api.example.com/data') console.log(response)
-
支持多种请求方法:
import { ofetch } from 'ofetch'const getResponse = await ofetch.get('https://api.example.com/data') const postResponse = await ofetch.post('https://api.example.com/data', { key: 'value' }) console.log(getResponse, postResponse)
-
自动处理 JSON:
import { ofetch } from 'ofetch'const response = await ofetch('https://api.example.com/data') console.log(response) // 自动解析 JSON
2. Axios 介绍
axios
是一个基于 Promise 的 HTTP 客户端库,可以在浏览器和 Node.js 中使用。它非常流行,并且提供了丰富的功能,如拦截请求和响应、取消请求、自动转换 JSON 数据等。
主要特点
-
基于 Promise:
import axios from 'axios'axios.get('https://api.example.com/data').then(response => {console.log(response.data)}).catch(error => {console.error(error)})
-
支持 TypeScript:
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'const fetchData = async (config: AxiosRequestConfig): Promise<AxiosResponse<any>> => {const response = await axios(config)return response }
-
内置拦截器:
import axios from 'axios'axios.interceptors.request.use(config => {console.log('Making request to ' + config.url)return config }, error => {return Promise.reject(error) })axios.interceptors.response.use(response => {console.log('Received response from ' + response.config.url)return response }, error => {return Promise.reject(error) })
-
支持多种请求方法:
import axios from 'axios'axios.get('https://api.example.com/data') axios.post('https://api.example.com/data', { key: 'value' })
-
自动转换 JSON:
import axios from 'axios'axios.get('https://api.example.com/data').then(response => {console.log(response.data) // 自动解析 JSON}).catch(error => {console.error(error)})
3. ofetch
与 Axios 的比较
特性 | ofetch | axios |
---|---|---|
体积 | 较小,适合对性能要求较高的项目 | 较大,功能更全面 |
API 设计 | 更简洁,支持多种请求方法的直接使用 | 基于 Promise,功能分散 |
拦截器 | 简单的全局配置 | 强大的请求和响应拦截器 |
自动转换 JSON | 支持 | 支持 |
TypeScript 支持 | 提供了很好的类型支持,便于类型推断 | 提供了很好的类型支持,但相对 ofetch 更复杂 |
4. 如何选择
选择 ofetch
还是 axios
取决于项目的具体需求、团队的技术栈以及对功能和性能的要求。以下是选择的建议:
-
小型项目或对性能要求较高的项目:推荐使用
ofetch
,由于其体积较小且 API 设计简洁,可以提高项目的加载速度和开发效率。 -
大型项目或需要更多高级功能的项目:推荐使用
axios
,其功能较为全面,适用于需要更多高级功能的场景,如取消请求、请求配置更灵活等。
五、ofetch
的使用示例
结合项目中的 http.ts
文件,展示如何在 Nuxt3 项目中使用 ofetch
:
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus'
import type { FetchOptions } from 'ofetch'
import { ofetch } from 'ofetch'
import { LoadingInstance } from 'element-plus/lib/components/loading/src/loading'
import debounce from "lodash/debounce"
import { callWithNuxt } from '#app'
import cloneDeep from "lodash/cloneDeep"import { useStore } from '@/composables/piniaStore'
import { storeToRefs } from 'pinia'
import { SystemUser } from '~~/types'const store = useStore()
const { userInfo } = storeToRefs(store)
let loadingInstance: LoadingInstance | null = nullconst showLoading = debounce(() => {loadingInstance = ElLoading.service({lock: true,text: 'Loading',background: 'rgba(0, 0, 0, 0.7)'})
}, 500)const hideLoading = () => {if (loadingInstance) {loadingInstance.close()}
}export const http = ofetch.create({baseURL: process.env.API_URL || 'https://www.abeille.top/api',onRequest: ({ options }) => {showLoading()},onResponse: ({ response }) => {hideLoading()},onError: ({ error }) => {hideLoading()ElMessage.error('Request failed: ' + error.message)},onResponseError: ({ response }) => {hideLoading()ElMessage.error('Response error: ' + response.status)}
})
六、Nuxt.js 的常用配置
一、配置 IP 和端口
第一种 nuxt.config.js
:
module.exports = {server: {port: 8000,host: '127.0.0.1'}
}
第二种 package.json
:
"config": {"nuxt": {"port": "8000","host": "127.0.0.1"}
},
二、配置全局 CSS
在开发多页项目时,都会定义一个全局的 CSS 来初始化我们的页面渲染,比如把 padding 和 margin 设置成 0,网上也有非常出名的开源 CSS 文件 normalize.css
。要定义这些配置,需要在 nuxt.config.js
里进行操作。
比如现在我们要把页面字体设置为红色,就可以在 assets/css/common.css
文件,然后把字体设置为红色。
/assets/css/common.css
html{color:red;
}
body {margin:0;padding:0
}
/nuxt.config.js
css:['~assets/css/normalize.css'],
设置好后,在终端输入 npm run dev
。然后你会发现字体已经变成了红色。
七、Nuxt.js 的路由配置和参数传递
一、基本路由
Nuxt.js 的路由并不复杂,它给我们进行了封装,让我们节省了很多配置环节。
Nuxt 会自动生成路由,故而只需使用 <nuxt-link :to=""> </nuxt-link>
,而非 <router-link :to=""> </router-link>
页面跳转方式:
- 不要写成 a 标签,因为是重新获取一个新的页面,并不是 SPA
<nuxt-link to="/users"></nuxt-link>
this.$router.push('/users')
动态路由:
- 在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录。
- 获取动态参数
{{ $route.params.id }}
二、路由传参
this.$route.query.key
的方式参数显示在地址栏上, 但是并不是我们想要的, :id?id=``?
所以建议还是尽量使用 router-link
来实现跳转来解决地址栏的变化, 更方便网站的优化
1. nuxt-link
中传递参数
方式一
传参:
<nuxt-link :to="{ path: '/about', query: { index: id } }" target="_blank"></nuxt-link>
地址栏显示:
localhost:3000/about?id=123
接收地址栏参数:
this.$route.query.index方式二
传参:
<nuxt-link target="_blank" :to="{ name: 'log-id', params: { id: n.id, key: value }}"></nuxt-link>
地址栏显示:
localhost:3000/about/123
接收:
async asyncData ({ params }) { // params.id 就是我们传进来的值}
// 或者 created () { this.$route.params.id}
2. 在方法中传递
方式一
跳转:
getDescribe(id) {// 直接调用 $router.push 实现携带参数的跳转this.$router.push({path: `/describe/${id}`,})
}
接收:
$route.params.id方式 二
注意:
页面之间的跳转使用 query 不然的话刷新页面后会找不到参数
跳转:this.$router.push({path: '/describe',query: {id: id}
})
接收:
$route.query.id
三、路由传参校验
Nuxt.js 可以让你在动态路由对应的页面组件中配置一个 validate
方法用于校验动态路由参数的有效性。该函数有一个布尔类型的返回值,如果返回 true
则表示校验通过,如果返回 false
则表示校验未通过。
export default {// nuxt 中使用 validate 方法进行路由参数校验,这个方法必须返回一个布尔值,为 true 表示校验通过,为 false 表示校验失败。注意 validate 不能写到 methods 属性中。validate(obj) {// console.log(obj);// return truereturn /^\d+$/.test(obj.params.id)}
}
四、路由嵌套
注意:
在 Nuxt 框架中,在 nuxt.config.js
中 components: true
已开启了组件自动导入,故而不需要在 Vue 文件中通过 import
和 components
来导入组件,只需在 template
中写入相应组件的组件名即可
- 添加一个 Vue 文件,作为父组件
- 添加一个与父组件同名的文件夹来存放子视图组件
- 在父文件中,添加组件,用于展示匹配到的子视图
五、Nuxt.js 的路由动画效果
路由的动画效果,也叫作页面的更换效果。Nuxt.js 提供两种方法为路由提供动画效果,一种是全局的,一种是针对单独页面制作。
1. 全局路由动画
全局动画默认使用 page
进行设置,例如现在我们为每个页面都设置一个进入和退出时的渐隐渐现的效果。我们可以先在根目录的 assets/css
下建立一个 normalize.css
文件。
(1)添加样式文件
/assets/css/normalize.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/normalize.css'],
这时候在页面切换的时候就会有 2 秒钟的动画切换效果了,但是你会发现一些页面是没有效果的,这是因为你没有使用 <nuxt-link>
组件来制作跳转链接。你需要进行更改。
<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.js 的默认模板和默认布局
在开发应用时,经常会用到一些公用的元素,比如网页的标题是一样的,每个页面都是一模一样的标题。这时候我们有两种方法,第一种方法是作一个公用的组件出来,第二种方法是修改默认模板。这两种方法各有利弊,比如公用组件更加灵活,但是每次都需要自己手动引入;模板比较方便,但是只能每个页面都引入。
1. 默认模板
Nuxt.js 为我们提供了超简单的默认模板订制方法,只要在根目录下创建一个 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
。需要注意的是在默认布局里不要加入头部信息,只是关于 <template>
标签下的内容统一订制。
需求:我们在每个页面的最顶部放入“学习 Nuxt.js” 这几个字,看一下在默认布局里的实现。
<template><div><p>学习 Nuxt.js</p><nuxt/></div>
</template>
这里的 <nuxt/>
就相当于我们每个页面的内容,你也可以把一些通用样式放入这个默认布局里,但会增加页面的复杂程度。
总结:要区分默认模板和默认布局的区别,模板可以订制很多头部信息,包括 IE 版本的判断;模板只能定制 <template>
里的内容,跟布局有关系。在工作中修改时要看情况来编写代码。
九、Nuxt.js 插件的使用
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. Element 按需引入
第一步,下载依赖:
# 先下载element-ui
npm install element-ui --save# 如果使用按需引入,必须安装 babel-plugin-component
npm install babel-plugin-component --save-dev
在 文件根目录 创建 (或已经存在) 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"}]]},extend(config, ctx) {if (ctx.isClient) {config.module.rules.push({enforce: 'pre',test: /\.(js|vue)$/,loader: 'eslint-loader',exclude: /(node_modules)/})}}
}
3. 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']} }
4. Vuex 的使用
Nuxt.js 内置引用了 vuex
模块,所以不需要额外安装。
Nuxt.js 会找到应用根目录下的 store
目录,如果该目录存在,它将做以下的事情:
- 引用
vuex
模块 - 将
vuex
模块 加到 vendors 构建配置中去 - 设置
Vue
根实例的store
配置项
Nuxt.js 支持两种使用 store
的方式,你可以择一使用:
- 模块方式:
store
目录下的每个.js
文件会被转换成为状态树指定命名的子模块 (当然,index
是根模块) - 普通方式:
store/index.js
返回一个 Vuex.Store 实例(官方不推荐)
模块方式
状态树还可以拆分成为模块,store
目录下的每个 .js
文件会被转换成为状态树指定命名的子模块
使用状态树模块化的方式,store/index.js
不需要返回 Vuex.Store 实例,而应该直接将 state
、mutations
和 actions
暴露出来:
index.js
export const state = () => ({articleTitle: [],labelList: []
})export const mutations = {// 设置热门文章标题updateArticleTitle(state, action) {state.articleTitle = action},// 设置标签列表数据updateLabel(state, action){state.labelList = action}
}export const actions = {// 获取热门文章标题fetchArticleTitle({ commit }) {return this.$axios.$get('http://localhost:3000/article/title').then(response => {commit('updateArticleTitle', response.data)})},// 获取标签fetchLabel({ commit }) {return this.$axios.$get('http://localhost:3000/label/list').then(response => {commit('updateLabel', response.data)})},
}
index.vue
fetch
方法中触发异步提交状态事件
<script>
import ArticleList from '~/components/archive/list'
import Banner from '~/components/archive/banner'export default {components: {ArticleList,Banner,},async asyncData({ app }){// 获取文章列表数据let article = await app.$axios.get(`http://localhost:3000/article/list?pageNum=1&pageSize=5`)return { articleList: article.data.data }},async fetch({ store }) {return Promise.all([store.dispatch('common/fetchArticleTitle'),store.dispatch('common/fetchLabel')])},computed: {},methods: {}
}
</script>
对应组件中通过 computed
方法获取状态数据
computed: {labelList(){return this.$store.state.common.labelList}
},
十、Nuxt.js 的错误页面和个性 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。
- 我们先把
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>
- 第一步完成后,我们修改
/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 numberreturn /^\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 的方法,增加了 asyncData
,异步请求数据。
1. 三种方式
Nuxt.js 提供了几种不同的方法来使用 asyncData
方法,你可以选择自己熟悉的一种来用:
-
返回一个
Promise
, Nuxt.js 会等待该Promise
被解析之后才会设置组件的数据,从而渲染组件.export default {async asyncData({ params }) {return axios.get(`https://my-api/posts/${params.id}`).then((res) => {return { title: res.data.title }})} }
-
使用
async
或await
export default {async asyncData({ params }) {const { data } = await axios.get(`https://my-api/posts/${params.id}`)return { title: data.title }} }
-
使用回调函数
export default {asyncData({ params }, callback) {axios.get(`https://my-api/posts/${params.id}`).then((res) => {callback(null, { title: res.data.title })})} }
安装 Axios
Vue.js 官方推荐使用的远程数据获取方式是 Axios,所以我们安装官方推荐,来使用 Axios。这里我们使用 npm 来安装 axios。 直接在终端中输入下面的命令:
npm install axios --save
2. asyncData
的 Promise 方法
我们在 pages
下新建一个文件,叫做 asyncData.vue
。然后写入下面的代码:
<script>
import axios from 'axios'
export default {data() {return {name: 'hello World',}},asyncData() {return axios.get('接口').then((res) => {console.log(res)return { info: res.data }})}
}
</script>
asyncData
的方法会把值返回到 data
中。是组件创建(页面渲染)之前的动作,所以不能使用 this.info
,
# return 的重要性
一定要 return 出去获取到的对象,这样就可以在组件中使用,这里返回的数据会和组件中的 data 合并。这个函数不光在服务端会执行,在客户端同样也会执行。
3. asyncData
的 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. asyncData
的 await 方法
当然上面的方法稍显过时,现在都在用 async...await
来解决异步, 改写上面的代码。
<script>
import axios from 'axios'
export default {data() {return {name: 'hello World',}},async asyncData() {let { data } = await axios.get('接口')return { info: data }}
}
</script>
5. 注意事项 + 生命周期:
asyncData
方法会在组件(限于页面组件)每次加载之前被调用asyncData
可以在服务端或路由更新之前被调用- 第一个参数被设定为当前页面的上下文对象
- Nuxt 会将
asyncData
返回的数据融合到组件的data
方法返回的数据一并返回给组件使用 - 对于
asyncData
方式实在组件初始化前被调用的,所以在方法内饰没办法通过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 框架非常简单,因为大部分的事情他都为我们做好了,我们只要安装它的规则来编写代码。