【问题标题】:Why can't I reach the method outside the class?为什么我无法达到课外的方法?
【发布时间】:2021-06-08 14:36:00
【问题描述】:

我正在努力解决以下问题: 我必须基本上只使用 JS 来创建按钮。

//btn add
let button_add = document.createElement("button");
let button_add_class = button_add.className = "btn-add";
let button_add_click = button_add.setAttribute("onclick", "addBookToShoppingCart(first)");
let buttonText1 = document.createTextNode("Add to Shopping Cart");
button_add.appendChild(buttonText1);
this.mainBookScreen.appendChild(button_add);

按钮需要调用addBookToShoppingCart(first)方法,该方法在ShoppingCart类中。

class ShoppingCart{
   addBookToShoppingCart(bookObject) {
         alert('Hello World!');
   }
}

如果我点击按钮,我会在浏览器的控制台中收到以下错误消息:

未捕获的 ReferenceError:未定义 addBookToShoppingCart
在 HTMLButtonElement.onclick

编辑: 我的最新代码在这里:

class ShoppingCart{
    addBookToShoppingCart(bookObject) {
        alert('Hello World!');
    }
}

class Shop {
    constructor() {
        this.shoppingCart = new ShoppingCart("Shopping Cart");
        this.mainBookScreen = document.getElementById("mainBookScreen");
    }
    addBookToScreen(book) {
    //btn add
        const button_add = document.createElement("button");
        button_add.classList.add("btn-add");
        button_add.textContent = "Add to Shopping Cart";
        button_add.addEventListener("click", function(){this.shoppingCart.addBookToShoppingCart(first)});
        this.mainBookScreen.appendChild(button_add);
    }
}

class Book {
    //book constructors
}

let first = "TEST";
let book = [];
book[0] = new Book("bla1", "bla2", "bla3");
boook[1] = new Book("ble1", "ble2", "ble3");

const shop = new Shop();

shop.addBookToScreen(book[0]);
shop.addBookToScreen(book[1]);

如果我点击按钮,浏览器中的错误消息:

无法读取未定义的属性“addBookToShoppingCart” 在 HTMLButtonElement。

【问题讨论】:

标签: javascript oop dom-events


【解决方案1】:

你遇到了一些问题。

首先,不要使用诸如onclick 之类的DOM 属性设置事件。虽然这可行,但它是一种更过时的方法,不符合使用.addEventListener() 的 DOM 事件处理标准。

接下来,当你只是设置一个对象的属性时,不应该设置变量——你可以只设置属性。

而且,至于调用你的方法,你需要先创建你的类的实例,然后才能使用它,当你这样做时,你必须在该实例的上下文中调用属性和方法。

class ShoppingCart{
   addBookToShoppingCart(bookObject) {
         alert('Hello World!');
   }
}

// Make an instance of the class:
let cart = new ShoppingCart();

let first = "TEST";

const button_add = document.createElement("button");

// You don't need variables to simply set properties:
button_add.classList.add("btn-add");
button_add.textContent = "Add to Shopping Cart";

// Use .addEventListener() to set up events, but the second argument takes
// a function reference, so your function invocation needs to be wrapped in 
// a reference, but within the invocation, you must call the function as
// a method of an instance of the class.
button_add.addEventListener("click", function(){cart.addBookToShoppingCart(first)});

document.body.appendChild(button_add);

根据您的编辑,问题在于在 DOM 事件中 this 将引用触发事件的 DOM 对象,而不是代码所属的类实例。这是因为为事件处理代码创建的闭包。如果将this替换为实例名,代码如下:

class ShoppingCart{
    addBookToShoppingCart(bookObject) {
        alert('Hello World!');
    }
}

class Shop {
    constructor() {
        this.shoppingCart = new ShoppingCart("Shopping Cart");
        this.mainBookScreen = document.getElementById("mainBookScreen");
    }
    addBookToScreen(book) {
    //btn add
        const button_add = document.createElement("button");
        button_add.classList.add("btn-add");
        button_add.textContent = "Add to Shopping Cart";
        button_add.addEventListener("click", function(){
          // Can't use "this" to refer to the instance of the class
          // within a DOM event handler. Instead, refer to the instance
          // variable.
          shop.shoppingCart.addBookToShoppingCart(first);
        });
        this.mainBookScreen.appendChild(button_add);
    }
}

class Book {
    //book constructors
}

let first = "TEST";
let book = [];
book[0] = new Book("bla1", "bla2", "bla3");
book[1] = new Book("ble1", "ble2", "ble3");

const shop = new Shop();

shop.addBookToScreen(book[0]);
shop.addBookToScreen(book[1]);
<div id="mainBookScreen"></div>

【讨论】:

  • 谢谢!你帮了我很多。如果我有两节课怎么办。在这种情况下ShoppingCartShop。我在 Shop 类的构造函数中创建了一个新的 ShoppingCart 实例。除了构造函数之外,还有一个addBookToScreen(book) 方法。我在这里粘贴了您关于button_add 声明和.addEventListener() 的代码,方式与您解释的相同。 first 变量声明在类之外。如果我单击按钮,则会出现错误消息:“shoppingCart.addBookToShoppingCart 不是 HTMLButtonElement 的函数。”我错了什么?
  • ...我找到了以前的主题link,正如您在评分最高的答案(非静态)案例中看到的那样。
  • @MartinB 我们需要查看您的最新代码。您应该编辑您的问题并附加您现在拥有的内容。
  • @ScottMarkus 已编辑并添加了最新代码。谢谢!
  • @MartinB 查看我更新的答案,不要忘记通过单击答案顶部左侧的复选标记将答案标记为“该”答案。
【解决方案2】:

JS 中的 Class 有自己的作用域。换句话说,函数addBookToShoppingCart在全局范围内是不可用的,这意味着你不能在不创建类的对象的情况下访问它。下面是一个如何访问类内部函数的例子

class Dog {
  function bark() {}
} 

var dog = new Dog();
dog.bark()

请阅读 JS 中的 scopesclass 了解更多详情。

【讨论】:

    【解决方案3】:

    我看到 2 个问题,其中一个是名为 boook 的变量,未定义。

    另一个问题是addEventListener函数,this引用了按钮,就像调用Element.shoppingCart.addBookToShoppingCart(first)一样。

    为了修复它,保存一个带有 this 引用的变量并使用它,我会给你一个完整的例子:

    
    $(function(){
    
        class ShoppingCart{
            
            addBookToShoppingCart(bookObject) {
                alert('Hello World!');
            }
            
        }
    
        class Shop {
            constructor() {
                this.shoppingCart = new ShoppingCart();
                this.mainBookScreen = document.getElementById("mainBookScreen");
            }
            addBookToScreen(book){
            //btn add
                const button_add = document.createElement("button");
                button_add.classList.add("btn-add");
                button_add.textContent = "Add to Shopping Cart";
                
                let classhere = this;
                
                button_add.addEventListener("click", function(){
                    
                    //this -> button element..
                    
                    classhere.shoppingCart.addBookToShoppingCart(first);
                    
                });
                
                this.mainBookScreen.appendChild(button_add);
            }
        }
    
        class Book {
            //book constructors
        }
    
        let first = "TEST";
        let book = [];
        book[0] = new Book("bla1", "bla2", "bla3");
        book[1] = new Book("ble1", "ble2", "ble3");
    
        const shop = new Shop();
    
        shop.addBookToScreen(book[0]);
        shop.addBookToScreen(book[1]);
    
    });
    

    【讨论】:

      猜你喜欢
      • 2017-08-16
      • 1970-01-01
      • 2013-11-30
      • 1970-01-01
      • 2013-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多