用组件纯javascript做列表任务

时间:2018-03-06 08:55:27

标签: javascript components

有一个待办事项列表任务。 有三个组成部分。 class TodoAppComponent,类TodoFormComponent和类TodoListComponent。 请在TodoListComponent中检查我的doneTask()。 当我添加一个任务时,我需要在复选框状态变为“检查”时越过该行。 它似乎无法正常工作,但控制台没有显示任何错误



class TodoAppComponent {
  constructor(mountPoint, props = {}) {
    this.mountPoint = mountPoint;
    this.props = props;
  }

  querySelectors() {
    this.todoFormMountPoint = this.mountPoint.querySelector(
      ".todo-app__form-point"
    );
    this.todoListMountPoint = this.mountPoint.querySelector(
      ".todo-app__list-point"
    );
  }

  mountChildren() {
    this.todoFormComponent = new TodoFormComponent(this.todoFormMountPoint, {
      onTodoAdd: this.handleTodoAdd.bind(this)
    });
    this.todoFormComponent.mount();
    this.todoListComponent = new TodoListComponent(this.todoListMountPoint);
    this.todoListComponent.mount();
  }

  handleTodoAdd(task) {
    this.todoListComponent.addTask(task);
    const numItems = this.todoListComponent.getNumTasks();
    this.todoFormComponent.setCounter(numItems + 1);
  }

  mount() {
    this.mountPoint.innerHTML = this.render();
    this.querySelectors();
    this.mountChildren();
  }

  render() {
    return `
      <div class="todo-app">
        <h2>Todo:</h2>
        <div class="todo-app__form-point"></div>
        <div class="todo-app__list-point"></div>
      </div>
    `;
  }
}

class TodoFormComponent {
  constructor(mountPoint, props = {}) {
    this.mountPoint = mountPoint;
    this.props = props;
  }

  querySelectors() {
    this.field = this.mountPoint.querySelector(".todo-form__field");
    this.btn = this.mountPoint.querySelector(".todo-form__btn");
    this.counter = this.mountPoint.querySelector(".todo-form__counter");
  }

  addEventListeners() {
    this.btn.addEventListener("click", this.handeBtnClick.bind(this));
  }

  handeBtnClick() {
    this.props.onTodoAdd(this.field.value);
    this.field.value = "";
  }

  mount() {
    this.mountPoint.innerHTML = this.render();
    this.querySelectors();
    this.addEventListeners();
  }

  setCounter(val) {
    this.counter.innerHTML = val;
  }

  render() {
    return `
      <div class="todo-form">
        <input class="todo-form__field" type="text">
        <button class="todo-form__btn">
          Add #<span class="todo-form__counter">1</span>
        </button>
      </div>
    `;
  }
}

class TodoListComponent {
  constructor(mountPoint, props = {}) {
    this.mountPoint = mountPoint;
    this.props = props;
  }

  querySelectors() {
    this.list = this.mountPoint.querySelector(".todo-list");
  }

  mount() {
    this.mountPoint.innerHTML = this.render();
    this.querySelectors();
    this.doneTask();
  }

  addTask(task) {
    this.list.innerHTML += `
    <tr><td><input class ="checkbox" type="checkbox"></td>
    <td>${task}</td>
    <td><button value="&#215" style="width:5px;height:15px;"></button></td></tr>
        `;
  }

  doneTask() {
    let checkboxElements = document.getElementsByClassName("checkbox");

    for (let i = 0; i < checkboxElements.length; i++) {
      checkboxElements[i].addEventListener("change", function() {
        if (this.checked) {
          this.closest("tr").style.textDecoration = "line-through";
        }
      });
    }
  }
  getNumTasks() {
    return this.list.children.length;
  }

  render() {
    return `
      <br>
      <table class="todo-list" style="width:50px"></table>
    `;
  }
}

const root = document.querySelector("#root");

const cmp = new TodoAppComponent(root);

cmp.mount();
&#13;
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="root"></div>
  
</body>
</html>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

&#13;
&#13;
class TodoAppComponent {
  constructor(mountPoint, props = {}) {
    this.mountPoint = mountPoint;
    this.props = props;
  }

