React(5)—— React模块化案例 - TodoList

一、目标功能界面

===========================================================================

在这里插入图片描述

二、界面模块拆分

===========================================================================

在这里插入图片描述

在这里插入图片描述

三、搭建静态页面

===========================================================================

index.js

import React from “react”;

import ReactDDOM from “react-dom”;

import App from “./App”;

ReactDDOM.render(, document.getElementById(“root”));

App.jsx

import React, { Component } from “react”;

import Header from “./components/Header”;

import List from “./components/List”;

import Footer from “./components/Footer”;

import ‘./App.css’

export default class App extends Component {

render() {

return (

);

}

}

App.css

/base/

body {

background: #fff;

}

.btn {

display: inline-block;

padding: 4px 12px;

margin-bottom: 0;

font-size: 14px;

line-height: 20px;

text-align: center;

vertical-align: middle;

cursor: pointer;

box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);

border-radius: 4px;

}

.btn-danger {

color: #fff;

background-color: #da4f49;

border: 1px solid #bd362f;

}

.btn-danger:hover {

color: #fff;

background-color: #bd362f;

}

.btn:focus {

outline: none;

}

/app/

.todo-container {

width: 600px;

margin: 0 auto;

}

.todo-container .todo-wrap {

padding: 10px;

border: 1px solid #ddd;

border-radius: 5px;

}

Header/index.js

import React, { Component } from ‘react’

import ‘./index.css’

export default class Header extends Component {

render() {

return (

)

}

}

Header/index.css

/header/

.todo-header input {

width: 560px;

height: 28px;

font-size: 14px;

border: 1px solid #ccc;

border-radius: 4px;

padding: 4px 7px;

}

.todo-header input:focus {

outline: none;

border-color: rgba(82, 168, 236, 0.8);

box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);

}

List/index.jsx

import React, { Component } from ‘react’

import Item from ‘…/Item’

import ‘./index.css’

