从JavaScript中的另一个类调用类方法?

时间:2019-05-11 15:08:38

标签: javascript

我正在执行一项任务,需要将搜索字段连接到一个简单的JS应用程序,该应用程序显示一些项目,用户可以搜索并过滤它们。

共有三类-App,ProductsPanel和Search。 Search和ProductsPanel都在App类内部进行了初始化。

ProductsPanel类包含一个包含10个产品的数组。

我想从Search内部调用ProductsPanel的方法来过滤产品。我怎样才能做到这一点?

我尝试在第一个类的构造函数中使用this.productsPanel = new productsPanel(),但这会带来一个没有所有产品数组的新实例。

这是App类:

class App {
  constructor() {
    this.modules = {
      search: {
        type: Search,
        instance: null
      },
      filter: {
        type: Filter,
        instance: null
      },
      productsPanel: {
        type: ProductsPanel,
        instance: null
      },
      shoppingCart: {
        type: ShoppingCart,
        instance: null
      }
    };
  }

  init() {
    const placeholders = document.querySelectorAll("#root [data-module]");
    for (let i = 0; i < placeholders.length; i++) {
      const root = placeholders[i];
      const id = root.dataset.module;
      const module = this.modules[id];
      if (module.instance) {
        throw new Error(`module ${id} has already been started`);
      }
      module.instance = new module.type(root);
      module.instance.init();
      // console.info(`${id} is running...`);
    }
  }
}

app = new App();
app.init();

这是搜索:

export default class Search {
  constructor(root) {
    this.input = root.querySelector("#search-input");
  }

  // addEventListener is an anonymous function that encapsulates code that sends paramaters to handleSearch() which actually handles the event
  init() {
    this.input.addEventListener("input", () => {
      this.handleSearch();
    });
  }

  handleSearch() {
    const query = this.input.value;
    app.modules.productsPanel.instance.performSearch(query);
  }
}

和ProductsPanel类:

export default class ProductsPanel {
  constructor(root) {
    this.view = new ProductsPanelView(root, this);
    this.products = [];
  }

  init() {
    this.products = new ProductsService().products;
    this.products.forEach(x => this.view.addProduct(x));
  }

  performSearch(query) {
    query = query.toLowerCase();

    this.products.forEach(p => {
      if (query === p.name) {
        this.view.showProduct(p.id);
      } else {
        this.view.hideProduct(p.id);
      }
    });
  }

  addToCart(id) {
    const product = this.products.filter(p => p.id === id)[0];
    if (product) {
      app.modules.shoppingCart.instance.addProduct(product);
    }
  }
}

我想在由App类创建的实例上调用ProductsPanel的performSearch方法。我不知道该怎么做。

1 个答案:

答案 0 :(得分:0)

尝试下面的自定义事件处理程序类

class CustomEventEmitter {
  constructor() {
    this.eventsObj = {};
  }

  emit(eName, data) {
    const event = this.eventsObj[eName];
    if( event ) {
      event.forEach(fn => {
        fn.call(null, data);
      });
    }
  }

  subscribe(eName, fn) {
    if(!this.eventsObj[eName]) {
      this.eventsObj[eName] = [];
    }

    this.eventsObj[eName].push(fn);
    return () => {
      this.eventsObj[eName] = this.events[eName].filter(eventFn => fn !== eventFn);
    }
  }


}

如何使用?

创建CustomEventEmitter类的对象

let eventEmitter = new CustomEventEmitter()

订阅活动

emitter.subscribe('event: do-action', data => {
  console.log(data.message);
});

致电事件

emitter.emit('event: do-action',{message: 'My Custom Event handling'});

希望这会有所帮助!