基于(可变)变量加载Vue组件



Vue.js的新手在这里,所以抱歉,如果我错过了一些明显的。

我想根据变量的内容加载组件——所以如果变量的内容改变了,我希望组件也相应改变。我导入了所有组件(例如import Project1 from "@/components/Project1";),再次保存在components: {'p1': Project1}

中。我用<component :is="this.goTo.page"/>转到。页面在数据中定义为data() {return {goTo: {page: "p1"}}}。问题似乎是goTo.page的反应性。我通过this.$set(this.goTo, "page", "p2");更新它。当运行时,我得到错误Uncaught TypeError: Cannot read property 'page' of undefined,我真的不理解,因为它初始化为"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>

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

this<template>中不可用。一切"inside"this,是可用的

除了以上内容,根据你的更新,

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

this的第二个参数。$set应该是一个字符串,包含你想要更新的键名。

如果这不起作用,你的nextTick可能是问题所在。例如,在挂载之后没有nextTick,除非更新了某些内容。

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

根据注释更新。

我相信是这一行(第108行?),它覆盖了你的this

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

试试相反:let colStart = Matter.Events.on(engine, 'collisionStart', (event) => {

函数有它自己的作用域/this。我们通常会绑定到它,但我认为这不起作用,因为你们现在在做回调。箭头函数确保作用域是词法的。

同样适用于:let colEnd = Matter.Events.on(engine, 'collisionEnd', function (event) {,更改为:let colEnd = Matter.Events.on(engine, 'collisionEnd', (event) => {

最新更新