我如何用Vue在div中加载画布?



我对Vue真的很新,对于这个项目,我试图在div内加载画布。如果画布在div外加载,它可以正常工作,但我想显示一个画布,如果loadModal是真的。在这段代码中,我使用了两个画布,一个在div内,另一个在div外。它只在div外正确加载画布。有没有一种方法来加载画布内的div ?下面是我在JsFiddle

上的代码JsFiddle Code = https://jsfiddle.net/ujjumaki/6vg7r9oy/9/

<<p>视图/strong>
<div id="app">
<button @click="runModal()">
Click Me
</button>
<br><br>
<div v-if="loadModal == true">
<canvas id="myCanvas" width="200" height="100" style="border:3px solid #d3d3d3; color:red;">
</canvas>
</div>

<!-- this one loads correctly -->
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #d3d3d3;">
</canvas>
</div>

new Vue({
el: "#app",
data: {
loadModal: false,
},
methods: {
runModal(){
this.loadModal = true;
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(95, 50, 40, 0, 2 * Math.PI);
ctx.stroke();
}
}
})

尝试使用v-show并使用class代替id,这样您可以选择所有div:

new Vue({
el: "#app",
data: {
loadModal: false,
},
methods: {
runModal(){
this.loadModal = true;
const c = document.querySelectorAll("canvas");
c.forEach(can => {
let ctx = can.getContext("2d");
ctx.beginPath();
ctx.arc(95, 50, 40, 0, 2 * Math.PI);
ctx.stroke();
})
}
}
})
Vue.config.productionTip = false
Vue.config.devtools = false
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button @click="runModal()">
Click Me
</button>
<br><br>
<div v-show="loadModal == true">
<canvas class="canvas" id="myCanvas" width="200" height="100" style="border:3px solid #d3d3d3; color:red;">
</canvas>
</div>
<canvas class="canvas" id="myCanvas" width="200" height="100" style="border:3px solid #d3d3d3; color:red;">
</canvas>
</div>

问题是runModal()loadModal设置为true立即试图在有条件呈现的<div v-if="loadModal">中引用<canvas>,但<div>(及其<canvas>)仍然未呈现尚未loadModal变化的效果直到下一个渲染周期才完成。<div>之外的<canvas>"load "正确,因为它不是有条件呈现的。

一种解决方案是在尝试访问<canvas>:

之前,使用$nextTick()回调await下一个渲染周期。
new Vue({
methods: {
async runModal() {
this.loadModal = true;
// await next render cycle
await this.$nextTick();
// <canvas id="myCanvas"> is available here
var c = document.getElementById("myCanvas");
⋮
}
}
})

更新小提琴

或者,使用<div v-show="loadModal">(如另一个答案所述)也可以工作,因为<canvas>已经在文档中呈现,因此可以查询。如果您更喜欢延迟渲染<canvas>,请坚持使用v-if="loadModal"

最新更新