Leafage 诞生记(二nuxt.js如何在组件和页面请求数据)

Posted 布吉岛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leafage 诞生记(二nuxt.js如何在组件和页面请求数据)相关的知识,希望对你有一定的参考价值。

本文个人博客地址:https://www.abeille.top/posts/detail/213489UI

上一篇 创建了前端工程,接下来开始写代码。

因为初始化项目,只是最小的一些基本依赖,再开发中,需要一些第三方的库来支持,比如样式/组件库。

在开发Leafage网站的过程中,我试用过viewui(原来叫iview)、element-ui、ant design vue、vuetify这几个组件库,但是约到后面会发现,使用组件库是比较容易开发界面,但是限制很多,而且很多文档写的不好,稍微复杂点的组合或者配置,很难实现,还有最重要的一点,除了vuetify之外的几个组件库, 都不是默认支持响应式的,需要自己适配,后来发现了nuxtjs的官网用的是css样式库tailwindcss,与它同样类似的还有bulma,bulma和tailwindcss都是css开发的,不包含任何框架依赖,但是bulma更类似于bootstrap,区别是不依赖jquery等任何javascript,参考nuxtjs官网的开发,选择使用tailwindcss。

作为一个java开发的程序员,从零开始写前端,还不用组件库,是很难肯痛苦的事情,那找一个好看的模板来模仿,总是容易的吧,然后就开始网罗各大模板网站,有的模板可能需要花几块钱,买一个自己满意的,然后参照来写或者直接进行修改。

页面开发完成之后,需要请求服务接口,由于现在还没有开发后台服务,所以需要使用mock.js来进行api的模拟。

首先安装mock.js依赖:

yarn add mock.js -D

安装完成后,打开plugins目录,添加 mock.ts 文件(如果使用的是javascript,则创建mock.js),配置mock接口,示例如下:

import Mock from \'mockjs\'

Mock.mock(/posts\\.json/, {
  \'list|1-10\': [{
    \'id|+1\': 1,
    \'title\': \'my title\'
  }]
})

配置完成之后,需要在nuxt.config.ts文件中进行配置,才会生效,否则,会执行默认的配置;

  // Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
  plugins: [
    \'~/plugins/mock\'
  ],

接下来就使用axios请求接口,获取数据了。

1、配置axios

因为初始化项目时,安装了axios工具,现在就可以在页面(pages目录下的.vue)或者组件(components目录下的.vue)中使用axios来请求数据。nuxtjs默认会配置axios的一些配置,如果想要进行自己的一些配置,那么在plugins目录下创建axios.ts文件,然后进行相关设置,参考如下:

import { Plugin } from \'@nuxt/types\'
import { AxiosRequestConfig, AxiosError } from \'axios\'

const statusCode: any = {
  400: \'请求参数错误\',
  401: \'权限不足, 请重新登录\',
  403: \'服务器拒绝本次访问\',
  500: \'内部服务器错误\',
  501: \'服务器不支持该请求中使用的方法\',
  502: \'网关错误\',
  504: \'网关超时\'
}

