日历搜索
(子组件向父组件传递数据的方法———回调函数)*
一、准备工作:
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元素
<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;
}
三、运行命令:
也可以在清单文件中设置简写命令:“start”: “react-scripts start”
"scripts": {
"start": "react-scripts start",
"test": "echo \"Error: no test specified\" && exit 1"
},