react实现兄弟组件传值,新增和删除记录

本文介绍如何使用React从零开始构建一个简单的待办事项应用,包括项目创建、组件设计及状态管理等关键技术点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、项目的创建

        创建一个空白文件夹,打开控制台,输入命令:

        npx create-react-app my-react(项目名称)

        搭建一个react的脚手架,搭建完成之后输入npm my-react 进入项目

        这个时候我们就可以输入npm start 启动项目了

二、修改App.js文件配置

        找到项目中src文件夹中的的App.js文件,打开,然后将内容全部删除,再输入如下代码:

import React, { Component } from 'react'


export default class App extends Component {
  render() {
    return (
      <div className="App">
        
      </div>
    )
  }
}

三、创建组件   

        这是一个类组件,代表着App.js已经变成了一个类组件,然后在src文件夹下创建一个components文件夹,用于存放组件,并在里面创建四个文件,如下:

        其中Todo.jsx为父组件,TodoInput.jsx和TodoList.jsx都是它的子组件,而todo.scss为sass样式文件,用于存放三个组件的css样式

 四、App.js引入父组件

        在App.js文件中将Todo.jsx文件引入,App.js代码如下:

import React, { Component } from 'react'
import Todo from "./components/Todo"

export default class App extends Component {
  render() {
    return (
      <div className="App">
        <Todo />
      </div>
    )
  }
}

        需要注意的是,引入的Tode首字母必须要大写,不然要报错。

五、Todo.jsx父组件引入子组件,并安装sass

        操作步骤与App.js引入Todo.jsx组件的步骤一样,但是引入todo.sass却不需要命名,如下:

         sass文件引入是不能直接使用的,需要在项目中安装才能使用,安装代码如下:

                npm i node-sass@npm:dart-sass

        安装完成后再启动项目就可以正常使用了

六、Todo.jsx文件代码

        

import React, { Component } from 'react'
import './todo.scss'
import TodoInput from './TodoInput'
import TodoList from './TodoList'

export default class Todo extends Component {
    state = {
        todoList: []
    }
    addTodo = (todo) =>{ //增加记录
        const todoList = [
            ...this.state.todoList,
            {
                id:Math.random(),
                body:todo,
                state:false
            }
        ]
        this.setState({
            todoList
        })
    }
    //改变状态
    changeState = (id) =>{ 
        let todoList = [...this.state.todoList]
        todoList.forEach(item => {
            if(item.id === id){
                item.state = !item.state
            }
        })
        this.setState({
            todoList
        })
    }
    //删除记录
    delTodo = (id) => {
        let todoList = [...this.state.todoList]
        let newtodoList = todoList.filter(item => {
            return item.id !== id
        }) //过滤
        this.setState({
            todoList:newtodoList
        })
    }
    render() {
        const {todoList} = this.state
        return (
            <div className="todo">
                <TodoInput addTodo={this.addTodo} />
                <TodoList todoList={todoList} changeState={this.changeState} delTodo={this.delTodo}/>
            </div>
        )
    }
}

七、TodoInput.jsx文件代码

import React, { Component } from 'react'

export default class TodoInput extends Component {
    state = {
        todo:''
    }
    setTodo = (e) => {
        this.setState({
            todo:e.target.value
        })
    }
    submitTodo = (e) =>{
        if(e.keyCode === 13){ //判断是否按下回车
            this.props.addTodo(this.state.todo)

            //清空输入框的内容
            this.setState({
                todo:''
            })
        }
    }
    render() {
        const {todo} = this.state
        return (
            <div className='todo-input'>
                <input type="text" value={todo} onChange={this.setTodo} onKeyDown={this.submitTodo} className="todo-input-1"/>
            </div>
        )
    }
}

八、TodoList.jsx文件代码

import React, { Component } from 'react'

export default class TodoList extends Component {
    delTodo = (e,id) => {
        e.preventDefault() //阻止默认事件
        this.props.delTodo(id) //删除回调函数
    }
    changeState = (id) =>{
        this.props.changeState(id)
    }
    render() {
        const {todoList} = this.props
        //列表循环
        const lis = todoList.map(item => (
            <li key={item.id} className='todo-item'>
                <span className={['todo-select',(item.state?'done':'')].join(' ')} onClick={() => this.changeState(item.id)}></span>
                <span className='todo-body'>{item.body}</span>
                <a href="" onClick={(e) => this.delTodo(e,item.id)}>删除</a>
            </li>
        ))

        // 判断数据是否存在,条件渲染
        const dom = todoList.length>0 ? lis : <li className="todo-li">暂无数据</li>

        return (
            <div className="todo-list">
                <ul>
                    {dom}
                </ul>
            </div>
        )
    }
}

