Communication between React components: child components pass data cases to parent components (callback function)

日历搜索(The method of passing data from the child component to the parent component——callback function)*

一、准备工作:

1. Create the myProject02 project directory.

2. Create a manifest file. [npm init -y](//catch throws an error to ensure that the following logic can run normally)

3. Install third-party dependent packages as needed. Three packages are used here, namely react (core library), react-dom (Dom package), and react-scripts (inherited from babel). [npm install react reacat-dom react-scripts --save](//catch throws an error to ensure that the following logic can run normally)

4. Create a public folder under the project directory, and create index.html under this folder.

5. Create the src folder in the project directory, and create the entry file index.js, the outer component (parent component) App.js and the outer component style file App.css under this folder.

6. Create a components folder in the src directory (since the subcomponents may have their own css styles, create a separate folder for storing subcomponents here).

7. Under the components folder, create LogForm, Logs (Log folder), and LogSearch subcomponent folders respectively

8. Create LogForm.css under the LogForm folder for writing subcomponent css styles, create LogsForm.jsx for writing subcomponent related codes; create Logs.css and Logs.jsx under the Logs folder, and create Create a Log folder (Log.jsx, Log.css); create LogSearch.css, LogSearch.jsx under the LogSearch folder.

9. Project catalog:

insert image description here

二、编写各组件的代码:

​ 1. index.html: only one root Dom element

			 <div id="root"></div>

2. Entry file index.js:

import ReactDOM from 'react-dom/client'
import App from './App'

const   root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<App />)

3. Outer component App.js:

	import React,{
    
    Component} from 'react'
	import Logs from './components/Logs/Logs'
	import './App.css'
	import LogForm from './components/LogForm/LogForm'
	import LogSearch from './components/LogSearch/LogSearch'

	export default class App extends Component {
    
    
   		 state = {
    
    
    	    logs:[]
    	}
   		 search = ''// 钩子函数
		componentDidMount() {
    
    
    	// 获取localStorage中的数据
   		 let logs = localStorage.getItem('logs')
  	  	// 如果logs为空 就让它等于一个空数组  方便以后遍历
    		if(logs === null) {
    
    
     		   logs = []
   			 }else{
    
    
      		   logs = JSON.parse(logs)
    		}
    		this.setState({
    
    
       			 logs
    		})
	}

	// 添加数据 用于子组件LogForm 调用  完成添加数据操作
	addLogHandle = newThing =>{
    
    
        let {
    
    logs} = this.state
    	logs.push(newThing) //把传过来的数据 push到logs中
    	//修改logs
    	this.setState({
    
    
    	    logs
   		 })
   		 // 设置localStorage--把数据存放到localStorage中
   		 localStorage.setItem('logs',JSON.stringify(logs))
	}
	// 删除数据
	delLogHandle = id => {
    
    
    	let logs = JSON.parse(localStorage.getItem('logs'))
    	logs.forEach((o, index) => {
    
    
       		 if (o.id === id) {
    
    
          		let flag = confirm('确定要删除吗')
            	if (flag) {
    
    
               		 logs.splice(index, 1)
                	 this.setState({
    
    
                    	logs
                	})
            	}
        	}
  		 })
    	 // 设置localStorage--把数据存放到localStorage中
    	localStorage.setItem('logs',JSON.stringify(logs))
   		// 如果时通过搜索进行删除操作 在删除之后需要再次调用搜索函数 因为可能搜索出来符合条件的多条数据
    	this.searchLog(this.search)
   		 console.log(this.search);
	}
	// 搜索数据
	searchLog = (keyWords) => {
    
    
    	//把从父组件传过来keyWords存放到search中 
    	// 目的是为了搜索出多条数据并进行删除之后还显示搜索的显示 而不是所有数据
    	this.search=keyWords 
        let logs = JSON.parse(localStorage.getItem('logs'))  //这里要从localStorage中获取数据 而不是state  否则显示的还是没有删除时的数据
        // 如果输入的不为空 就过滤符合条件的数据  否则 输出原有的
        if (keyWords !== '') {
    
    
            this.setState({
    
    
                logs: logs.filter(e => e.thing.includes(keyWords))
            })
        } else {
    
    
            this.componentDidMount()
        }
	}
	render() {
    
    
    	return(
        	<div className='app'>
          	  	<LogForm addLog={
    
    this.addLogHandle}/>
            	<LogSearch search={
    
    this.searchLog} />
            	<Logs logs={
    
    this.state.logs} delLog={
    
    this.delLogHandle}/>
        	</div>
    	)
	}
	}

​ 4、App.css:

/*设置基本样式*/
* {
    
    
  box-sizing: border-box;
  }

/*设置body的样式*/
body {
    
    
    background-color: #DFDFDF;
    margin: 0;
}

.app {
    
    
    width: 500px;
    margin: 50px auto;
}

​ 5、LogForm.jsx:

import React,{Component} from 'react'
import './LogForm.css'
export default class LogForm extends Component {
	state = {
   		 month:'',
   		 day:0,
   		 thing:'',
   		 duration:'',
   		 id:''
	}

// 获取输入框数据
saveMonth = e => {
    this.setState({
        month: e.target.value
    })
}

saveDay = e => {
    this.setState({
        day: e.target.value
    })
}

saveThing = e => {
    this.setState({
        thing: e.target.value
    })
}

saveDuration = e => {
    this.setState({
        duration: e.target.value
    })
}

// 添加数据
addLogHandler = (e) => {
    e.preventDefault()  //阻止默认跳转
    // 解构  并把month,day,thing,duration寻存放到一个对象中
    let {month,day,thing,duration,id} = this.state
    let newThing = {
        month,
        day,
        thing,
        duration,
        id:new Date().getTime() + ''
    }
    this.props.addLog(newThing)  //父组件传过来的一个方法  把处理好的数据传过去

}
render() {
    return(
        <div className='card'>
              <form className="logs-form" onSubmit={this.addLogHandler}>
                            <div className="form-item">
                                <label htmlFor="month">月份</label>
                                <input id="month" type="text" onChange={this.saveMonth}/>
                            </div>
                            <div className="form-item">
                                <label htmlFor="day">日期</label>
                                <input id="day" type="number" onChange={this.saveDay}/>
                            </div>
                            <div className="form-item">
                                <label htmlFor="desc">内容</label>
                                <input id="desc" type="text" onChange={this.saveThing}/>
                            </div>
                            <div className="form-item">
                                <label htmlFor="time">时长</label>
                                <input id="time" type="text" onChange={this.saveDuration}/>
                            </div>
                            <div className="form-btn">
                                <button>添加</button>
                            </div>
                        </form>
        </div>
    )
}
}

​ 6、LogForm.css:

/* 添加日志项的表单样式 */
.card {
    
    
    width: 500px;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, .2);
}

