Nuxt.js学习(八) --- 异步数据

[TOC]

1、异步数据

1.1、官方文档:

Nuxt.js 扩展了 Vue.js,增加了一个叫 asyncData 的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。

asyncData 方法

asyncData方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。 在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用 asyncData方法来获取数据,Nuxt.js 会将 asyncData 返回的数据融合组件 data 方法返回的数据一并返回给当前组件。

注意:由于asyncData方法是在组件初始化前被调用的,所以在方法内是没有办法通过 this 来引用组件的实例对象。

Nuxt.js 提供了几种不同的方法来使用 asyncData 方法,你可以选择自己熟悉的一种来用:

  1. 返回一个 Promise, nuxt.js会等待该Promise被解析之后才会设置组件的数据,从而渲染组件.
  2. 使用 async 或 await (了解更多)

我们使用[axios]重构HTTP请求,我们强烈建议您使用[axios模块]用于您的Nuxt项目中。

如果您的项目中直接使用了node_modules中的axios,并且使用axios.interceptors添加拦截器对请求或响应数据进行了处理,确保使用 axios.create创建实例后再使用。否则多次刷新页面请求服务器,服务端渲染会重复添加拦截器,导致数据处理错误。

import axios from 'axios'
const myaxios = axios.create({
  // ...
})
myaxios.interceptors.response.use(function (response) {
  return response.data
}, function (error) {
  // ...
})

返回 Promise

export default {
  asyncData ({ params }) {
    return axios.get(`https://my-api/posts/${params.id}`)
      .then((res) => {
        return { title: res.data.title }
      })
  }
}

2、具体使用

2.1.1、安装Axios

构建项目时,如果选择了axios组件,这一步跳过

npm install axios --save

2.1.2、建议配置baseURL

2.2.1 使用asyncData--一次请求【掌握】

//asyncData语法1:使用context对象
<template>
	{{名称}}
</template>

<script>
export default {
    //asyncData不能使用this(当前组件)
    //提供第一个参数context,表示上下文(nuxt所有功能)
    asyncData( context ) {
        //发送ajax
        let 数据 = context.$axios.get('','')
        // 将数据组合并返回
        return {
            名称: 数据
        }
    }
}
</script>


//asyncData语法2:对context对象进行解构,context.$axios--->{$axios}
<script>
export default {
    async asyncData( {$axios} ) {
        //发送ajax
        let { data } = await $axios.get('路径')
        //封装
        return {
            变量: 查询数据
        }
    }
}
</script>

示例

<template>
  <div>
    {{pageInfo}}
  </div>
</template>

<script>
export default {
  async asyncData( context ) {
      //发送ajax
      let { data } = await context.$axios.get('/userservice/user/list')
      //组合数据
      return {
        pageInfo: data.data
      }
  },
}
</script>

<style>

</style>

普通ajax和asyncData对比

2.2.2 使用asyncData--多次请求【掌握】

  • 多次请求,需要借助 Promise ( $axios.get() 返回的就是 Promise对象 )
<script>
//很少直接使用“响应对象”
export default {
    async asyncData( {$axios} ) {
        //发送多次请求
        let [响应1,响应2] = await Promise.all([请求1, 请求2])
        //返回数据
        return {
            变量1: 响应1,
            变量2: 响应2
        }
    }
}
</script>
<script>
//对“响应对象”进行解构   响应1 --> { data }
//“响应1”和“响应2”,都可以解构出data,变量名重复,建议采用别名 { data: 别名}
export default {
    async asyncData( {$axios} ) {
        //发送多次请求
        let [ { data: d1 }, {data:d2} ] = await Promise.all([请求1, 请求2])
        //返回数据
        return {
            变量1: d1.data, 
            变量2: d2.data
        }
    }
}
</script>
  • 实例1:Promise.all 发送1个请求
<template>
  <div>
      {{pageInfo}}
  </div>
</template>

<script>
export default {
  async asyncData({ $axios }) {
    //发送ajax
    let [ {data} ] = await Promise.all([ $axios.get('/userservice/user/list') ])
    //返回
    return {
      pageInfo : data.data
    }
  },
}
</script>

<style>

</style>
  • 实例2:Promise.all 发送2个请求
<template>
  <div>
      {{pageInfo}}
      {{list}}
  </div>
</template>

<script>
export default {
  async asyncData({ $axios }) {
    //发送ajax
    let [ {data : d1 }, {data : d2} ] = await Promise.all([ $axios.get('/userservice/user/list'), $axios.get('/userservice/user/list2') ])
    //返回
    return {
      pageInfo : d1.data,
      list : d2.data
    }
  },
}
</script>

<style>

</style>

2.3.1、 fetch发送ajax

  • fetch 方法用于在渲染==页面前==填充应用的状态树(store)数据, 与 asyncData 方法类似,不同的是它不会设置组件的数据。

  • 对比图

  • fetch语法:

    <script>
    export default {
        async fetch( {$axios, store } ) {
           //发送ajax
           let { data } = await $axios.get('路径')
           //将查询结果存放vuex中
           //....
        }
    }
    </script>
    
  • 实例