export default class List extends Component {

render() {

return (

    )

    }

    }

    List/index.css

    /main/

    .todo-main {

    margin-left: 0px;

    border: 1px solid #ddd;

    border-radius: 2px;

    padding: 0px;

    }

    .todo-empty {

    height: 40px;

    line-height: 40px;

    border: 1px solid #ddd;

    border-radius: 2px;

    padding-left: 5px;

    margin-top: 10px;

    }

    Item/index.jsx

    import React, { Component } from ‘react’

    import ‘./index.css’

    export default class Item extends Component {

    render() {

    return (

    • xxxxx

      <button className=“btn btn-danger” style={{display:‘none’}}>删除

      )

      }

      }

      Item/index.css

      /item/

      li {

      list-style: none;

      height: 36px;

      line-height: 36px;

      padding: 0 5px;

      border-bottom: 1px solid #ddd;

      }

      li label {

      float: left;

      cursor: pointer;

      }

      li label li input {

      vertical-align: middle;

      margin-right: 6px;

      position: relative;

      top: -1px;

      }

      li button {

      float: right;

      display: none;

      margin-top: 3px;

      }

      li:before {

      content: initial;

      }

      li:last-child {

      border-bottom: none;

      }

      Footer/index.jsx

      import React, { Component } from ‘react’

      import ‘./index.css’

      export default class Footer extends Component {

      render() {

      return (

      已完成0 / 全部2

      清除已完成任务

      )

      }

      }

      Footer/index.css

      /footer/

      .todo-footer {

      height: 40px;

      line-height: 40px;

      padding-left: 6px;

      margin-top: 5px;

      }

      .todo-footer label {

      display: inline-block;

      margin-right: 20px;

      cursor: pointer;

      }

      .todo-footer label input {

      position: relative;

      top: -1px;

      vertical-align: middle;

      margin-right: 5px;

      }

      .todo-footer button {

      float: right;

      margin-top: 5px;

      }

      页面效果

      在这里插入图片描述

      四、实现动态组件

      ===========================================================================

      1. 动态初始化页面


      状态驱动组件

      考虑两个问题 要将状态放在哪? 状态的存储形式是什么?

      1. 可以将状态放在需要使用状态的 父组件 App中,这样Header和List都可以通过props拿到状态数据

      2. 状态的存储形式采用对象数组

      // 初始化状态

      state = {

      todos: [

      { id: ‘001’, name: ‘吃饭’, done: true },

      { id: ‘002’, name: ‘睡觉’, done: true },

      { id: ‘003’, name: ‘敲代码’, done: false },

      ]

      }

      App.jsx

      在App.jsx组件中定义状态state,通过标签属性传递给子组件List的props

      export default class App extends Component {

      // 初始化状态

      state = {

      todos: [

      { id: ‘001’, name: ‘吃饭’, done: true },

      { id: ‘002’, name: ‘睡觉’, done: true },

      { id: ‘003’, name: ‘敲代码’, done: false },

      ]

      }

      render() {

      const {todos} = this.state

      return (

      )

      }

      }

      List/index.jsx

      • 子组件通过this.props得到父组件传递过来的状态

      • 通过循环遍历todos得到一个个todo,将他们传递给Item子组件

      • 通过标签属性的形式,父组件List传递状态到子组件Item中

      • 指定key 再展开todo传递给子组件

      export default class List extends Component {

      render() {

      const {todos} = this.props

      return (

        {

        todos.map((todo) => {

        return <Item key={todo.id} {…todo}/>

        })

        }

        )

        }

        }

        Item/index.jsx

        子组件通过this.props得到父组件传递过来的每个todo的状态

        动态渲染props中获取的状态 namedone

        export default class Item extends Component {

        render() {

        const { name, done } = this.props

        return (

        • {name}

          <button className=“btn btn-danger” style={{display:‘none’}}>删除

          )

          }

          }

          效果图:

          在这里插入图片描述

          2. 动态添加todo


          子组件Header要向父组件传递得到的输入值

          可以通过调用函数,传递参数的形式 来传递状态

          App.jsx

          • 状态在父组件中,修改状态的操作就定义在父组件中

          • 在父组件中定义一个addTodo函数,然后通过标签传递给子组件

          • addTodo函数接受一个参数,这个参数就是要接受的子组件的数据

          • 通过这个参数,将子组件的数据传给父组件

          export default class App extends Component {

          // 用于添加一个todo,接受的参数是todo对象

          addTodo = (todoObj) => {

          // 获取原todos

          const { todos } = this.state

          // 追加一个todo

          const newTodos = [todoObj, …todos]

          // 更新状态

          this.setState({ todos: newTodos })

          }

          render() {

          const {todos} = this.state

          return (

          );

          }

          }

          Header/index.js

          添加生成唯一id的库 —— nanoid

          npm install nanoid

          父组件通过标签属性传递了一个函数给子组件,子组件可以通过this.props来调用函数

          函数的参数,就是子组件要传递给父组件的数据

          export default class Header extends Component {

          handleKeyUp = (event) => {

          const {keyCode, target} = event

          if (keyCode !== 13) return

          if (target.value.trim() === ‘’) {

          alert(‘输入不能为空’)

          return

          }

          this.props.addTodo({

          id: nanoid(),

          name: target.value,

          done: false

          })

          target.value = ‘’

          }

          render() {

          return (

          )

          }

          }

          在这里插入图片描述

          3. 鼠标悬浮高亮


          • 定义一个mouse状态,用来 标识鼠标移入移出

          • 通过mouse状态的改变,来改变style样式(背景颜色+删除按钮显示与隐藏)

          Item/index.js

          export default class Item extends Component {

          // 标识鼠标移入移出

          state = {

          mouse: false

          }

          // 鼠标移入移出的回调

          handleMouse = (flag) => {

          return () => {

          this.setState({mouse: flag})

          }

          }

          render() {

          const { name, done } = this.props

          const {mouse} = this.state

          return (

          style={{ backgroundColor: mouse ? ‘#ddd’ : ‘white’ }}

          onMouseEnter={this.handleMouse(true)}

          onMouseLeave={this.handleMouse(false)}

          {name}

          <button className=“btn btn-danger” style={{display: mouse?‘block’:‘none’}}>删除

          )

          }

          }

          在这里插入图片描述

          4. 勾选 改变 状态


          • 勾选前面的选中框,要改变到state中的数据

          • 根据选中的框所属的todo的id找到数据,根据更改后done的值更新相应的done的值

          App.jsx

          • 在父组件中定义一个更新todo的函数,然后传递给子组件

          • 根据拿到的id和done的值,来更新状态state中相应id数据的值

          export default class App extends Component {

          // 用于更新一个todo

          updateTodo = (id, done) => {

          const { todos } = this.state

          const newTodos = todos.map((todo) => {

          if (todo.id === id) {

          return {…todo, done: done}

          } else {

          return todo

          }

          })

          this.setState({todos: newTodos})

          }

          render() {

          const {todos} = this.state

          return (

          自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

          深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

          因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

          img

          既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

          由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

          如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

          结尾

          正式学习前端大概 3 年多了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。

          以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。

          戳这里获取前端学习资料

          (todo.id === id) {

          return {…todo, done: done}

          } else {

          return todo

          }

          })

          this.setState({todos: newTodos})

          }

          render() {

          const {todos} = this.state

          return (

          自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

          深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

          因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

          [外链图片转存中…(img-Sz9gUrnh-1712952890433)]

          [外链图片转存中…(img-wkAGUznB-1712952890434)]

          既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

          [外链图片转存中…(img-SGGunfmi-1712952890434)]

          由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

          如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

          结尾

          正式学习前端大概 3 年多了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。

          以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。

          戳这里获取前端学习资料

          前端学习书籍导图-1

      • 22
        点赞
      • 16
        收藏
        觉得还不错? 一键收藏
      • 0
        评论

      “相关推荐”对你有帮助么?

      • 非常没帮助
      • 没帮助
      • 一般
      • 有帮助
      • 非常有帮助
      提交
      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包
      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值