.logs-form {
    
    
    background-color: #EAE2B7;
    margin-bottom: 16px;
    padding: 10px;
}

.form-item {
    
    
    height: 40px;
    line-height: 40px;
    margin: 16px 0;
    display: flex;
    flex-flow: row;
}

.form-item label {
    
    
    text-align: center;
    padding: 0 10px;
}

.form-item input {
    
    
    flex: auto;
    border: 1px solid #bbb;
    border-radius: 3px;
    outline: none;
}

.form-btn {
    
    
    text-align: center;
}

.form-btn button {
    
    
    width: 100px;
    height: 50px;
    border: none;
    background-color: #194B49;
    color: #fff;
    font-size: 20px;
    transition: .3s;
    border-radius: 3px;
}

.form-btn button:hover{
    
    
    background-color: #D62828;
}


​ 7、Logs.jsx:

import React,{Component} from 'react'
import Log from './Log/Log'
import './Logs.css'
export default class Logs extends Component {

  render() {
	 let {logs} = this.props 
     return(
        <div className='logs'> 
         {
           logs.length === 0 ?
          '暂无数据'
           :
        	logs.map((e,index) => <Log data={e} index={index} delLog = {this.props.delLog}/>)
         }
       </div>
    )
  }
}

​ 8、Logs.css:

