Javascript 调整大小时未定义Vue画布$ref。抛出错误,但works似乎仍能正常工作?
在我的应用程序中,我有一个选项卡式界面,在选项卡的一个“窗口”中,有一个画布,每次调整窗口大小时,它都会自动适应窗口大小。一切正常,但当我切换选项卡并切换回来,然后尝试调整窗口大小时,它仍然可以工作,但会抛出“this.$refs.canvas is undefined”错误 我已经建立了一个简单的示例,可以切换画布元素的开和关。如果要尝试调试,则代码已完成。如果在加载后立即调整窗口的大小,并且窗口可以正常工作,那么没有问题,但是如果打开和关闭画布,它将抛出一个错误 主应用程序文件:Javascript 调整大小时未定义Vue画布$ref。抛出错误,但works似乎仍能正常工作?,javascript,html,vue.js,Javascript,Html,Vue.js,在我的应用程序中,我有一个选项卡式界面,在选项卡的一个“窗口”中,有一个画布,每次调整窗口大小时,它都会自动适应窗口大小。一切正常,但当我切换选项卡并切换回来,然后尝试调整窗口大小时,它仍然可以工作,但会抛出“this.$refs.canvas is undefined”错误 我已经建立了一个简单的示例,可以切换画布元素的开和关。如果要尝试调试,则代码已完成。如果在加载后立即调整窗口的大小,并且窗口可以正常工作,那么没有问题,但是如果打开和关闭画布,它将抛出一个错误 主应用程序文件: <t
<template>
<div id="app">
<button class="toggleBtn" @click="toggleCanvas()">Toggle Canvas</button>
<component class="canvasBox" :is="canvasElX" />
</div>
</template>
<script>
import ResizeCanvas from './components/ResizeCanvas.vue'
export default {
name: 'App',
components: {
ResizeCanvas
},
data(){
return {
canvasShow: true,
canvasEl: null
}
},
computed: {
canvasElX(){
if (this.canvasShow){
return ResizeCanvas;
}
else{
return null;
}
}
},
methods: {
toggleCanvas(){
this.canvasShow = !this.canvasShow;
}
}
}
</script>
<style>
html, body{
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
}
#app {
display: flex;
width: 100%;
height: 100%;
}
.toggleBtn{
width: 150px;
}
.canvasBox{
flex-grow: 1;
}
</style>
切换画布
从“./components/ResizeCanvas.vue”导入ResizeCanvas
导出默认值{
名称:“应用程序”,
组成部分:{
调整画布大小
},
数据(){
返回{
拉票秀:没错,
画布:空
}
},
计算:{
canvasElX(){
如果(本次拉票){
返回大小调整画布;
}
否则{
返回null;
}
}
},
方法:{
切换画布(){
this.canvasShow=!this.canvasShow;
}
}
}
html,正文{
边际:0px;
填充:0px;
宽度:100%;
身高:100%;
}
#应用程序{
显示器:flex;
宽度:100%;
身高:100%;
}
.toggleBtn{
宽度:150px;
}
.拉票箱{
柔性生长:1;
}
调整画布组件的大小:
<template>
<div ref="resizeCanvas" class="resizeCanvas">
<canvas ref="canvas" class="canvas">
//Error loading canvas
</canvas>
</div>
</template>
<script>
export default {
name: 'ResizeCanvas',
mounted(){
window.addEventListener('resize', ()=>{this.resizeCanvas()});
this.resizeCanvas();
this.drawCanvas();
},
beforeDestroy(){
window.removeEventListener('resize', ()=>{this.resizeCanvas()});
},
methods: {
resizeCanvas(){
let canvas = this.$refs.canvas;
canvas.width = this.$refs.resizeCanvas.clientWidth;
canvas.height = this.$refs.resizeCanvas.offsetHeight;
this.drawCanvas();
},
drawCanvas(){
let canvas = this.$refs.canvas;
let ctx = canvas.getContext('2d');
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, 50, 50);
ctx.fillRect(canvas.width - 50, canvas.height - 50, 50, 50);
}
}
}
</script>
<style scoped>
.resizeCanvas{
position: relative;
width: 100%;
height: 100%;
}
.canvas{
position: absolute;
}
</style>
//加载画布时出错
导出默认值{
名称:“ResizeCanvas”,
安装的(){
window.addEventListener('resize',()=>{this.resizeCanvas()});
这个.resizeCanvas();
这个.drawCanvas();
},
在…之前{
window.removeEventListener('resize',()=>{this.resizeCanvas()});
},
方法:{
调整画布大小(){
让canvas=this.$refs.canvas;
canvas.width=此。$refs.resizeCanvas.clientWidth;
canvas.height=此。$refs.resizeCanvas.offsetHeight;
这个.drawCanvas();
},
drawCanvas(){
让canvas=this.$refs.canvas;
设ctx=canvas.getContext('2d');
ctx.fillStyle='黑色';
ctx.fillRect(0,0,50,50);
ctx.fillRect(canvas.width-50,canvas.height-50,50);
}
}
}
.resizeCanvas{
位置:相对位置;
宽度:100%;
身高:100%;
}
.帆布{
位置:绝对位置;
}
这是一个相当令人费解的问题。尽管它似乎无论如何都能工作,但我担心这可能会在后台造成一些隐秘的问题,我将来必须找出困难的办法。这里的问题是,您将不断添加新的事件侦听器,而旧的事件侦听器仍在运行,对
this的引用陈旧。$refs
这是因为您不幸没有正确使用(这是一个非常容易犯的错误)。要正常工作,您需要将与您在addEventListener
中注册的完全相同的函数传递给它
只要传入对组件方法的引用,就可以取消匿名箭头函数
mounted(){
window.addEventListener('resize',this.resizeCanvas)//传递方法引用
这个是resizeCanvas()
this.drawCanvas()
},
在…之前{
window.removeEventListener('resize',this.resizeCanvas)//相同的函数引用
},
如果您不想在每次激活选项卡时都重新加载画布,那么您可能会对以下内容感兴趣。谢谢,工作起来很有魅力!这真的很令人沮丧,因为我以为我正在删除事件侦听器,所以我不知道它还能是什么。谢谢你澄清这一点。我真的不想让它保持活力,因为我更愿意释放内存,但“保持活力”这句话听起来在未来可能真的很有用,所以也谢谢你。