поэтому я конвертирую собственный HTML-шаблон в проект vuejs. Я импортировал все файлы css и js для использования на моей домашней странице. Файлы css загружаются нормально. Для файлов JS тема поставляется с несколькими пользовательскими сценариями js вместе с обычными библиотеками, такими как three.js и т. д. Я импортирую их все ниже моего HomeComponent в теге скрипта. Но я сталкиваюсь с этой ошибкой:
"Uncaught TypeError: Cannot read properties of null (reading 'offsetWidth')
at eval (demo3.js?dad6:2:20)
at ./src/assets/assets/js/demo3.js (app.js:92:1)
at __webpack_require__ (app.js:1124:33)
at fn (app.js:1357:21)
at eval (index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HomeComponent.vue?vue&type=script&lang=js:26:85)
at ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HomeComponent.vue?vue&type=script&lang=js (app.js:30:1)
at __webpack_require__ (app.js:1124:33)
at fn (app.js:1357:21)
at eval (HomeComponent.vue?vue&type=script&lang=js:5:216)
at ./src/components/HomeComponent.vue?vue&type=script&lang=js (app.js:296:1)"
Ниже приведен мой код App.vue:
<template>
<router-view />
</template>
<script>
export default {
name: "App",
components: {},
};
</script>
Ниже приведен мой код homecomponent.vue (частично — некоторый код скрыт внутри шаблона):
<template>
<header class = "offcanvas-menu">
<input type = "checkbox" id = "toogle-menu" />
<label for = "toogle-menu" class = "toogle-open"><span></span></label>
<nav>
<div>
<label for = "toogle-menu" class = "toogle-close">
<span></span>
</label>
</div>
<ul>
<li><a href = "#section1">Section </a></li>
<li><a href = "#section2">Section </a></li>
<li><a href = "#section3">Section </a></li>
<li><a href = "#section4">Section </a></li>
<li><a href = "#section5">Section </a></li>
</ul>
</nav>
</header>
<main>
<div class = "content">
<canvas class = "scene scene--full" id = "scene"></canvas>
<div class = "content__inner">
<h2 class = "content__title">مؤشر المعلوماتية</h2>
<div class = "content-button mt-2">
<button
type = "button"
class = "btn btn-relief-primary btn-large menu-trigger display-5"
>
<i data-feather = "menu"></i> القائمة
</button>
</div>
</div>
</div>
<nav class = "grim">
<div class = "grim__item">
<div class = "grim__item-bg grim__item-bg--5"></div>
</div>
<div class = "grim__item">
<div class = "grim__item-bg grim__item-bg--5"></div>
</div>
<div class = "grim__item">
<div class = "grim__item-bg grim__item-bg--5"></div>
<div class = "grim__item-content">
<div class = "grim__item-inner"></div>
</div>
</div>
..
<div class = "grim__item">
<div class = "grim__item-bg grim__item-bg--9"></div>
<div class = "grim__item-img grim__item-img--4"></div>
<a href = "dashboard-region.html" class = "grim__link grim__item-content">
<div class = "grim__item-inner">
<h3 class = "grim__item-title">test</h3>
<span class = "grim__item-desc">test</span>
</div>
</a>
<div class = "grim__item-bg grim__item-bg-cover grim__item-bg--9"></div>
</div>
<div class = "grim__item">
<div class = "grim__item-bg grim__item-bg--10"></div>
<div class = "grim__item-img grim__item-img--5" style = ""></div>
<a href = "wizard.html" class = "grim__link grim__item-content">
<div class = "grim__item-inner">
<h3 class = "grim__item-title">test</h3>
<span class = "grim__item-desc"
>test</span
>
</div>
</a>
<div class = "grim__item-bg grim__item-bg-cover grim__item-bg--10"></div>
</div>
</nav>
</main>
<!-- home -->
</template>
<style>
@import url("https://fonts.googleapis.com/css?family=Barlow:400,500,700|Poppins:600");
@import url("https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,300;0,400;0,500;0,600;1,400;1,500;1,600");
</style>
<script>
//All css files
import "../assets/assets/css/base.css";
import "../assets/app-assets/css-rtl/bootstrap.css";
import "../assets/app-assets/css-rtl/bootstrap-extended.css";
import "../assets/app-assets/css-rtl/colors.css";
import "../assets/app-assets/css-rtl/themes/dark-layout.css";
import "../assets/assets/css/menu.css";
import "../assets/app-assets/css-rtl/custom-rtl.css";
import "../assets/assets/css/style-rtl.css";
export default {
name: "HomeComponent",
};
//All JS files
import "../assets/assets/js/demo.js";
import "../assets/assets/js/three.min.js";
import "../assets/assets/js/perlin.js";
import "../assets/assets/js/TweenMax.min.js";
import "../assets/assets/js/demo3.js";
import "../assets/assets/js/grid.js";
import "../assets/assets/js/imagesloaded.pkgd.min.js";
import "../assets/assets/js/anime.min.js";
import "../assets/assets/js/menu2.js";
</script>
Проблема связана с файлом demo3.js.
Демо3.js
var canvas = document.querySelector("#scene");
var width = canvas.offsetWidth,
height = canvas.offsetHeight;
var renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true,
});
renderer.setPixelRatio(window.devicePixelRatio > 1 ? 2 : 1);
renderer.setSize(width, height);
renderer.setClearColor(0x161d31);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(100, width / height, 0.1, 10000);
camera.position.set(120, 0, 300);
var light = new THREE.HemisphereLight(0xffffff, 0x0c056d, 0.6);
scene.add(light);
var light = new THREE.DirectionalLight(0x590d82, 0.5);
light.position.set(100, 300, 400);
scene.add(light);
var light2 = light.clone();
light2.position.set(-100, 300, 400);
scene.add(light2);
var geometry = new THREE.IcosahedronGeometry(120, 4);
for (var i = 0; i < geometry.vertices.length; i++) {
var vector = geometry.vertices[i];
vector._o = vector.clone();
}
var material = new THREE.MeshPhongMaterial({
emissive: 0x23f660,
emissiveIntensity: 0.4,
shininess: 0,
});
var shape = new THREE.Mesh(geometry, material);
scene.add(shape);
function updateVertices(a) {
for (var i = 0; i < geometry.vertices.length; i++) {
var vector = geometry.vertices[i];
vector.copy(vector._o);
var perlin = noise.simplex3(
vector.x * 0.006 + a * 0.0002,
vector.y * 0.006 + a * 0.0003,
vector.z * 0.006
);
var ratio = perlin * 0.4 * (mouse.y + 0.3) + 0.9;
vector.multiplyScalar(ratio);
}
geometry.verticesNeedUpdate = true;
}
function render(a) {
requestAnimationFrame(render);
updateVertices(a);
renderer.render(scene, camera);
}
function onResize() {
canvas.style.width = "";
canvas.style.height = "";
width = canvas.offsetWidth;
height = canvas.offsetHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
var mouse = new THREE.Vector2(0.8, 0.5);
function onMouseMove(e) {
TweenMax.to(mouse, 0.8, {
y: e.clientY / height,
x: e.clientX / width,
ease: Power1.easeOut,
});
}
requestAnimationFrame(render);
window.addEventListener("mousemove", onMouseMove);
var resizeTm;
window.addEventListener("resize", function () {
resizeTm = clearTimeout(resizeTm);
resizeTm = setTimeout(onResize, 200);
});
Итак, мое приложение вообще не загружается. теперь я потерял, как это решить. Это мой первый опыт преобразования html-шаблона в vuejs. Хз чего ожидать. Скриншот файловой структуры (https://i.stack.imgur.com/dKzTb.png)
скриншот сведений об ошибке в console.info (https://i.stack.imgur.com/9Rzap.png)
@ Legit007, как это исправить? Я понимаю, что это так, я должен как-то смонтировать дом до загрузки js, но не знаю, как
Может быть, вы можете попробовать использовать асинхронный смонтированный экспорт по умолчанию: lavalite.org/blog/created-and-mountedin-vuejs и вызвать свой js в смонтированном блоке
не сработало :( @Legit007
Итак, вы вызвали свою js-функцию в смонтированной функции и все еще получаете null с помощью document.querySelector("#scene")? Вам нужно добавить смонтированную функцию в homecomponent.vue. Вам не следует импортировать 'import "../assets/assets/js/demo3.js"; вам нужно импортировать функцию. Like -> import {yourFunction} из "demo3.js";
Вы импортируете свой файл demo3.js
(и, следовательно, выполняете его) до того, как приложение отобразит DOM. Итак, элемент #scene
еще не существует, в результате получается null
.
Несколько решений для этого:
demo3.js
после хука mounted
:mounted() {
import('../assets/assets/js/demo3.js') // dynamic import
}
demo3.js
в функцию и экспортируете его.// demo3.js
export function renderScene() {
var canvas = document.querySelector("#scene");
var width = canvas.offsetWidth,
height = canvas.offsetHeight;
// [...]
}
import { renderScene } from '../assets/assets/js/demo3.js'
export default {
mounted() {
renderScene()
}
}
demo3.js
в компонент vue и используете ссылки на шаблоны.mounted() {
const scene = this.$refs.scene
if (scene) {
const width = canvas.offsetWidth,
height = canvas.offsetHeight;
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true,
});
// [...]
}
}
В demo3.js эта строка дает вам нулевой объект var canvas = document.querySelector("#scene"); Итак, ваш холст = null, и вы не можете получить доступ к offsetWidth