网站首页 > 基础教程 正文
由于代码太多,文章中的附件放置尾部
一、组件的组合使用-TodoList案例
1. 具体代码查看附件二
2. 注意点
1、父组件向子组件传数据:直接在子组件标签中添加键值对形式的数据(props)
父组件:
<List todos={todos}}/>
子组件使用:
const {todos} = this.props
2、子组件向父组件传递数据:父组件通过props给子组件传递一个函数,子组件在想要传递数据给父组件时,调用该函数
? 父组件给子组件一个调用的函数
<Header addTodo={this.addTodo}/>
? 子组件调用父组件函数
handleKeyUp = (event)=>{
//准备好一个todo对象
const todoObj = {id:nanoid(),name:target.value,done:false}
//将todoObj传递给App
this.props.addTodo(todoObj)
}
3、生成时间戳:Date.now()
UUID:生成唯一时间戳的库
npm i uuid (库比较大)
npm i nanoid(库小,很快安装)/ yarn add nanoid
用法:
import {nanoid} from 'nanoid'
调用:
nanoid( )
4、在react中,<input type="checkbox"/>若加了checked属性,则必须加onChange事件,不然无法改变勾选状态。defaultChecked只在第一次起效果。
3. todoList案例相关知识点
1.拆分组件、实现静态组件,注意:className、style的写法
2.动态初始化列表,如何确定将数据放在哪个组件的state中?
某个组件使用:放在其自身的state中
某些组件使用:放在他们共同的父组件state中(官方称此操作为:状态提升)
3.关于父子之间通信:
1.【父组件】给【子组件】传递数据:通过props传递
2.【子组件】给【父组件】传递数据:通过props传递,要求父给子传递一个函数
4.注意defaultChecked 和 checked的区别,类似的还有:defaultValue 和 value
5.状态在哪里,操作状态的方法就在哪里
二、react配置代理
1. 单一配置
在package.json中追加如下配置
"proxy":"http://localhost:5000"
说明:
1. 优点:配置简单,前端请求资源时可以不加任何前缀。
2. 缺点:不能配置多个代理。
3. 工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)
2. 多服务配置
? 创建代理配置文件
在src下创建配置文件:src/setupProxy.js
? 编写setupProxy.js配置具体代理规则
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.use(
//api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
proxy('/api1', {
target: 'http://localhost:5000',//配置转发目标地址(能返回数据的服务器地址)
changeOrigin: true, //控制服务器接收到的请求头中host字段的值
//changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000; changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000;changeOrigin默认值为false,但我们一般将changeOrigin值设为true
pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
}),
proxy('/api2', {
target: 'http://localhost:5001',
changeOrigin: true,
pathRewrite: {'^/api2': ''}
})
)
}
说明:
1. 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
2. 缺点:配置繁琐,前端请求资源时必须加前缀。
附件二:todoList案例代码
1. APP.css
.btn:focus {
outline: none;
}
.todo-container {
width: 600px;
margin: 0 auto;
}
.todo-container .todo-wrap {
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
}
2. APP.js
import React, {Component} from 'react';
import Header from "./components/Header";
import List from "./components/List";
import Footer from "./components/Footer";
import './App.css'
class App extends Component {
state = {
todos:[
{id:'001',name:'吃饭',done:true},
{id:'002',name:'睡觉',done:true},
{id:'003',name:'打代码',done:false},
{id:'004',name:'逛街',done:false}
]
}
//添加数据
addTodo = (data)=>{
const {todos} = this.state
this.setState({todos:[data, ...todos]})
}
//勾选数据
checkTodo = (id,done)=>{
const {todos} = this.state
const newTodos = todos.map(item=>{
if(item.id === id) return {...item,done}
else return item
})
this.setState({todos: newTodos})
}
//删除单条数据
deleteTodo = (id)=>{
const { todos } = this.state
//赛选数据
const newTodos = todos.filter(item=>item.id !== id)
//重新赋值
this.setState({todos: newTodos})
}
//全选/全不选
checkAllTodo = (done)=>{
const { todos } = this.state
const newTodos = todos.map(item=>{
return {...item,done}
})
this.setState({todos:newTodos})
}
//清空已选择
clearCheckedTodo = ()=>{
const { todos } = this.state
const newTodos = todos.filter(item=> !item.done)
this.setState({todos:newTodos})
}
render() {
const {todos} = this.state
return (
<div className="todo-container">
<div className="todo-wrap">
{/*头部*/}
<Header addTodo={this.addTodo}/>
{/*主体*/}
<List todos={todos} checkTodo={this.checkTodo} deleteTodo={this.deleteTodo}/>
{/*底部*/}
<Footer todos={todos} checkAllTodo={this.checkAllTodo} clearCheckedTodo={this.clearCheckedTodo}/>
</div>
</div>
);
}
}
export default App;
3. Header.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;
}
4. Header.jsx
import React, {Component} from 'react';
import PropTypes from 'prop-types'
import {nanoid} from "nanoid";
import './idnex.css'
class Header extends Component {
//类型限制
static propTypes = {
addTodo:PropTypes.func.isRequired
}
//键盘事件回调
handleKeyUp = (event)=>{
//解构赋值获取keyCode,target
const {keyCode, target} = event
//判断是否是回车键
if (keyCode == 13){
//获取值
const val = target.value
if(val.trim() === ''){
alert('输入的值不能为空')
return
}
//创建一个对象
const todoObj = {id:nanoid(), name:val, done:false}
//将数据传递给APP组件
this.props.addTodo(todoObj)
//清空数据
target.value = ''
}
}
render() {
return (
<div className="todo-header">
<input onKeyUp={this.handleKeyUp} type="text" placeholder="请输入你的任务名称,按回车键确认"/>
</div>
);
}
}
export default Header;
5. List.css
/*main*/
.todo-main {
margin-left: 0px;
border: 1px solid #ddd;
border-radius: 2px;
padding: 0px;
}
.todo-empty {
height: 40px;
line-height: 40px;
border: 1px solid #ddd;
border-radius: 2px;
padding-left: 5px;
margin-top: 10px;
}
6. List.js
import React, {Component} from 'react';
import PropTypes from 'prop-types'
import Item from "../Item";
import './index.css'
class List extends Component {
//对传入的数据进行限制
static propTypes = {
todos:PropTypes.array.isRequired,
deleteTodo:PropTypes.func.isRequired,
checkTodo:PropTypes.func.isRequired
}
render() {
const {todos,checkTodo, deleteTodo} = this.props
return (
<ul className="todo-main">
{
todos.map(item=>{
return <Item key={item.id} todo={item} checkTodo={checkTodo} deleteTodo={deleteTodo}/>
})
}
</ul>
);
}
}
export default List;
7. Item.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 span{
margin-left: 10px;
}
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;
}
8. Item.js
import React, {Component} from 'react';
import './index.css'
class Item extends Component {
state = {
mouse:false //标识鼠标移入移除
}
//鼠标移入移除
handleMouse = (flag)=>{
return ()=>{
this.setState({mouse:flag})
}
}
//删除
handleDelete = (id)=>{
return ()=>{
if(window.confirm('是否确认删除?')){
const {deleteTodo} = this.props
deleteTodo(id)
}
}
}
//勾选
handleCheck = (id)=>{
return (event)=>{
this.props.checkTodo(id, event.target.checked)
}
}
render() {
//接收list的值
const {id, name, done} = this.props.todo
const {mouse} = this.state
return (
<li style={{backgroundColor: mouse ? '#ddd' : 'white'}} onMouseEnter={this.handleMouse(true)}
onMouseLeave={this.handleMouse(false)}>
<label>
<input type="checkbox" onChange={this.handleCheck(id)} checked={done}/>
<span>{name}</span>
</label>
<button className="btn btn-danger" style={{display:mouse?'block':'none'}}
onClick={this.handleDelete(id)}>删除</button>
</li>
);
}
}
export default Item;
9. Footer.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;
}
10. Footer.js
import React, {Component} from 'react';
import './index.css'
class Footer extends Component {
//全选/全不选
checkAllTodo = (event)=>{
this.props.checkAllTodo(event.target.checked)
}
//清空已选择数据
clearCheckedTodo = ()=>{
this.props.clearCheckedTodo()
}
render() {
const {todos} = this.props
//已完成数
const doneCount = todos.reduce((pre, todo)=> pre + (todo.done?1:0),0)
//总数
const c = todos.length
return (
<div className="todo-footer">
<label>
<input type="checkbox" onChange={this.checkAllTodo} checked={doneCount === c && c !== 0? true:false}/>
</label>
<span>
<span>已完成{doneCount}</span> / 全部{c}
</span>
<button className="btn btn-danger" onClick={this.clearCheckedTodo}>清除已完成任务</button>
</div>
);
}
}
export default Footer;
结语:
把所有美好都给你
你值得
我愿意
回复react笔记,可以获得全套笔记
猜你喜欢
- 2024-11-26 51.C# Button控件
- 2024-11-26 跑马灯、滚动marqueen效果
- 2024-11-26 HTML DOM 事件
- 2024-11-26 w08Button,发出你的指令,让程序随心而动
- 2024-11-26 前端校招面试者简历这么厉害,怎么测试实力深浅?
- 2024-11-26 konva系列教程4:图形属性
- 2024-11-26 强大 WebView2 + 不用写 JavaScript 的 htmx.js 「小轻快」开发桌面程序
- 2024-11-26 33-jquery移入移出事件
- 2024-11-26 【JS 无冒泡事件】JS不会冒泡的事件有哪些??
- 2024-11-26 什么是窗口子类化
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)