<template>
  <div>

  </div>
</template>

<script>
export default {
  async fetch( {$axios} ) {
    //发送ajax
    let { data } = await $axios.get('/userservice/user/list')
    console.info( data )
    //将查询结果保存vuex
  }
}
</script>

<style>

</style>

创建远程数据

{
  "name": "庭前云落",
  "age": 18,
  "temp": "I love java!"
}

输入后会拿到一个地址,就是你刚刚输入的数据请求地址

https://api.myjson.com/bins/1bqqsw

ansycData.vue

<template>
  <div>
    <h1>姓名:{{info.name}}</h1>
    <h2>年龄:{{info.age}}</h2>
    <h2>简介:{{info.temp}}</h2>
  </div>
</template>

<script>
import axios from 'axios'
export default {
   data() {
     return {
      name:"111"
     }
   },
  async asyncData(){
  let{data} =await axios.get('https://api.myjson.com/bins/1bqqsw')
   return {info:data}
   } 
};
</script>

<style>
</style>

展示效果:

3、自定义axios:实现步骤

  • 自定义axios目的:编写一个api.js文件,用于统一维护请求路径

  • 步骤一:前提,修改nuxt.config.js,编写axios baseURL

  • 步骤二:创建 ~/plugins/api.js 文件,并在nuxt.config.js文件进行配置(仅客户端可用)

  plugins: [
    { src: '~/plugins/ElementUI', ssr: true },
    { src: '~/plugins/api.js', mode: 'client' }
  ]

  • 步骤三:修改api.js,拷贝固定内容,在api中编写具体功能
//自定义函数
const request = {
    // test: (params) => {
    //     return axios.get('/web-service/test', {
    //         params
    //     })
    // },
    //方法名 : 函数
    findAll: (params) => {
        return axios.get('/teacherservice/tbclass',{params})
    }

}

var axios = null
export default ({ $axios }, inject) => {

    //3) 保存内置的axios
    axios = $axios

    //4) 将自定义函数交于nuxt
    // 使用方式1:在vue中,this.$request.xxx()
    // 使用方式2:在nuxt的asyncData中,content.app.$request.xxx()

    inject('request', request)
}
  • 步骤四:其他组件中发送ajax
<template>
  <div>
    <el-form :inline="true" v-model="tbClass" class="demo-form-inline" size="mini">
      <el-form-item label="班级名称">
        <el-input v-model="tbClass.cname" placeholder="请输入班级名称"></el-input>
      </el-form-item>
      <el-button type="primary" size="mini" @click="findAll()">查询</el-button>
    </el-form>

    {{tbClass}}
    <el-table :data="tlist" style="width: 100%" border stripe>
      <el-table-column prop="cname" label="班级名称" width="180"></el-table-column>
      <el-table-column prop="teacher1.tname" label="授课老师名称" width="180"></el-table-column>
      <el-table-column prop="teacher2.tname" label="处理老师名称" width="180"></el-table-column>
      <el-table-column prop="teacher3.tname" label="辅导员老师名称" width="180"></el-table-column>
      <el-table-column label="操作">
        <el-button size="mini">编辑</el-button>
        <el-button size="mini" type="danger">删除</el-button>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tlist: [],
      tbClass: {}
    };
  },
  methods: {
    async findAll() {
      let { data: baseResult } = await this.$request.findAll(this.tbClass);
      this.tlist = baseResult.data;
    }
  },
  async mounted() {
    this.findAll();
  }
};
</script>

<style>
</style>

3.1.1、自定义axios 原理分析

  • 测试 asyncData

  • 修改让模式支持服务端

<template>
  <div>
    {{pageInfo}}
  </div>
</template>

<script>
export default {
  //页面加载成功 (前端客户端执行)
  async mounted() {
    //发送ajax
    let { data } = await this.$request.findAll()

    console.info( data )
  },
  // 前端服务端执行
  async asyncData( context ) {
    let { data } = await context.app.$request.findAll()
    return {
      pageInfo : data.data
    }
  },
}
</script>

<style>

</style>

4、错误处理

Nuxt.js 在上下文对象context中提供了一个 error(params) 方法,你可以通过调用该方法来显示错误信息页面。params.statusCode 可用于指定服务端返回的请求状态码。

以返回 Promise 的方式举个例子:

export default {
  asyncData ({ params, error }) {
    return axios.get(`https://my-api/posts/${params.id}`)
      .then((res) => {
        return { title: res.data.title }
      })
      .catch((e) => {
        error({ statusCode: 404, message: 'Post not found' })
      })
  }
}

如果你使用 回调函数 的方式, 你可以将错误的信息对象直接传给该回调函数, Nuxt.js 内部会自动调用 error 方法:

export default {
  asyncData ({ params }, callback) {
    axios.get(`https://my-api/posts/${params.id}`)
      .then((res) => {
        callback(null, { title: res.data.title })
      })
      .catch((e) => {
        callback({ statusCode: 404, message: 'Post not found' })
      })
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值