<前端组件化>拆分组件思想--吃饭睡觉打代码案例(附源码)
Posted codeMak1r.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了<前端组件化>拆分组件思想--吃饭睡觉打代码案例(附源码)相关的知识,希望对你有一定的参考价值。
👏欢迎来到我的React系列文章
🍭本系列文章从React入门开始,涵盖了React的一切基础,属于是从零开始的一个系列
🍭文章会以图文结合-动图-代码实现-解释代码的形式带领大家走进React的世界
🍭持续更新中~希望大家能够喜欢,系列文章👉React–从基础到实战
🌈博客主页👉codeMak1r的博客
👉关注✨点赞👍收藏📂
- 🔥React入门与概览(JSX语法)
- 🔥面向组件编程——组件实例的三大核心属性state、props和refs超详解
- 🔥受控组件与非受控组件(vue和react的双向绑定分别是怎么实现的?)
- 🔥React函数的柯里化(什么?这玩意儿不仅能装x,还能优化代码?)
- 🔥四行代码让我的cpu跑上90度——走进组件生命周期
- 🔥图文详解react组件生命周期——React v16.8
- 🔥react新生命周期图文详解——最新版
- 🔥react-getSnapshotBeforeUpdate()生命周期函数详解
- 🔥使用create-react-app(CRA)创建react项目
- 🔥react父子组件传值(通信)
- 🔥<前端组件化>拆分组件思想-吃饭、睡觉、打代码案例(附源码)(👈本文)
本例使用的是React v18.1技术栈
文章目录
🏆组件的组合使用-TodoList
功能: 组件化实现此功能
1.显示所有todo列表
2.输入文本,点击按钮显示到列表的首位,并清除输入的文本
▶️拆分组件
📎项目结构
📌index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
📌App.jsx
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: true
]
// addTodo用于添加一个todo,接受的参数是todo对象
addTodo = (todoObj) =>
const todos = this.state
const newTodos = [todoObj, ...todos]
this.setState( todos: newTodos );
// 用于勾选和取消勾选todo
updateTodo = (id, done) =>
// 获取todos
const todos = this.state
// 匹配处理数据
const newTodos = todos.map((todoObj) =>
if (todoObj.id === id) return ...todoObj, done
else return todoObj
)
this.setState( todos: newTodos );
// 用于删除一个todo
deleteTodo = (id) =>
const todos = this.state
// 删除指定ID的todo对象
const newTodos = todos.filter((todoObj) =>
// 数组的过滤方法,返回id不等于传进来的id值的那些todoObj对象,说明排除掉了点击了删除id对应的那个todoObj
return todoObj.id !== id
)
this.setState( todos: newTodos );
// 用于全选
checkAllTodo = (done) =>
const todos = this.state
const newTodos = todos.map((todoObj) =>
return ...todoObj, done
)
this.setState( todos: newTodos );
// 用于清除已完成任务
clearAllDone = () =>
const todos = this.state
// 过滤数据
const newTodos = todos.filter((todoObj) =>
return todoObj.done !== true
)
this.setState( todos: newTodos );
render()
return (
<div className="todo-container">
<div className="todo-wrap">
<Header addTodo=this.addTodo />
<List todos=this.state.todos
updateTodo=this.updateTodo
deleteTodo=this.deleteTodo />
<Footer todos=this.state.todos
checkAllTodo=this.checkAllTodo
clearAllDone=this.clearAllDone />
</div>
</div>
);
export default App;
📌App.css
/*base*/
body
background: #fff;
.btn
display: inline-block;
padding: 4px 12px;
margin-bottom: 0;
font-size: 14px;
line-height: 20px;
text-align: center;
vertical-align: middle;
cursor: pointer;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
border-radius: 4px;
.btn-danger
color: #fff;
background-color: #da4f49;
border: 1px solid #bd362f;
.btn-danger:hover
color: #fff;
background-color: #bd362f;
.btn:focus
outline: none;
.todo-container
width: 600px;
margin: 0 auto;
.todo-container .todo-wrap
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
Header部分
🛠Header-index.jsx
import React, Component from 'react';
import PropTypes from 'prop-types';
import nanoid from 'nanoid'
import './index.css'
class Header extends Component
// 键盘事件的回调
handleKeyUp = (event) =>
if (event.key !== 'Enter') return
console.log(event.target.value, event.keyCode, event.key)
// 添加的todo名字不能为空
if (event.target.value.trim() === '')
alert('输入不能为空')
return
const todoObj = id: nanoid(), name: event.target.value, done: false
this.props.addTodo(todoObj)
// 清空输入框
event.target.value = ''
// 对接收的props进行类型限制
static propTypes =
addTodo: PropTypes.func.isRequired,
render()
return (
<div className="todo-header">
<input onKeyUp=this.handleKeyUp type="text" placeholder="请输入你的任务名称,按回车键确认" />
</div>
);
export default Header;
🛠Header-index.css
/*header*/
.todo-header input
width: 560px;
height: 28px;
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
padding: 4px 7px;
.todo-header input:focus
outline: none;
border-color: rgba(82, 168, 236, 0.8);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
List部分
🛠List-index.jsx
import React, Component from 'react';
import PropTypes from 'prop-types';
import Item from '../Item';
import './index.css'
class List extends Component
// 对接收的props进行类型限制
static propTypes =
todos: PropTypes.array.isRequired,
updateTodo: PropTypes.func.isRequired,
deleteTodo: PropTypes.func.isRequired,
render()
const todos, updateTodo, deleteTodo = this.props
return (
<ul className="todo-main">
todos.map(todo =>
return <Item key=todo.id ...todo
updateTodo=updateTodo
deleteTodo=deleteTodo />
)
</ul>
);
export default List;
🛠List-index.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;
Item部分
🛠Item-index.jsx
import React, Component from 'react';
import './index.css'
class Item extends Component
// 标识鼠标移入、移出
state = mouse: false
// 鼠标移入移出的回调
handleMouse = (flag) =>
return () =>
this.setState( mouse: flag );
// checkbox勾选的回调
handleCheck = (id) =>
return (event) =>
console.log(id, event.target.checked)
this.props.updateTodo(id, event.target.checked)
// 删除一个todo的回调
handleDelete = (id, name) =>
return () =>
if (window.confirm('确定删除' + name + '吗?'))
this.props.deleteTodo(id)
render()
const id, name, done = this.props
return (
<li style= backgroundColor: this.state.mouse ? '#ddd' : 'white'
onMouseEnter=this.handleMouse(true)
onMouseLeave=this.handleMouse(false)>
<label>
<input type="checkbox"
checked=done
onChange=this.handleCheck(id) />
<span>name</span>
</label>
<button onClick=this.handleDelete(id, name)
className="btn btn-danger"
style= display: this.state.mouse ? 'block' : 'none' >删除</button>
</li>
);
export default Item;
🛠Item-index.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 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;
Footer部分
🛠Footer-index.jsx
import React, Component from 'react';
import './index.css'
class Footer extends Component
// 全选checkbox的回调
handleCheckAll = (event) =>
console.log(event.target.checked)
this.props.checkAllTodo(event.target.checked)
// 清除所有已完成任务的回调
handleClearAllDone = () =>
this.props.clearAllDone()
render()
const todos = this.props
// 已完成的个数
const doneCount = todos.reduce((prev, currentTodo) =>
return prev + (currentTodo.done ? 1 : 0)
, 0)
// 总数
const total = todos.length
return (
<div className="todo-footer">
<label>
<input type="checkbox"
checked=doneCount === total && total !== 0 ? true : false
onChange=this.handleCheckAll />
</label>
<span>
<span>已完成doneCount</span> / 全部total
</span>
<button onClick=浅谈React组件