我的第一个react项目 TodoList

332 阅读3分钟

先看下效果图 项目地址:git.coding.net/Weishengyan…

效果图 环境准备:

安装node ,去官网下载安装,安装完自带npm包管理工具

使用到css工具:bulma、scss

友情链接bulma中文翻译:lqzh.me/bulma-docs-…

创建项目

npx create-react-app my-app

(npx 是一个帮你执行文件的工具,会自动查找当前依赖包中的可执行文件,如果找不到,就会去 PATH 里找。如果依然找不到,就会帮你安装!)

cd my-app

npm start

这个时候项目运行起来啦!

因为要用到bulma、scss,在项目目录下安装bulma、scss


npm install bulma node-sass  --save

在项目public目录下的index.html文件中引入bulma的css

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css"></link>

清空src目录,然后建一个TodoList文件夹、index.js文件 index.js文件内容为:

import React from 'react';

import ReactDOM from 'react-dom';

import TodoList from './TodoList/TodoList';

ReactDOM.render(<TodoList />, document.getElementById('root'));

在TodoList文件夹中新建一个TodoList.js文件,TodoList.scss文件

文件结构 TodoList.js文件内容为:

import React, { Component } from 'react'

class TodoList extends Component {

    render() {

        return (

        <div>TodoList</div>

        )

    }

}

export default TodoList

这时候运行不会报错,页面会有“TodoList”

TodoList.js基本架构


import React, { Component, Fragment } from 'react'

import './TodoList.scss';

class TodoList extends Component {

  constructor (props) {

    super(props)

    this.state = {

      list: [],

      inputValue: ''

    }

    // 绑定 this对象

  }

  handleInputChange = (e) => {

    this.setState({

      inputValue: e.target.value

    })

  }

  handleClickAdd = () => {

    if (this.state.inputValue === '') {

      console.log('输入错误')

      return 0

    }

    this.setState({

      list: [...this.state.list,{

        content:this.state.inputValue,

        isEnd:false

      }],

      inputValue:''

    })

    console.log(this.state.list)

  }

  render() {

      let EndNum = this.state.list.filter(item => item.isEnd === true)

      return (

        <Fragment>

          <div className='container ContentBox'>

            <section className="hero is-primary">

              <div className="hero-body">

                <div className="container">

                  <h1 className="title">

                    TodoList

                  </h1>

                </div>

              </div>

            </section>

            <div className="notification action">

              <input

                type="text"

                className="input is-primary"

                value={this.state.inputValue}

                onChange={this.handleInputChange}

              />

              <button className="button is-primary" onClick={this.handleClickAdd}>add</button>

            </div>

            <footer className="footer">

              <p>共有:{this.state.list.length} 件事情</p>

              <p>已完成:{EndNum.length}</p>

              <p>未完成:{this.state.list.length - EndNum.length}</p>

            </footer>

          </div>

        </Fragment>

      )

  }

}

export default TodoList

(css的样式可以在coding上面去复制,我这里就不展示出来了)

效果图 这个时候页面是这样的,可以打印出来

然后我们要给他添加子组件,在TodoList文件夹中创建TodoItem.js文件,在TodoList.js中import

子组件:

import React from 'react'

class TodoItem extends React.Component {

  render() {

    const {content,index,isEnd} = this.props

    return (

      <li className="content notification is-primary">

        <label className="checkbox">

        <input

          type="checkbox"

        />

            <span className="tag">{index + 1}</span>

            {content}

            <span

              className={isEnd ? 'tag is-info' : 'tag is-warning'}

            >

              {isEnd ? '已完成' : '未完成'}

            </span>

        </label>

      </li>

    )

  }

}

export default TodoItem

在父组件中添加函数


import TodoItem from './TodoItem' // 子组件

添加函数

  getTodoItem() { // 获取子组件

    return this.state.list.map((item, index) => {

      return (

        <TodoItem

          key={index}

          content={item.content}

          isEnd={item.isEnd}

          index={index}

        />

      )

    })

  }

render()函数中

<ul className="notification list">{this.getTodoItem()}</ul>

插入位置 效果如下:

效果图

接下来我们给每个事项添加删除和修改状态的事件 父组件:


// 父组件通过属性的形式向子组件传递参数

  // 子组件通过props接收父组件传递过来的参数

  handleDelete = (index) => { // 删除

    console.log(index)

    const list = [...this.state.list]

    list.splice(index, 1)

    this.setState({

      list

    })

  }

  handleIsEnd = (index) => { // isEnd

    let list = [...this.state.list]

    list = list.map((item,itemIndex) => {

      if (itemIndex === index) {

        item.isEnd = !item.isEnd

        console.log(item)

      }

      return item

    })

    this.setState({

      list

    })

  }

  getTodoItem() { // 获取子组件

    return this.state.list.map((item, index) => {

      return (

        <TodoItem

          deleteItem={this.handleDelete}

          handleIsEnd={this.handleIsEnd}

          key={index}

          content={item.content}

          isEnd={item.isEnd}

          index={index}

        />

      )

    })

  }

子组件:

// 子组件如果想和父组件通信,子组件要调用父组件传递过来的方法

  handleDelete = () => { //删除

    const {deleteItem, index} = this.props

    deleteItem(index)

  }

  handleIsEnd = () => { // 是否完成

    const {handleIsEnd, index} = this.props

    handleIsEnd(index)

  }

将方法加到jsx中

插入位置 好了 项目完成✅ 赶快试试吧!