解决Vue异步请求中this为undefined以及mounted中获取不到data的数据的问题

解决Vue异步请求中this为undefined以及mounted中获取不到data的数据的问题

起因

使用Nuxt做项目要实现视频点播功能,视频存在阿里云,整合了一个阿里云播放器,在created中使用封装的异步请求获取视频的vid和播放凭证,但是发现后端接口提示获取视频id失败。

image-20220723122110528

<template>
  <div>
    <!-- 阿里云视频播放器样式 -->
    <link
      rel="stylesheet"
      href="https://g.alicdn.com/de/prismplayer/2.8.1/skins/default/aliplayer-min.css"
    />
    <!-- 阿里云视频播放器脚本 -->
    <script
      charset="utf-8"
      type="text/javascript"
      src="https://g.alicdn.com/de/prismplayer/2.8.1/aliplayer-min.js"
    />

    <!-- 定义播放器dom -->
    <div id="J_prismPlayer" class="prism-player" />
  </div>
</template>
<script>
import vodApi from "@/api/vod";

export default {
  layout: "video", //应用video布局
  data() {
    return {
      vid: "",
      playAuth: "",
    };
  },
  created() {
    this.init()
  },
  methods: {
    init() {
      vodApi.getPlayAuth(this.$route.params.id).then((response) => {
        this.vid = this.$route.query.courseId;
        this.playAuth = response.data.data.playAuth;
      });
    },
    createPlayer() {
      new Aliplayer(
        {
          id: "J_prismPlayer",
          vid: this.vid, // 视频id
          playauth: this.playAuth, // 播放凭证
          encryptType: "1", // 如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项
          width: "100%",
          height: "500px",
          // 以下可选设置
          cover: "", // 封面
          qualitySort: "asc", // 清晰度排序

          mediaType: "video", // 返回音频还是视频
          autoplay: false, // 自动播放
          isLive: false, // 直播
          rePlay: false, // 循环播放
          preload: true,
          controlBarVisibility: "hover", // 控制条的显示方式:鼠标悬停
          useH5Prism: true, // 播放器类型:html5
        },
        function (player) {
          console.log("播放器创建成功");
        }
      );
    },
  },
  mounted(){
    //页面渲染之后  created
    this.createPlayer()
  },
};
</script>

排查

​ 对后端接口进行了DEBUG,发现获取到的id为undefined

image-20220723122358977

​ 我就纳闷了这是什么鬼情况。对前端进行DEBUG,发现赋值后的视频id和播放凭证仍是空。

image-20220723123253207

image-20220723123344600

​ 看到这,我怀疑是this的锅,将视频id的赋值放到异步请求外,发现输出了undefined,离谱......

image-20220723125120025

image-20220723125746050

​ 这说明路由没有这个值,对这个方法进行一下DEBUG。

image-20220723125211928

​ 可以发现,路由中果然没有这个值....

image-20220723125955601

​ 我记得还有一种方式传递,是在路径后加?参数名=xxx,并用this.$route.query.xxx得到它的值,说干就干!

image-20220723130308238

image-20220723130708999

​ 进行DEBUG,成功获取到了视频id!

image-20220723130753381

​ 那么接下来的问题就只剩下,异步请求中如何给播放凭证赋值了...尝试在外头用变量保存this试试....

​ 成功保存!

image-20220723131152950

​ 但是我发现DEBUG的时候,并不执行then里面的语句!....

​ 经过百度,发现mounted中读取数据的时候,以及console.log输出的时候,有可能created的异步请求还没有返回数据,自然是无法读取和输出的。$\color{red}{也就是created里的数据还没获取到,mounted就开始了渲染视图的工作,且mounted只会调用一次}$。接下来,DEBUG一波,返现直接跳过了then,去执行mounted了,后面才执行的then

<template>
  <div>
    <!-- 阿里云视频播放器样式 -->
    <link
      rel="stylesheet"
      href="https://g.alicdn.com/de/prismplayer/2.8.1/skins/default/aliplayer-min.css"
    />
    <!-- 阿里云视频播放器脚本 -->
    <script
      charset="utf-8"
      type="text/javascript"
      src="https://g.alicdn.com/de/prismplayer/2.8.1/aliplayer-min.js"
    />

    <!-- 定义播放器dom -->
    <div id="J_prismPlayer" class="prism-player" />
  </div>
</template>
<script>
import vodApi from "@/api/vod";