  querySelectors() {
    this.todoFormMountPoint = this.mountPoint.querySelector(
      ".todo-app__form-point"
    );
    this.todoListMountPoint = this.mountPoint.querySelector(
      ".todo-app__list-point"
    );
  }

  mountChildren() {
    this.todoFormComponent = new TodoFormComponent(this.todoFormMountPoint, {
      onTodoAdd: this.handleTodoAdd.bind(this)
    });
    this.todoFormComponent.mount();
    this.todoListComponent = new TodoListComponent(this.todoListMountPoint);
    this.todoListComponent.mount();
  }

  handleTodoAdd(task) {
    this.todoListComponent.addTask(task);
    const numItems = this.todoListComponent.getNumTasks();
    this.todoFormComponent.setCounter(numItems + 1);
  }

  mount() {
    this.mountPoint.innerHTML = this.render();
    this.querySelectors();
    this.mountChildren();
  }

  render() {
    return `
      <div class="todo-app">
        <h2>Todo:</h2>
        <div class="todo-app__form-point"></div>
        <div class="todo-app__list-point"></div>
      </div>
    `;
  }
}

class TodoFormComponent {
  constructor(mountPoint, props = {}) {
    this.mountPoint = mountPoint;
    this.props = props;
  }

  querySelectors() {
    this.field = this.mountPoint.querySelector(".todo-form__field");
    this.btn = this.mountPoint.querySelector(".todo-form__btn");
    this.counter = this.mountPoint.querySelector(".todo-form__counter");
  }

  addEventListeners() {
    this.btn.addEventListener("click", this.handeBtnClick.bind(this));
  }

  handeBtnClick() {
    this.props.onTodoAdd(this.field.value);
    this.field.value = "";
  }

  mount() {
    this.mountPoint.innerHTML = this.render();
    this.querySelectors();
    this.addEventListeners();
  }

  setCounter(val) {
    this.counter.innerHTML = val;
  }

  render() {
    return `
      <div class="todo-form">
        <input class="todo-form__field" type="text">
        <button class="todo-form__btn">
          Add #<span class="todo-form__counter">1</span>
        </button>
      </div>
    `;
  }
}

class TodoListComponent {
  constructor(mountPoint, props = {}) {
    this.mountPoint = mountPoint;
    this.props = props;
  }

  querySelectors() {
    this.list = this.mountPoint.querySelector(".todo-list");
  }

  mount() {
    this.mountPoint.innerHTML = this.render();
    this.querySelectors();
    this.doneTask();
  }

  addTask(task) {
    this.list.innerHTML += `
    <tr><td><input class ="checkbox" type="checkbox"></td>
    <td>${task}</td>
    <td><button value="&#215" style="width:5px;height:15px;"></button></td></tr>
        `;
        
     this.doneTask();
  }

  doneTask() {
    let checkboxElements = document.getElementsByClassName("checkbox");

    for (let i = 0; i < checkboxElements.length; i++) {
      checkboxElements[i].addEventListener("change", function() {
        if (this.checked) {
          this.closest("tr").style.textDecoration = "line-through";
        }
      });
    }
  }
  getNumTasks() {
    return this.list.children.length;
  }

  render() {
    return `
      <br>
      <table class="todo-list" style="width:50px"></table>
    `;
  }
}

const root = document.querySelector("#root");

const cmp = new TodoAppComponent(root);

cmp.mount();
&#13;
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="root"></div>
  
</body>
</html>
&#13;
&#13;
&#13;

因为您的函数doneTask()未被调用,这就是样式未更新的原因。试试这个。 我刚刚在doneTask()中致电addTask()

希望这会有所帮助!!

答案 1 :(得分:0)

方法doneTask()在页面初始化时只运行一次,以添加侦听器。此时实际上没有元素,因此没有添加任何监听器。

相反,尝试为添加到DOM的每个元素添加一个侦听器(因此doneTask()是多余的):

  addTask(task) {
    this.list.innerHTML += `
    <tr><td><input class ="checkbox" type="checkbox"></td>
    <td>${task}</td>
    <td><button value="&#215" style="width:5px;height:15px;"></button></td></tr>
        `;

    // Actually add the listener
    this.list.lastChild.firstChild.firstChild.firstChild.addEventListener("change", function() {
      if (this.checked) {
        this.closest("tr").style.textDecoration = "line-through";
      }
    });

  }