Advantages of React:
Virtual DOM:
React defines a variable-based model for the DOM, which means all operations and transformations happen within these variables. This reduces the number of direct manipulations on the real DOM, leading to improved performance.
Component System:
React's component system allows you to treat any part of a page or application as a reusable component. This leads to a more modular structure with low coupling and high cohesion.
Single-Way Data Flow:
The core concept of single-way data flow simplifies the data binding process. You only need to bind server-side data to the frontend, allowing developers to focus on business logic rather than complex data management.
JSX:
React allows you to use HTML-like syntax in your JavaScript code. JSX makes it easier to write and understand the structure of components.
Simplicity and Reusability:
Function components in React are simple and easy to understand, making them ideal for beginners. They also offer great reusability, reducing the amount of code that needs to be written.
Performance Optimization:
Function components have better rendering performance compared to class components. They consume less memory and CPU resources because they don't create component instances and avoid unnecessary lifecycle methods.
Testability:
Function components are typically stateless and act like pure functions, which makes them easier to test.
Hooks:
React function components support Hooks, which were introduced in React 16.8. Hooks enable function components to manage state and lifecycle without the need for class components, enhancing their functionality and flexibility.
What is JSX?
JSX stands for JavaScript and XML (HTML), representing the way of writing HTML template structures within JS code. It is the method used in React for building UI components.
- This is a react template code for basic.
const message = 'hello,world'
function App(){
return (
<div>
<h1>this is title</h1>
{message}
</div>
)
}
Js Expression
const message = 'hello,world'
function getAge(){
return 18
}
function App(){
return (
<div>
<h1>this is title</h1>
{/* string */}
{'this is str'}
{/* variable */}
{message}
{/* function */}
{getAge()}
</div>
)
}
List rendering
const list = [
{id:1, name:'Java'},
{id:2, name: 'C#'},
{id:3, name: 'React'},
{id:4, name: 'Rust'}
]
function App(){
return (
<ul>
{list.map(item=><li key={item.id}>{item}</li>)}
</ul>
)
}
Conditional rendering
In React, you can use logic with the operator &&, ternary expressions (? 🙂 Implements basic conditional rendering
const flag = true
const loading = false
function App(){
return (
<>
{flag && <span>this is span</span>}
{loading ? <span>loading...</span>:<span>this is span</span>}
</>
)
}
React Event Bind
React Event Binds through on + eventName={event function}
, follow the camel naming method.
function App(){
const clickHandler = (e)=>{
console.log('button has clicked', e)
}
return (
<button onClick={clickHandler}>click me</button>
)
}
Passing Custom Parameters
Event arguments e and custom arguments are passed at the location of the event binding, and the parameters are declared in clickHandler, in the corresponding order
function App(){
const clickHandler = (name,e)=>{
console.log('button has clicked', name,e)
}
return (
<button onClick={(e)=>clickHandler('jack',e)}>click me</button>
)
}
React Components
A component is a part of a user interface, it can have its own logic and appearance, components can be nested with each other, and can be used multiple times
How to use the components
function Button(){
return <button>click me</button>
}
function App(){
return (
<div>
<Button/>
<Button></Button>
</div>
)
}
Components Status
useState is a React Hook (function) that allows us to add a 'state variable' to a component to control the rendering results that affect the component
function App(){
const [ count, setCount ] = React.useState(0)
return (
<div>
<button onClick={()=>setCount(count+1)}>{ count }</button>
</div>
)
}
example of simple comment list
todo:
- display comment list
- delete comment
- hight tab for navigate
- set comment can order by hot or date
base code
import { useState } from 'react'
import './App.scss'
import avatar from './images/bozai.png'
// comment list data
const defaultList = [
{
rpid: 3,
user: {
uid: '13258165',
avatar: 'https://www.coderlk.com/wp-content/uploads/2024/08/dulante.png',
uname: 'Durante',
},
content: 'ok, good job',
ctime: '10-18 08:15',
like: 88,
},
{
rpid: 2,
user: {
uid: '36080105',
avatar: '',
uname: '',
},
content: 'Almost every wise saying has an opposite one,no less wise,to balance it.',
ctime: '12-13 11:29',
like: 93,
},
{
rpid: 1,
user: {
uid: '30009257',
avatar,
uname: 'lk',
},
content: 'To write the most elegant code',
ctime: '11-19 09:00',
like: 66,
},
]
const user = {
uid: '30009257',
avatar,
uname: 'lk
}
const tabs = [
{ type: 'hot', text: 'Hot'},
{ type: 'time', text: 'News'}
]
const App = () => {
return (
<div className="app">
<div className="reply-navigation">
<ul className="nav-bar">
<li className="nav-title">
<span className="nav-title-text">comment</span>
<span className="total-reply">{10}</span>
</li>
<li className="nav-sort">
<span className='nav-item'>Hot</span>
<span className='nav-item'>News</span>
</li>
</ul>
</div>
<div className="reply-wrap">
<div className="box-normal">
<div className="reply-box-avatar">
<div className="bili-avatar">
<img className="bili-avatar-img" src={avatar} alt="user avatar" />
</div>
</div>
<div className="reply-box-wrap">
<textarea
className="reply-box-textarea"
placeholder="place a friendly comment"
/>
<div className="reply-box-send">
<div className="send-text">publish</div>
</div>
</div>
</div>
<div className="reply-list">
<div className="reply-item">
<div className="root-reply-avatar">
<div className="bili-avatar">
<img
className="bili-avatar-img" alt=""
/>
</div>
</div>
<div className="content-wrap">
<div className="user-info">
<div className="user-name">jack</div>
</div>
<div className="root-reply">
<span className="reply-content">this is comment repaied</span>
<div className="reply-info">
<span className="reply-time">{'2023-11-11'}</span>
<span className="reply-time">likes:{100}</span>
<span className="delete-btn">
delete
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default App
CSS configure
.app {
width: 80%;
margin: 50px auto;
}
.reply-navigation {
margin-bottom: 22px;
.nav-bar {
display: flex;
align-items: center;
margin: 0;
padding: 0;
list-style: none;
.nav-title {
display: flex;
align-items: center;
width: 114px;
font-size: 20px;
.nav-title-text {
color: #18191c;
font-weight: 500;
}
.total-reply {
margin: 0 36px 0 6px;
color: #9499a0;
font-weight: normal;
font-size: 13px;
}
}
.nav-sort {
display: flex;
align-items: center;
color: #9499a0;
font-size: 13px;
.nav-item {
cursor: pointer;
&:hover {
color: #00aeec;
}
&:last-child::after {
display: none;
}
&::after {
content: ' ';
display: inline-block;
height: 10px;
width: 1px;
margin: -1px 12px;
background-color: #9499a0;
}
}
.nav-item.active {
color: #18191c;
}
}
}
}
.reply-wrap {
position: relative;
}
.box-normal {
display: flex;
transition: 0.2s;
.reply-box-avatar {
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 50px;
}
.reply-box-wrap {
display: flex;
position: relative;
flex: 1;
.reply-box-textarea {
width: 100%;
height: 50px;
padding: 5px 10px;
box-sizing: border-box;
color: #181931;
font-family: inherit;
line-height: 38px;
background-color: #f1f2f3;
border: 1px solid #f1f2f3;
border-radius: 6px;
outline: none;
resize: none;
transition: 0.2s;
&::placeholder {
color: #9499a0;
font-size: 12px;
}
&:focus {
height: 60px;
background-color: #fff;
border-color: #c9ccd0;
}
}
}
.reply-box-send {
position: relative;
display: flex;
flex-basis: 86px;
align-items: center;
justify-content: center;
margin-left: 10px;
border-radius: 4px;
cursor: pointer;
transition: 0.2s;
& .send-text {
position: absolute;
z-index: 1;
color: #fff;
font-size: 16px;
}
&::after {
position: absolute;
width: 100%;
height: 100%;
background-color: #00aeec;
border-radius: 4px;
opacity: 0.5;
content: '';
}
&:hover::after {
opacity: 1;
}
}
}
.bili-avatar {
position: relative;
display: block;
width: 48px;
height: 48px;
margin: 0;
padding: 0;
border-radius: 50%;
}
.bili-avatar-img {
position: absolute;
top: 50%;
left: 50%;
display: block;
width: 48px;
height: 48px;
object-fit: cover;
border: none;
border-radius: 50%;
image-rendering: -webkit-optimize-contrast;
transform: translate(-50%, -50%);
}
// 评论列表
.reply-list {
margin-top: 14px;
}
.reply-item {
padding: 22px 0 0 80px;
.root-reply-avatar {
position: absolute;
left: 0;
display: flex;
justify-content: center;
width: 80px;
cursor: pointer;
}
.content-wrap {
position: relative;
flex: 1;
&::after {
content: ' ';
display: block;
height: 1px;
width: 100%;
margin-top: 14px;
background-color: #e3e5e7;
}
.user-info {
display: flex;
align-items: center;
margin-bottom: 4px;
.user-name {
height: 30px;
margin-right: 5px;
color: #61666d;
font-size: 13px;
line-height: 30px;
cursor: pointer;
}
}
.root-reply {
position: relative;
padding: 2px 0;
color: #181931;
font-size: 15px;
line-height: 24px;
.reply-info {
position: relative;
display: flex;
align-items: center;
margin-top: 2px;
color: #9499a0;
font-size: 13px;
.reply-time {
width: 76px;
margin-right: 20px;
}
.reply-like {
display: flex;
align-items: center;
margin-right: 19px;
.like-icon {
width: 14px;
height: 14px;
margin-right: 5px;
color: #9499a0;
background-position: -153px -25px;
&:hover {
background-position: -218px -25px;
}
}
.like-icon.liked {
background-position: -154px -89px;
}
}
.reply-dislike {
display: flex;
align-items: center;
margin-right: 19px;
.dislike-icon {
width: 16px;
height: 16px;
background-position: -153px -153px;
&:hover {
background-position: -217px -153px;
}
}
.dislike-icon.disliked {
background-position: -154px -217px;
}
}
.delete-btn {
cursor: pointer;
&:hover {
color: #00aeec;
}
}
}
}
}
}
.reply-none {
height: 64px;
margin-bottom: 80px;
color: #99a2aa;
font-size: 13px;
line-height: 64px;
text-align: center;
}
set function
const [activeTab, setActiveTab] = useState('hot')
const [list, setList] = useState(defaultList)
const onDelete = rpid => {
setList(list.filter(item => item.rpid !== rpid))
}
const onToggle = type => {
setActiveTab(type)
let newList
if (type === 'time') {
newList = orderBy(list, 'ctime', 'desc')
} else {
newList = orderBy(list, 'like', 'desc')
}
setList(newList)
}