解决Vue异步请求中this为undefined以及mounted中获取不到data的数据的问题
解决Vue异步请求中this为undefined以及mounted中获取不到data的数据的问题
起因
使用Nuxt
做项目要实现视频点播功能,视频存在阿里云,整合了一个阿里云播放器,在created
中使用封装的异步请求获取视频的vid和播放凭证,但是发现后端接口提示获取视频id失败。
<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
。
我就纳闷了这是什么鬼情况。对前端进行DEBUG,发现赋值后的视频id和播放凭证仍是空。

看到这,我怀疑是this
的锅,将视频id的赋值放到异步请求外,发现输出了undefined
,离谱......
这说明路由没有这个值,对这个方法进行一下DEBUG。
可以发现,路由中果然没有这个值....
我记得还有一种方式传递,是在路径后加?参数名=xxx
,并用this.$route.query.xxx
得到它的值,说干就干!
进行DEBUG,成功获取到了视频id!
那么接下来的问题就只剩下,异步请求中如何给播放凭证赋值了...尝试在外头用变量保存this试试....
成功保存!
但是我发现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>

$\color{red}{那就为mounted设置一个定时器,created获取数据的速度是很快的,让mounted停那么一丢丢时间}$。
mounted: function () {
setTimeout(() => {
//填入要执行的方法
}, 1000);
}
mounted: function () {
//定时器,进行延迟,等待异步请求数据
setTimeout(() => {
//填入要执行的方法
this.createPlayer();
}, 1000);
}
完美!
<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>
总结
- 获取路由参数的两种方式
- this.$route.params.id 用于获取如下形式的参数
路径/id
- this.$route.query.xxx 用于获取如下形式的参数 路径?xxx=...
- this.$route.params.id 用于获取如下形式的参数
- 注意在异步请求中的
this
不是VueComponent
- 注意
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
}
})
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律