Soy realmente nuevo en Vue y para este proyecto, estaba tratando de cargar un lienzo dentro de un div. Si el lienzo se carga fuera de un div, funciona correctamente, pero quiero mostrar un lienzo solo si loadModal es verdadero. En este código, he usado dos lienzos, uno está dentro de div y el otro está fuera de div. Carga el lienzo correctamente fuera de div solamente. ¿Hay alguna manera de cargar el lienzo dentro de div también? Aquí está mi código a continuación en JsFiddle
Código JsFiddle = https://jsfiddle.net/ujjumaki/6vg7r9oy/9/
Vista
<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>Método
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(); } } })Pruebe con v-show y con class en lugar de id, para que pueda seleccionar todos los divs:
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>El problema es que runModal() establece loadModal en true e inmediatamente intenta hacer referencia al <canvas> dentro del <div v-if="loadModal"> representado condicionalmente, pero el <div> (y su <canvas> ) todavía no se representa todavía El efecto del cambio loadModal no se completa hasta el siguiente ciclo de renderizado. El <canvas> fuera de <div> se "carga" correctamente porque no se representa de forma condicional.
Una solución es await el siguiente ciclo de renderizado con la devolución de llamada $nextTick() antes de intentar acceder al <canvas> :
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"); ⋮ } } }) Alternativamente, usar <div v-show="loadModal"> (como se describe en otra respuesta) también funciona porque el <canvas> ya está representado en el documento y, por lo tanto, está disponible para consultar. Si prefiere representar perezosamente el <canvas> , quédese con v-if="loadModal" .