Search code examples
javascriptcanvasvue.jscomponentslifecycle

vueJS life cycle with canvas, switching components


Im having some trouble displaying vue components containing a canvas with different behaviors.

I want to be able to "switch component" using v-if and passing different properties.

i made a small example, see code below:

What happens now is that when i switch to 'blue' then 'red' is still "living" so when i draw the color is still 'red', although i can see the dom is changing and switching to 'canvas2'

--- COMPONENT------

<template>
        <div class="container-fluid">

        <canvas style="border: 1px solid black;" width="300px" height="150px" :id="'canvas'+canvasKey"></canvas>

        </div>
        </template>

    export default {
        data: function() {
            return {
            }
        },
        mounted: function() {
            this.draw_canvas()
        },
        created: function() {
        },
        watch: {},
        props: ['canvasKey'],
        computed: {},
        methods: {
            draw_canvas: function() {
                var app = this
                var c = document.getElementById("canvas"+this.canvasKey)
                var ctx = c.getContext("2d");

                if(this.canvasKey == 1) {
                    var color = 'red'
                } else if(this.canvasKey == 2) {
                    var color = 'blue'
                }

                var mousePos = function(mouseEv) {
                    let offset = $("#canvas"+app.canvasKey).offset()
                    let pos = {
                        x: mouseEv.pageX - offset.left,
                        y: mouseEv.pageY - offset.top,
                    }
                    return pos
                }

                $('#canvas'+this.canvasKey).on('mousemove' , function(ev) {
                    var pos = mousePos(ev)
                    ctx.beginPath()
                    ctx.arc(pos.x, pos.y, 10, 0, 2 * Math.PI)
                    ctx.fillStyle = color
                    ctx.fill()
                })
            }
        }
    }

---CREATE COMPONENT---

<canvas-test v-if="color == 'red'"  canvasKey="1"></canvastest>
<canvas-test v-if="color == 'blue'" canvasKey="2"></canvas-test>

I hope i made my question clear, help will be much appreciated, thnks alot in advance


Solution

  • You use a non-reactive variable inside v-if statements. This is not supported and the net effect is that the v-if evaluation doesn't changes, even if color does, so it's always the same component being rendered.

    Switch to using a color data property in the parent component and, for example, use v-model or v-bind:value to use it (as described in Using-v-model-on-Components in the guide). In the parent:

    <template>
      ...
        <canvas-test v-if="color == 'red'" v-model="color"  canvasKey="1"></canvastest>
        <canvas-test v-if="color == 'blue'" v-model="color" canvasKey="2"></canvas-test>
      ...
    </template>
    <script>
    ...
    export default {
      data () {
        ...
        color: 'red',
        ...
      }
      ...
      components: {
        CanvasTest
      }
      ...
    }
    </script>
    

    in the canvas component:

    <script>
    ...
    export default {
      ...
      props: ['value'],  // the color is in 'value'
      ...
    }
    </script>
    

    If you only want to have multiple components with different properties, just define their properties using props.