组件化拆分(三)-Todos案例——单页面-详细代码

Todos案例-单页面-详细代码

src/views/Todos.js

/*
  Todos的模板
*/
import React from 'react'
import 'todomvc-common/base.css'
import 'todomvc-app-css/index.css'

class Todos extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      isAll: false,
      currentType: 'all',
      etitle: '',
      todos: [{
        id: 1,
        etitle: '写代码',
        done: false,
        isEdit: false
      }, {
        id: 2,
        etitle: '去K歌',
        done: true,
        isEdit: false
      }]
    }
    this.titleRef = React.createRef()
  }
  componentDidMount () {
    // 自己实现光标定位,也可以使用标准的autoFocus属性实现
    this.titleRef.current.focus()
  }
  handleEtitle = (e) => {
    this.setState({
      etitle: e.target.value
    })
  }
  handleEditEtile = (id, e) => {
    // 控制数组中对应标题的变化
    let todos = [...this.state.todos]
    todos.some(item => {
      if (item.id === id) {
        // 把最新的输入内容进行更新
        item.etitle = e.target.value
        return true
      } 
      return false
    })
    this.setState({
      todos: todos
    })
  }
  handleKeyup = (e) => {
    // 回车键的数字标识是13
    if (e.keyCode === 13) {
      // 按了回车键:添加任务
      let ids = this.state.todos.map(item => {
        return item.id
      })
      let maxId = Math.max.apply(null, ids) + 1
      let todo = {
        id: maxId,
        etitle: this.state.etitle,
        done: false
      }
      // let todos = [...this.state.todos]
      // todos.push(todo)
      this.setState({
        todos: [...this.state.todos, todo],
        etitle: ''
      })
    }
  }

  handleDelete = (id) => {
    // 控制删除操作
    let todos = [...this.state.todos]
    // 查找要删除的数据索引
    let index = todos.findIndex(item => {
      return item.id === id
    })
    // 根据索引删除数组的元素
    todos.splice(index, 1)
    this.setState({
      todos: todos
    })
  }

  handleCheck = (id) => {
    // 点击每个条目的时候,需要把数据中的done属性进行取反
    let todos = [...this.state.todos]
    todos.some(item => {
      if (item.id === id) {
        // 找到后把对应done状态取反
        item.done = !item.done
        // 终止继续遍历
        return true
      }
      return false
    })
    this.setState({
      todos: todos
    })
  }

  handleCheckAll = () => {
    this.setState({
      isAll: !this.state.isAll
    }, () => {
      // 控制所有的列表的选中状态
      let todos = [...this.state.todos]
      todos.forEach(item => {
        item.done = this.state.isAll
      })
      this.setState({
        todos: todos
      })
    })
  }

  // handleBlue = (id) => {
  //   // 编辑状态失去焦点触发
  //   let todos = [...this.state.todos]
  //   todos.some(item => {
  //     if (item.id === id) {
  //       // 找到后把对应done状态取反
  //       item.isEdit = !item.isEdit
  //       // 终止继续遍历
  //       return true
  //     }
  //     return false
  //   })
  //   this.setState({
  //     todos: todos
  //   })
  // }

  handleDoubleClick = (id, e) => {
    // let input = e.target.parentNode.parentNode.children[1]
    // 获取label元素的父元素的下一个兄弟元素 input
    let input = e.target.parentNode.nextSibling
    // e.persist()
    setTimeout(() => {
      // 页面已经显示input元素之后才控制获取焦点
      input&&input.focus()
    }, 0)
    // 双击进入编辑状态;或者失去焦点是,取消编辑状态
    let todos = [...this.state.todos]
    todos.some(item => {
      if (item.id === id) {
        // 找到后把对应isEdit状态取反
        item.isEdit = !item.isEdit
        // 终止继续遍历
        return true
      }
      return false
    })
    this.setState({
      todos: todos
    })
  }

  handleCount = () => {
    // 计算剩余的没有完成的任务数量
    let num = 0
    this.state.todos.forEach(item => {
      if (!item.done) {
        // 没有完成的任务
        num += 1
      }
    })
    return num
  }

  handleFilter = (e) => {
    // 更新当前的筛选条件
    let id = e.target.dataset.id
    if (!id) {
      // 没有id,什么都不做
      return 
    }
    this.setState({
      currentType: id
    })
  }

  handleFilterData = () => {
    let { todos, currentType } = this.state
    return todos.filter(item => {
      if (currentType === 'all') {
        // 全部列表
        return true
      } else if (currentType === 'will' && !item.done) {
        // 未完成
        return true
      } else if (currentType === 'done' && item.done) {
        return true
      } else {
        return false
      }
    })
  }

  handleClearAll = () => {
    // 清除所有的已完成任务
    let todos = this.state.todos.filter(item => {
      return !item.done
    })
    this.setState({
      todos: todos
    })
  }

  render () {
    let { todos, etitle, isAll, currentType } = this.state
    // 根据当前筛选条件,过滤出列表数据
    todos = this.handleFilterData()

    let todoTags = todos.map(item => (
      <li key={item.id} className={[item.done?'completed':'', item.isEdit? 'editing': ''].join(' ')}>
        <div className="view" onDoubleClick={this.handleDoubleClick.bind(this, item.id)}>
          <input checked={item.done} onChange={this.handleCheck.bind(this, item.id)} className="toggle" type="checkbox"/>
          <label>{item.etitle}</label>
          <button className="destroy" onClick={this.handleDelete.bind(this, item.id)}></button>
        </div>
        <input value={item.etitle} onChange={this.handleEditEtile.bind(this, item.id)} onBlur={this.handleDoubleClick.bind(this,item.id)} className="edit" />
      </li>
    ))
    return (
      <div>
        <section className="todoapp">
          <header className="header">
            <h1>土豆丝</h1>
            <input ref={this.titleRef} onKeyUp={this.handleKeyup} value={etitle} onChange={this.handleEtitle} className="new-todo" placeholder="你想做什么?" />
          </header>
          <section className="main">
            <input defaultChecked={isAll} id="toggle-all" className="toggle-all" type="checkbox"/>
            <label onClick={this.handleCheckAll} htmlFor="toggle-all">全部标记为完成</label>
            <ul className="todo-list">
              {todoTags}
            </ul>
          </section>
          <footer className="footer">
            <span className="todo-count">剩余<strong>{this.handleCount()}</strong>个任务</span>
            <ul onClick={this.handleFilter} className="filters">
              <li>
                <a data-id='all' className={currentType==='all'?'selected': ''} href="#/">全选</a>
              </li>
              <li>
                <a data-id='will' className={currentType==='will'?'selected': ''}  href="#/active">未完成</a>
              </li>
              <li>
                <a data-id='done' className={currentType==='done'?'selected': ''}  href="#/completed">已完成</a>
              </li>
            </ul>
            <button onClick={this.handleClearAll} className="clear-completed">清除所有已完成任务</button>
          </footer>
        </section>
        <footer className="info">
          <p>Double-click to edit a todo</p>
          <p>Template by <a href="http://sindresorhus.com">Sindre Sorhus</a></p>
          <p>Created by <a href="http://todomvc.com">you</a></p>
          <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
        </footer>
      </div>
    )
  }
}

export default Todos

你可能感兴趣的:(redux,定位,checkbox,reactjs)