/\*设置外层容器logs的样式\*/*
.logs {
    
    
  padding: 20px;
  background-color: #EAE2B7;
  border-radius: 10px;
  box-shadow: 0 0 10px rgba(0, 0, 0, .2);
}

​ 9、Log.jsx:

import React,{Component} from 'react'
import './Log.css'
export default  class  Log  extends  Component {
	delLogHandle = id => {
     	this.props.delLog(id)
	}

  render() {
​    const {month, day, thing, duration,id} = this.props.data
 	 return (

     	 <div className="item" >
       		 	<div className="date">
         	 		<div className="month"> {month} </div>
           			<div className="day"> {day} </div>
				</div>
            	<div className="content">
					<h2 className="desc">{thing}</h2>
		 			<div className="time">{duration}</div>
				</div>
        		<div className="delete" onClick={() => this.delLogHandle(id)}>×</div>
   		</div>
 	)
  }
}

​ 10、Log.css:

/*设置item的样式*/
.item {
    
    
    /*开启弹性盒*/
    display: flex;
    margin: 16px 0;
    padding: 6px;
    background-color: #FCBF49;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, .2);
}

.item:hover .delete {
    
    
    opacity: 1;
}

/*设置日期的样式*/
.date {
    
    
    width: 90px;
    background-color: #fff;
    border-radius: 10px;
    font-weight: bold;
    text-align: center;
    overflow: hidden;
}

/*设置月份效果*/
.month {
    
    
    height: 30px;
    line-height: 30px;
    font-size: 20px;
    color: #fff;
    background-color: #D62828;
}

/*设置日期的效果*/
.day {
    
    
    height: 60px;
    line-height: 60px;
    font-size: 50px;
}

/*设置日志内容的样式*/
.content {
    
    
    flex: auto;
    text-align: center;
    font-weight: bold;
}

/*设置描述内容*/
.desc {
    
    
    font-size: 16px;
    color: #194B49;
}

/*设置学习时间*/
.time {
    
    
    color: #D62828;
}

/* 刪除按鍵 */
.delete {
    
    
    margin-right: 10px;
    color: white;
    font-size: 20px;
    font-weight: bold;
    cursor: pointer;
    transition: .3s;
    opacity: 0;
}

.delete:hover {
    
    
    color: #D62828;
}

​ 11、LogSEarch.jsx:

import React, { Component } from 'react'
import './LogSearch.css'
export default class LogSearch extends Component {
            state = {
                search: ''
            }
            // 输入框搜索
            Search = e => {
                let keyWords = e.target.value
                this.setState({
                    search:keyWords
                })
                this.props.search(keyWords)
            }

        render() {
            return (
                <div className="search">
                    <input type="text" onChange={this.Search}/>
                    <input type="button" value="搜索" />
                </div>

            )
        }
}

​ 12、LogSearch.css:


.search input{
    
    
    width: 360px;
    height: 40px;
}

.search input[type=button]{
    
    
    width: 80px;
    height: 40px;
    line-height: 40px;
    border: none;
    background-color: #194B49;
    color:#fff;
    font-size: 16px;
    transition: .3s;
    border-radius: 3px;
    margin-bottom: 20px;
    margin-left: 10px;

}

.search input[type=button]:hover{
    
    
    background-color: #D62828;
}

三、运行命令:

npm react-scripts start

You can also set a shorthand command in the manifest file: "start": "react-scripts start"

 "scripts": {
    
    
    "start": "react-scripts start",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

Guess you like

Origin blog.csdn.net/qq_53008791/article/details/125803907