export default {
  layout: "video", //应用video布局
  data() {
    return {
      vid: "",
      playAuth: "1",
    };
  },
  created() {
    console.log("执行了created");
    this.init();
    console.log(this.vid);
    console.log(this.playAuth);
    console.log("执行了created");
  },
  methods: {
    init() {
      this.vid = this.$route.query.vid;
      var that = this;
      vodApi
        .getPlayAuth(this.$route.query.vid)
        .then((response) => {
          console.log("执行了then");
          console.log(response.data);
        })
        .catch((response) => {
          console.log("执行了catch:" + response);
        });
    },
    createPlayer() {
      console.log("执行了mounted");
      new Aliplayer(
        {
          id: "J_prismPlayer",
          vid: this.vid, // 视频id
          playauth: this.playAuth, // 播放凭证
          encryptType: "1", // 如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项
          width: "100%",
          height: "500px",
          // 以下可选设置
          cover: "", // 封面
          qualitySort: "asc", // 清晰度排序

          mediaType: "video", // 返回音频还是视频
          autoplay: false, // 自动播放
          isLive: false, // 直播
          rePlay: false, // 循环播放
          preload: true,
          controlBarVisibility: "hover", // 控制条的显示方式:鼠标悬停
          useH5Prism: true, // 播放器类型:html5
        },
        function (player) {
          console.log("播放器创建成功");
        }
      );
    },
  },
  mounted(){
    this.createPlayer()
  },
};
</script>

image-20220723140501285

$\color{red}{那就为mounted设置一个定时器,created获取数据的速度是很快的,让mounted停那么一丢丢时间}$

mounted: function () {
    setTimeout(() => {
     //填入要执行的方法
    }, 1000);
  }
mounted: function () {
    //定时器,进行延迟,等待异步请求数据
    setTimeout(() => {
      //填入要执行的方法
      this.createPlayer();
    }, 1000);
  }

完美!

image-20220723140926921

image-20220723141058134

<template>
  <div>
    <!-- 阿里云视频播放器样式 -->
    <link
      rel="stylesheet"
      href="https://g.alicdn.com/de/prismplayer/2.8.1/skins/default/aliplayer-min.css"
    />
    <!-- 阿里云视频播放器脚本 -->
    <script
      charset="utf-8"
      type="text/javascript"
      src="https://g.alicdn.com/de/prismplayer/2.8.1/aliplayer-min.js"
    />

    <!-- 定义播放器dom -->
    <div id="J_prismPlayer" class="prism-player" />
  </div>
</template>
<script>
import vodApi from "@/api/vod";

export default {
  layout: "video", //应用video布局
  data() {
    return {
      vid: "",
      playAuth: "",
    };
  },
  created() {
    console.log("执行了created");
    this.init();
    console.log(this.vid);
    console.log(this.playAuth);
    console.log("执行了created");
  },
  methods: {
    init() {
      this.vid = this.$route.query.vid;
      var that = this;
      vodApi
        .getPlayAuth(this.$route.query.vid)
        .then((response) => {
          console.log("执行了then");
          that.playAuth = response.data.data.playAuth
        })
        .catch((response) => {
          console.log("执行了catch:" + response);
        });
    },
    createPlayer() {
      console.log("执行了mounted");
      new Aliplayer(
        {
          id: "J_prismPlayer",
          vid: this.vid, // 视频id
          playauth: this.playAuth, // 播放凭证
          encryptType: "1", // 如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项
          width: "100%",
          height: "500px",
          // 以下可选设置
          cover: "", // 封面
          qualitySort: "asc", // 清晰度排序

          mediaType: "video", // 返回音频还是视频
          autoplay: false, // 自动播放
          isLive: false, // 直播
          rePlay: false, // 循环播放
          preload: true,
          controlBarVisibility: "hover", // 控制条的显示方式:鼠标悬停
          useH5Prism: true, // 播放器类型:html5
        },
        function (player) {
          console.log("播放器创建成功");
        }
      );
    },
  },
  mounted:function(){
    setTimeout(() => {
        this.createPlayer()
    }, 1000);
  },
};
</script>

总结

  1. 获取路由参数的两种方式
    1. this.$route.params.id 用于获取如下形式的参数 路径/id
    2. this.$route.query.xxx 用于获取如下形式的参数 路径?xxx=...
  2. 注意在异步请求中的this不是VueComponent
  3. 注意data中的值由created中的异步请求获取并赋值的,mounted中要进行引用的话,可能异步请求中还未返回结果就被引用了。

推荐

具体详细的使用可以去官方查看

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

asyncData 方法

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

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

​ Nuxt.js 提供了几种不同的方法来使用 asyncData 方法,返回一个 Promise, nuxt.js 会等待该Promise被解析之后才会设置组件的数据,从而渲染组件.

Axios异步请求返回的就是一个Promise,所以用这一种方式就好。

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

asyncData({ params, error }) {
       return vod.getPlayAuth(params.vid)
        .then(response => {
            return { 
                playAuth: response.data.data.playAuth,
                vid: params.vid
            }
        })
}
posted @   ekertree  阅读(1925)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示