Total Newbie z Vue.js tutaj, tak przepraszam, jeśli brakuje mi czegoś oczywistych.

Chcę załadować komponenty oparte na zawartości zmiennej - więc jeśli zawartość moich zmiennych zmian, chcę odpowiednio zmienić komponent. Mam importowane wszystkie elementy (np import Project1 from "@/components/Project1";), które ponownie jest zapisywane w components: {'p1': Project1}

Używam <component :is="this.goTo.page"/> Z Goto.Page zdefiniowany w danych jako data() {return {goTo: {page: "p1"}}}. Problem wydaje się być reaktywnością Goto.page. Zaktualizuję go przez this.$set(this.goTo, "page", "p2");. Podczas pracy, otrzymuję błąd Uncaught TypeError: Cannot read property 'page' of undefined, który szczerze mówiąc, nie rozumiem, ponieważ jego zainicjowane z "P1".

import * as Matter from "matter-js";
import Project1 from "@/components/Project1";
import Project2 from "@/components/Project2";
import Project3 from "@/components/Project3";

export default {
  name: "Work",
  components: {
    'p1': Project1,
    'p2': Project2,
    'p3': Project3
  },
  data() {
    return {
      goTo: {
        page: "p1"
      }
    }
  },
  methods: {
    startMatter: function () {
  let harrie = require('@/assets/img/harrie.png');
  let kub = require('@/assets/img/kub.png');
  let jacs = require('@/assets/img/jacs.png');

  let container = document.getElementById('threecontainerWork');
  let nameTag = document.getElementById("title");

  let width = container.offsetWidth;
  let height = container.offsetHeight;

  let engine = Matter.Engine.create({});

  let renderer = Matter.Render.create({
    element: document.getElementById('matterContainer'),
    canvas: container,
    engine: engine,
    options: {
      width: width,
      height: height,
      wireframes: false
    }
  })

  let borderLeft = Matter.Bodies.rectangle(0, 0, 1, height * 2, {isStatic: true});
  let borderRight = Matter.Bodies.rectangle(width, 0, 1, height * 2, {isStatic: true});
  let roof = Matter.Bodies.rectangle(container.getBoundingClientRect().left, 0, width * 2, 1, {isStatic: true});
  let ground = Matter.Bodies.rectangle(container.getBoundingClientRect().left, height, width * 2, 1, {isStatic: true});
  let collider = Matter.Bodies.rectangle(container.offsetWidth / 2, container.offsetHeight, nameTag.offsetWidth, 1, {
    isStatic: true,
    isSensor: true,
    render: {
      fillStyle: 'red'
    }
  });

  let nameTagBox = Matter.Bodies.rectangle(container.offsetWidth / 2, container.offsetHeight / 2, nameTag.offsetWidth, nameTag.offsetHeight, {isStatic: true});

  let project1 = Matter.Bodies.rectangle(container.offsetWidth / 2, 100, 200, 200, {
    render: {
      sprite: {
        texture: harrie
      }
    }
  });
  let project2 = Matter.Bodies.rectangle(201, 0, 200, 200, {
    render: {
      sprite: {
        texture: kub
      }
    }
  });
  let project3 = Matter.Bodies.rectangle(1400, 0, 200, 200, {
    render: {
      sprite: {
        texture: jacs
      }
    }
  });

  let polyStack = Matter.Composites.stack(container.offsetWidth / 2, 50, 2, 10, 0, 0, function (x, y) {
    let sides = Math.round(Matter.Common.random(2, 8));
    return Matter.Bodies.polygon(x, y, sides, Matter.Common.random(100, 100));
  })

  let mouse = Matter.Mouse.create(renderer.canvas);
  let mouseConstraint = Matter.MouseConstraint.create(engine, {
    mouse: mouse
  })


  let colStart = Matter.Events.on(engine, 'collisionStart', function (event) {
    var pairs = event.pairs;

    for (var i = 0, j = pairs.length; i != j; ++i) {
      var pair = pairs[i];

      if (pair.bodyA === collider) {
        switch (pair.bodyB.id) {
          case project1.id:
            this.$set(this.goTo, 'page', "p1");
            break;
          case project2.id:
            this.$set(this.goTo, 'page', "p2");
            break;
          case project3.id:
            this.$set(this.goTo, 'page', "p3");
            break;
        }
      } else if (pair.bodyB === collider) {
        switch (pair.bodyA.id) {
          case project1.id:
            this.$set(this.goTo, 'page', "p1");
            break;
          case project2.id:
            this.$set(this.goTo, 'page', "p2");
            break;
          case project3.id:
            this.$set(this.goTo, 'page', "p3");
            break;
        }
      }
    }
  });
  let colEnd = Matter.Events.on(engine, 'collisionEnd', function (event) {
    var pairs = event.pairs;

    for (var i = 0, j = pairs.length; i != j; ++i) {
      var pair = pairs[i];

      if (pair.bodyA === collider) {
        switch (pair.bodyB.id) {
          case project1.id:
            this.$set(this.goTo, 'page', "noview");
            break;
          case project2.id:
            this.$set(this.goTo, 'page', "noview");
            break;
          case project3.id:
            this.$set(this.goTo, 'page', "noview");
            break;
        }
      } else if (pair.bodyB === collider) {
        switch (pair.bodyA.id) {
          case project1.id:
            this.$set(this.goTo, 'page', "noview");
            break;
          case project2.id:
            this.$set(this.goTo, 'page', "noview");
            break;
          case project3.id:
            this.$set(this.goTo, 'page', "noview");
            break;
        }
      }
    }
  });


  // TODO implement Vue.set(this.goTo, 'page', "p2"); correctly -> Matter Hell

  Matter.World.add(engine.world, [ground, borderLeft, borderRight, roof, collider, project1, project2, project3, nameTagBox, polyStack, mouseConstraint, colStart, colEnd]);
  Matter.Engine.run(engine);
  Matter.Render.run(renderer);

}
    },
  },
  mounted() {
    this.$nextTick(function () {
      this.startMatter();
    })
  }
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

