搜尋

首頁  >  問答  >  主體

Vue專案 - 一個自訂js腳本出現的Uncaught TypeError: Cannot read properties of null (reading 'offsetWidth')錯誤

所以我將自訂 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 檔案。

Demo3.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.addEventList ener("mousemove", onMouseMove);
var resizeTm;
window.addEventList ener("resize", function () {
  resizeTm = clearTimeout(resizeTm);
  resizeTm = setTimeout(onResize, 200);
});

所以,我的應用程式根本無法載入。現在我不知道如何解決這個問題。這是我第一次將 html 模板轉換為 vuejs。我不知道會發生什麼事。 文件結構截圖 (https://i.stack.imgur.com/dKzTb.png)

console.log 中錯誤詳細資訊的螢幕截圖 (https://i.stack.imgur.com/9Rzap.png)

P粉447785031P粉447785031376 天前620

全部回覆(1)我來回復

  • P粉920485285

    P粉9204852852023-12-14 09:31:33

    您將在應用程式呈現 DOM 之前匯入 demo3.js 檔案(並執行它)。因此元素 #scene 尚不存在,導致為 null

    幾種解決方案:

    1. 您可以在 mounted 掛鉤後動態匯入 demo3.js 檔案:
    mounted() {
      import('../assets/assets/js/demo3.js') // dynamic import
    }
    
    1. 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()
      }
    }
    
    1. 您將 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,
        });
        // [...]
      }
    }
    

    回覆
    0
  • 取消回覆