React(5)

本文详细介绍了在React应用中实现动态组件和状态管理的方法。通过`App.jsx`组件初始化状态,使用对象数组存储待办事项,并将状态通过props传递给`Item`和`Footer`子组件。`Item`组件展示了每个待办事项,`Footer`组件显示已完成的任务数量并提供清除功能。此外,文章还探讨了如何动态初始化页面并考虑状态的存储形式。
摘要由CSDN通过智能技术生成

}

[](()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 Compone 《大厂前端面试题解析+Web核心总结学习笔记+企业项目实战源码+最新高清讲解视频》无偿开源 徽信搜索公众号【编程进阶路】 nt {

    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 (

        );

        }

        }

        [](()List/index.jsx

        • 从父组件App中传过来的函数,继续传给它的子组件Item,完成祖孙组件中的通信

        export default class List extends Component {

        render() {

        const {todos, updateTodo} = this.props

        return (

          {

          todos.map((todo) => {

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

          })

          }

          )

          }

          }

          [](()Item/index.jsx

          • 通过List中转终于拿到祖先组件App中的函数updateTodo

          • 组件中定义onChange事件的回调函数handleCheck ,【高阶函数+柯里化】

          • 在回调函数中返回传递过来的函数并传入参数

          export default class Item extends Component {

          // 勾选、取消勾选todo的回调

          handleCheck = (id) => {

          return (event) => {

          this.props.updateTodo(id, event.target.checked)

          }

          }

          render() {

          const { id, name, done } = this.props

          const {mouse} = this.state

          return (

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

          onMouseEnter={this.handleMouse(true)}

          onMouseLeave={this.handleMouse(false)}

          <input type=“checkbox” defaultChecked={done} onChange={ this.handleCheck(id) }/>

          {name}

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

          )

          }

          }

          [](()5. 删除一个todo


          • 选中一个todo,点击删除按钮,删除这个todo

          [](()App.jsx

          因为状态数据在父组件中,所以删除todo的函数就定义在App中

          然后将函数传递给子组件

          export default class App extends Component {

          // 用于删除一个todo

          deleteTodo = (id) => {

          const { todos } = this.state

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

          return todo.id !== id

          })

          this.setState({todos:newTodos})

          }

          render() {

          const {todos} = this.state

          return (

          );

          }

          [](()List/index.jsx

          拿到函数继续传递

          export default class List extends Component {

          render() {

          const {todos, updateTodo, deleteTodo} = this.props

          return (

            {

            todos.map((todo) => {

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

            })

            }

            )

            }

            }

            [](()Item/index.jsx

            • 得到传递到的函数,将id作为函数参数传递给父组件

            • 定义绑定点击事件 这次没用高阶函数,换了一种写法,效果是一样的

            export default class Item extends Component {

        评论
        添加红包

        请填写红包祝福语或标题

        红包个数最小为10个

        红包金额最低5元

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

        抵扣说明:

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

        余额充值