#upperDiv {
    position: relative;

    width: 98vw;
    height: 81vh;
    margin: auto auto 1vh auto;

    display: flex;
    justify-content: center;
    align-items: center;

    top: 9vh /*Für alle anderen auch*/
}

#title {
    position: absolute;
    font-family: 'Playfair Display', serif;
    font-weight: 600;
    font-size: 5rem;
    color: #f0f0f0;
    padding: 2vh 3vw;
    border: 1px solid #f0f0f0;
    background-color: #1d1c1c;
    z-index: 2;
    text-align: center;
}

.threeContainer {
    width: 96vw;
    height: 70vh;
    z-index: 1;
    margin-bottom: 0;
}
<template>
  <div>
    <div id="upperDiv">
      <div class="threeContainer" id="matterContainer">
        <canvas id="threecontainerWork" class="threeContainer"></canvas>
      </div>
      <p id="title">My work</p>
    </div>
    <component :is="goTo.page"/>
  </div>
</template>
1
Nils 14 marzec 2021, 00:21

1 odpowiedź

Najlepsza odpowiedź

<component :is="goTo.page"/>

this nie jest dostępny w <template>. Dostępna jest wszystko "wewnątrz" {x2}}.

Oprócz powyższego i na aktualizację,

methods: {
  startMatter: function () {
    //some matter.js
    //if body collision detected:
    this.$set(this.goTo, 'page', "p2");
  },
},

Drugi argument tego. $ Set powinien być ciągiem z nazwą klucza, którą chcesz zaktualizować.

Jeśli to nie zadziała, Twój Nextick może być problemem. Tak jak w przypadku zamontowanego nie ma Nevertick, chyba że coś jest aktualizowane.

mounted() {
  this.$nextTick(function () {
    this.startMatter();
  })
}

Zaktualizowano na podstawie komentarzy.

Wierzę, że to ta linia (linia 108?), Która zastępuje twój this.

let colStart = Matter.Events.on(engine, 'collisionStart', function (event) {

Spróbuj zamiast tego: let colStart = Matter.Events.on(engine, 'collisionStart', (event) => {

Funkcja ma własny zakres / to. Zwykle wiąże się z nim, jednak myślę, że nie działa tak, jak jesteś w sprawach Callback teraz. Funkcja strzałki zapewnia, że zakres jest leksykalny.

To samo dotyczy: let colEnd = Matter.Events.on(engine, 'collisionEnd', function (event) {, Zmień go do: let colEnd = Matter.Events.on(engine, 'collisionEnd', (event) => {

1
Jens van Hellemondt 14 marzec 2021, 18:05