九、Todo.sass文件代码

.todo {
  width: 400px;
  margin: 50px auto 0;
  box-shadow: 0 0 3px #dedede;
  padding: 10px;
  list-style-type: none;
}
.todo-li{
  list-style-type: none;
}

.todo-input{
  display: flex;
  align-items: center;
  justify-content: center;
  .todo-input-1{
    outline: none;
    height: 30px;
    padding-left: 5px;
  }
}
.todo-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 30px;
  margin-bottom: 5px;

  .todo-select {
    display: inline-block;
    width: 20px;
    height: 20px;
    background-color: #999;
  }

  .done {
    background-color: aquamarine;
  }

  .todo-body {
    flex: 1;
    padding-left: 5px;
  }
}

这样一个通过输入框输入数据,按回车后添加记录,并且点删除能删除对应记录的小demo就做好了,点击小方块还能改变记录的状态

### React 父子组件实现方法 在 React 中,父子组件之间的数据递是一种常见需求。以下是几种主要的实现方式及其示例。 #### 方法一:通过 Props 进行父组件向子组件 Props 是 React 组件之间通信的核心机制之一。父组件可以将任意类型的属性(字符串、对象、函数等)作为 props 递给子组件[^2]。 **代码示例:** ```javascript // 父组件 import React, { Component } from 'react'; class ParentComponent extends Component { constructor(props) { super(props); this.state = { message: "来自父组件的消息" }; } render() { return ( <ChildComponent message={this.state.message} /> ); } } // 子组件 function ChildComponent(props) { return ( <div> <h4>我是子组件</h4> <p>{props.message}</p> </div> ); } export default ParentComponent; ``` --- #### 方法二:使用 Context API 实现更深层次的数据共享 当需要跨多层嵌套组件数据时,`Context` 提供了一种无需手动逐层递 `props` 的解决方案[^3]。 **代码示例:** ```javascript // 创建上下文 const MyContext = React.createContext(); // 父组件 function ParentComponent() { const value = "这是父组件通过 Context 递的"; return ( <MyContext.Provider value={value}> <ChildComponent /> </MyContext.Provider> ); } // 子组件 function ChildComponent() { return ( <GrandchildComponent /> ); } // 孙组件 function GrandchildComponent() { const contextValue = React.useContext(MyContext); return ( <div> <h4>我是孙组件</h4> <p>接收到的:{contextValue}</p> </div> ); } export default ParentComponent; ``` --- #### 方法三:通过回调函数实现实时交互 如果子组件需要更新父组件的状态,则可以通过定义并递回调函数的方式完成这一目标。 **代码示例:** ```javascript // 父组件 import React, { useState } from 'react'; function ParentComponent() { const [message, setMessage] = useState("初始消息"); const handleMessageChange = (newMessage) => { setMessage(newMessage); }; return ( <> <h3>当前消息:{message}</h3> <ChildComponent onMessageChange={handleMessageChange} /> </> ); } // 子组件 function ChildComponent({ onMessageChange }) { const updateParentState = () => { onMessageChange("新的消息"); }; return ( <button onClick={updateParentState}>点击修改父组件状态</button> ); } export default ParentComponent; ``` --- #### 方法四:基于 Redux 或其他全局状态管理工具 对于复杂的应用场景,尤其是涉及多个不直接关联的组件间通信时,推荐使用像 Redux 这样的全局状态管理库[^1]。 虽然此部分未提供具体代码片段,但其核心思路在于利用 Store 来集中存储应用状态,并允许任何订阅该 Store 的组件访问或更改这些状态。 --- ### 总结 以上介绍了四种不同的父子组件方式,每一种都有各自的适用范围优缺点: - **Props**: 最基础也是最常用的一种; - **Context**: 非常适合处理深层嵌套结构中的数据流动问题; - **Callback Functions**: 能够让子组件影响父组件的行为逻辑; - **Redux/Global State Management Tools**: 更适用于大型项目或者复杂的业务场景下统一管理分发状态。 根据实际开发需求选择合适的方案即可满足大部分情况下的父子组件通讯需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值