You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Webpack+原生JavaScript操作DOM遇报错及架构疑问

Fixing the register is not defined Error + Implementing MVC with Webpack & Vanilla JS

Hey there! Let's tackle your issues one by one—first the error you're seeing, then how to implement a clean MVC-style architecture with your Webpack setup.

1. Fixing the Uncaught ReferenceError: register is not defined

The root cause here is Webpack's module scoping. By default, Webpack wraps your code in an isolated module context, so functions like register() don't get attached to the global window object. Your inline onclick="register()" tries to call a global function that doesn't exist.

Here are two solutions, with the second being more aligned with modern modular practices:

Option 1: Expose the function to the global scope

Modify your src/index.js to explicitly attach the function to window:

function register() { 
  alert('Hello') 
}

// Expose to global scope so inline onclick can find it
window.register = register;

Inline event handlers mix HTML and JS, which makes code harder to maintain. Instead, bind the event directly in your JS:

First, update your HTML to remove the inline onclick:

<div class="form-group"> 
  <label for="matri">Matri</label> 
  <input class="form-control col-12" type="text" placeholder="Enter your matri" id="matry">
</div> 
<div class="text-left mt-5" style="width: 100%;">
  <!-- Remove onclick attribute -->
  <button class="btn btn-primary" id="registerBtn" type="button">Register</button>
</div>

Then update src/index.js to bind the event:

function register() {
  alert('Hello')
}

// Wait for DOM to load before accessing elements
document.addEventListener('DOMContentLoaded', () => {
  const registerBtn = document.getElementById('registerBtn');
  registerBtn.addEventListener('click', register);
});

Using MVC with vanilla JS and Webpack is a great choice—it will make your code more organized, testable, and scalable. Webpack's modular system fits perfectly with MVC's separation of concerns.

Let's adjust your existing structure to follow MVC principles:

your-project/
├── src/
│   ├── models/          # Data & business logic
│   │   └── UserModel.js
│   ├── controllers/     # Mediates between Model and View
│   │   └── AuthController.js
│   ├── views/           # DOM interactions & UI rendering
│   │   └── AuthView.js
│   ├── styles/          # SCSS/CSS files
│   └── index.js         # Entry point
├── dist/
├── index.html
└── webpack.config.js

Example Code for Each Layer

Model Layer (src/models/UserModel.js)

Handles data validation, API calls, and data storage—no DOM interaction here:

export default class UserModel {
  // Validate registration input
  static validateMatri(matri) {
    if (!matri || matri.length < 3) {
      return 'Matri must be at least 3 characters long';
    }
    return null; // No error
  }

  // Simulate API registration call
  static async registerUser(matri) {
    // Replace with real API fetch logic
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve({ success: true, message: 'Registration successful!' });
      }, 1000);
    });
  }
}

View Layer (src/views/AuthView.js)

Handles all DOM interactions—renders UI, listens for user events, and updates the interface:

export default class AuthView {
  constructor() {
    this.registerBtn = document.getElementById('registerBtn');
    this.matriInput = document.getElementById('matry');
    this.errorElement = document.createElement('div');
    this.errorElement.className = 'text-danger mt-2';
    this.matriInput.parentNode.appendChild(this.errorElement);
  }

  // Get input value
  getMatriValue() {
    return this.matriInput.value.trim();
  }

  // Show error message
  showError(message) {
    this.errorElement.textContent = message;
  }

  // Clear error message
  clearError() {
    this.errorElement.textContent = '';
  }

  // Bind registration button click event
  bindRegister(handler) {
    this.registerBtn.addEventListener('click', handler);
  }

  // Show success message
  showSuccess(message) {
    alert(message); // Or replace with a nicer UI component
  }
}

Controller Layer (src/controllers/AuthController.js)

Acts as the middleman—connects the View and Model, handles business logic:

import UserModel from '../models/UserModel.js';
import AuthView from '../views/AuthView.js';

export default class AuthController {
  constructor() {
    this.view = new AuthView();
    this.model = UserModel;

    // Bind the register handler to the view
    this.view.bindRegister(this.handleRegister.bind(this));
  }

  async handleRegister() {
    this.view.clearError();
    const matri = this.view.getMatriValue();
    
    // Validate input via model
    const validationError = this.model.validateMatri(matri);
    if (validationError) {
      this.view.showError(validationError);
      return;
    }

    // Try to register via model
    try {
      const result = await this.model.registerUser(matri);
      this.view.showSuccess(result.message);
      this.matriInput.value = ''; // Clear input
    } catch (error) {
      this.view.showError('Registration failed. Please try again.');
    }
  }
}

Entry Point (src/index.js)

Initialize the controller to kick off the app:

import AuthController from './controllers/AuthController.js';
import './styles/main.scss'; // Import your styles here

// Wait for DOM to be fully loaded before initializing
document.addEventListener('DOMContentLoaded', () => {
  new AuthController();
});

3. Minor Webpack Config Tweaks (Optional)

  • In Webpack 4+, when mode: 'production', the UglifyJSPlugin is included by default—you can remove it from your plugins list to avoid redundancy.
  • Your output.filename can be simplified to bundle.js since path already points to dist:
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    }
    

内容的提问来源于stack exchange,提问作者Thiago Cunha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:33:25