React组件之间的通信:子组件向父组件传递数据案例(回调函数)

日历搜索(子组件向父组件传递数据的方法———回调函数)*

一、准备工作:

​ 1、创建myProject02工程目录。

​ 2、创建清单文件。 [npm init -y](//catch抛出错误 为了保证后面的逻辑可以正常运行)

​ 3、根据需要安装第三方依赖包,这里用到三个包,分别是react(核心库)、react-dom(Dom包)、react-scripts(继承由babel)。 [npm install react reacat-dom react-scripts --save](//catch抛出错误 为了保证后面的逻辑可以正常运行)

​ 4、在工程目录下创建public文件夹,并在该文件夹下创建index.html。

​ 5、在工程目录下创建src文件夹,并在该文件夹下创建入口文件index.js、外层组件(父组件)App.js和外层组件样式文件App.css。

​ 6、在src目录下创建components文件夹 (由于子组件可能会分别由自己的css样式,所以这里单独创建一个用于存放子组件的文件夹)。

​ 7、在components文件夹下,分别创建LogForm、Logs(Log文件夹)、LogSearch子组件文件夹

​ 8、LogForm文件夹下创建LogForm.css用于编写子组件css样式、创建LogsForm.jsx用于编写子组件相关代码;Logs文件夹下创建Logs.css、Logs.jsx,在该文件夹下在创建一个Log文件夹(Log.jsx、Log.css);LogSearch文件夹下创建LogSearch.css、LogSearch.jsx。

​ 9、工程目录:

在这里插入图片描述

二、编写各组件的代码:

​ 1、index.html:只有一个根Dom元素

扫描二维码关注公众号,回复: 14871099 查看本文章
			 <div id="root"></div>

​ 2、入口文件index.js:

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

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

​ 3、外层组件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

​ 也可以在清单文件中设置简写命令:“start”: “react-scripts start”

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

猜你喜欢

转载自blog.csdn.net/qq_53008791/article/details/125803907