export const accessor: Plugin = ({ error, app: { $axios }, redirect }) => {

  $axios.onRequest((config: AxiosRequestConfig) => {
    return config
  })

  $axios.onError((err: AxiosError<any>) => {
    const status: any = err.response?.status
    if (status === 404) {
      redirect(\'/error\')
    } else {
      error({ message: statusCode[status] })
      return Promise.reject(err)
    }
  })
}

需要注意的是,当使用typescript时,引入axios的时候,不是

import axios form \'axios\'

而是需要通过@nuxt/types引入Plugin,然后引入axios的AxiosRequestConfig和 AxiosError如果用到axios更多属性,则同样需要引入;

import { Plugin } from \'@nuxt/types\'
import { AxiosRequestConfig, AxiosError } from \'axios

和mockjs同样的,配置完成后,需要在nuxt.config.ts中的plugins项下加入此配置文件;

  // Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
  plugins: [
    \'~/plugins/mock\',
    \'~/plugins/axios\'
  ],

2、使用axios

基础的使用方法参考axios官方文档(中文文档:http://axios-js.com/zh-cn/docs/ ),包括同步请求、异步请求、并发请求等。

在nuxtjs中除了在vue勾子(Hook)中使用axios的一般场景,针对渲染的时机,它还提供了另外两种请求请求数据的函数,fetch() 和 asyncData()。

两个函数的共同点是,都是异步函数,所以在使用时需要await关键字,两者的区别是:

asyncData():

  • 只能在页面中使用,即pages目录下的.vue文件中,他会阻塞页面的加载,所以不能请求很大的数据量或者很多同步接口;
  • 不能使用this关键字;
  • 不能被调用,只在页面加载时,自动执行;

fetch():

  • 可以在组件中使用,也可以在页面中使用,即在components目录和pages目录下的.vue文件中都可以;
  • 可以使用this关键字;
  • 可以重复调用,即在组件中直接调用fetch()来重新获取数据;

针对两个函数的使用,我们通过一下示例来看看如何使用:

fetch()示例:

import { defineComponent } from "@vue/composition-api";
import { SERVER_URL } from "~/assets/request";

export default defineComponent({
  name: "Main",

  async fetch() {
    this.datas = await this.$axios
      .get(SERVER_URL.posts.concat("?page=0&size=10&order=", this.order))
      .then((res) => res.data);
  },

  data() {
    return {
      datas: [],
      order: "likes",
    };
  },

  methods: {
    retrieve(order: string) {
      this.order = order;
      this.$fetch(); // 这里调用fetch()函数,复用接口请求
    },
  },
});

示例中展示了,fetch()请求接口的使用以及在其他函数中如何被调用执行;

另外,使用fetch()会有一个$fetchState来判断fetch()执行情况,可以根据不同情况处理不同的页面逻辑,示例如下:

<div>
    <p v-if="$fetchState.pending">Fetching mountains...</p>
    <p v-else-if="$fetchState.error">An error occurred :(</p>
    <div v-else class="mb-12">
    </div>
</div>

asyncData示例:

import { defineComponent } from "@vue/composition-api";
import { SERVER_URL } from "~/assets/request";

export default defineComponent({
  name: "Portfolio",

  scrollToTop: true, // 这个配置会在加载页面是自动滚动到页面顶部

  async asyncData({ app: { $axios } }) { // asyncData()函数中不能使用this关键字,所以这里通过入参方式引入全局配置的一些参数,这里需要axios
    let [datas, categories] = await Promise.all([
      await $axios.$get(SERVER_URL.portfolio.concat("?page=0&size=10")),
      await $axios.$get(SERVER_URL.category.concat("?page=0&size=5")),
    ]);
    return { datas, categories };
  },

  data() {
    return {
      code: "",
      datas: [],
    };
  },

  methods: {
    retrieve(code: string) {
      this.code = code;
      this.$axios
        .get(SERVER_URL.portfolio.concat("?page=0&size=12&category=", code))
        .then((res) => (this.datas = res.data));
    },
  },

  head() {
    const title = "Portfolio - Leafage";
    const description =
      "Leafage的作品集,包含旅行记录、生活分享等资源信息,提供原创、优质、完整内容";
    return {
      title,
      meta: [
        { hid: "description", name: "description", content: description },
        // Open Graph
        { hid: "og:title", property: "og:title", content: title },
        {
          hid: "og:description",
          property: "og:description",
          content: description,
        },
        // Twitter Card
        { hid: "twitter:title", name: "twitter:title", content: title },
        {
          hid: "twitter:description",
          name: "twitter:description",
          content: description,
        },
      ],
    };
  },
});

通过代码可以看到,在asyncData()函数使用时,传入了对象参数 app: { $axios },因为asyncData()执行的时候,组件还没有初始化完成,因此只能通过引入全局挂在的配置来使用一些工具,同样可以传入 $store, $router等;

推荐几个模板站:

  1. http://www.bootstrapmb.com/
  2. https://tailwindcomponents.com/
  3. https://www.mobantu.com/6548....

以上是关于Leafage 诞生记(二nuxt.js如何在组件和页面请求数据)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 nuxt.js 上从子组件获取父组件的值?

如何使用 Nuxt.js 从缓存中排除组件?

Nuxt.js的学习路由组件的学习

NUXT.js 和 Axios 运行时如何避免代码重复?

Nuxt.js - 如何在布局内使用布局

如何在 Nuxt 中用一个组件创建无限路由