结束了期末考!来整理一下前端 react 笔记!!!
<body>
<div id="root"></div>
<!-- 添加依赖 -->
<!-- 依赖三个包 -->
<!--1. CDN引入 -->
<!--2. 下载引入 -->
<!--3. npm下载引入 -->
<script crossorigin src="./lib/react.js"></script>
<script crossorigin src="./lib/react_dom.js"></script>
<script crossorigin src="./lib/babel.js"></script>
<!-- 告诉是文本类型/babel -->
<script type="text/babel">
// 编写react代码(jsx语法)
// jsx语法-->普通的js代码 通过babel
// 渲染hello world
// 渲染到哪
// 可以创建多个根
// React 18 之后
const root = ReactDOM.createRoot(document.querySelector
('#root'))
root.render(<h1>Hello world</h1>)
</script>
</body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root"></div>
<!-- 引入依赖 -->
<script src="./lib/react.js"></script>
<script src="./lib/react-dom.js"></script>
<script src="./lib/babel.js"></script>
<script type="text/babel">
const root = ReactDOM.createRoot(document.querySelector("#root"))
// 1. 将文本定义成变量
let message = "hello react"
// 2. 监听按钮的点击:不要获取元素,而是定义一个函数进行绑定:onClick={}
function btnClick() {
console.log("btnClick!");
// 2.1修改数据
message = "hello world"
// 2.2重新渲染界面(修改完数据不会重新渲染)
RooterRender()
}
// 第一次直接调用进行渲染
RooterRender()
// 3. 封装一个渲染函数
function RooterRender() {
// 第一个小括号:render 方法调用
// 第二个小括号:表示接下来写的东西是一个整体
// 动态的绑定就是使用大括号
root.render((
<div>
<h2>{message}</h2>
<button onClick={btnClick()}>修改文本</button>
</div>
))
}
</script>
</body>
</html>
onClick = {this.btnClick.bind(this)}
this.btnClick = this.btnClick.bind(this)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="../lib/babel.js"></script>
<script src="../lib/react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script type="text/babel">
// 继承了React.Component就是一个类
class App extends React.Component {
// 组件数据:参与界面刷新的数据(参与数据流)/不参与界面更新的数据
// 数据定义在组件内部
constructor() {
super()
// 在这里防放置数据
// 参与页面更新的数据必须放在这里
this.state = {
message: "hrllo youlishu"
}
// 对需要绑定的方法提前绑定好 this
// this.btnClick = this.btnClick.bind(this)
}
// 组件方法(实例方法)、类的实例方法
btnClick() {
// 内部完成了两件事情:
// 1. 将state中message值修改掉
// 2. 自动重新执行render函数
console.log("btnClick")
console.log("this:", this)
this.setState({
message: "hello hahh"
})
}
// 渲染内容 render 方法:固定的方法,必须是这个名字
render() {
// 解构
const { message } = this.state
return (
<div>
<h2>{message}</h2>
<button onClick={() => this.btnClick()}>修改文本</button>
</div>
)
}
}
// this 绑定问题
// 创建一个类
// const app = new App()
// const foo = app.btnClick
// foo()//默认绑定 => window => 在严格模式下指向 undefined
// // 在 ES6 class 下就是严格模式
// // 这里是指向 window × 实际是 undefined ,因为用到了 babel ,会对代码进行转换
// function bar() {
// console.log(this);
// }
// bar()
// 创建根
const root = ReactDOM.createRoot(document.querySelector("#app"))
// 渲染一个组件
root.render(<App />)
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script src="./lib/react.js"></script>
<script src="./lib/react-dom.js"></script>
<script src="./lib/babel.js"></script>
<script type="text/babel">
// 1. 创建 root
const root = ReactDOM.createRoot(document.querySelector("#root"))
// 封装 App 组件
class App extends React.Component {
constructor() {
super()
this.state = {
movies: ['星际穿越', '老人与海', '我喜欢你', '大话西游']
}
}
render() {
// 1. 对movies进行for循环
// const liEls = []
// for (let i = 0; i < this.state.movies.length; i++) {
// const movie = this.state.movies[i]
// const liEl = <li>{movie}</li>
// liEls.push(liEl)
// }
// return (
// <div>
// <h1>电影列表</h1>
// <ul>
// 能够直接显示数组中的元素
// {liEls}
// </ul>
// </div>
// )
// 2. movies数组=>liEls
// const liEls = this.state.movies.map(movie=> <li>{movie}</li>)
// ()小括号目的:把里面的东西当成一个整体
// 3. 既然有2,不如直接上,如果里面特别复杂,另外的做法
return (
<div>
<h1>电影列表</h1>
<ul>
{this.state.movies.map(movie => <li>{movie}</li>)}
</ul>
</div>
)
}
}
// 2. 渲染组件
// 必须要这样写 <App /> => jsx => React.createElement
root.render(<App />)
</script>
</body>
</html>
<body>
<div id="root"></div>
<script src="./lib/react.js"></script>
<script src="./lib/react-dom.js"></script>
<script src="./lib/babel.js"></script>
<script type="text/babel">
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
message: "hello youlishu",
counter: 1000
}
}
increment() {
this.setState({
counter: this.state.counter + 1
})
console.log("increment");
}
decrement() {
this.setState({
counter: this.state.counter - 1
})
console.log("decrement");
}
render() {
const { counter } = this.state
return (
< div >
<h2>当前计数:{counter}</h2>
<button onClick={() => this.increment()}>+1</button>
<button onClick={() => this.decrement()}>-1</button>
</ div>
)
}
}
// 2. 创建root并且渲染App函数
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
let element2 = <div>hhhh</div>
是 js 的语法扩展,很多地方称之为 JavaScript XML
可以看成 html in js
用于描述 UI 界面,并且可以和 js 融合在一起
不同于 Vue 中的模板语法,不需要专门学习模块语法中的一些指令
all in js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script src="../lib/react.js"></script>
<script src="../lib/react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script type="text/babel">
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
message: "Hello World"
}
}
render() {
const { message } = this.state
// 把一个元素赋值给了 element ,js 中没有这种语法
const element = <h2>{message}</h2>
return element
}
}
// 2. 创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
</html>
<body>
<div id="root"></div>
<script src="../lib//react.js"></script>
<script src="../lib//react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script type="text/babel">
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
message:"Hello World"
}
}
render() {
const { message } = this.state
// 书写规范
// 1. jsx结构中只能有一个根元素
// 2. jsx结构通常会包裹一个(),将整个jsx当做一个整体,实现换行
// 3. 可以写单标签或双标签,但是单标签必须以 / 结尾
return (
<div>
<h2>{message}</h2>
</div>
)
}
}
// 2. 创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App/>)
</script>
</body>
注释:{/*注释写法*/}
,jsx 文件
JSX嵌入变量作为子元素
JSX 嵌入表达式
<body>
<div id="root"></div>
<script src="../lib//react.js"></script>
<script src="../lib//react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script type="text/babel">
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
// Number、String、Array
message: "Hello World",
// 数组
names: ["美洋洋", "嗨森", "懒图图"],
// 特殊
aaa: undefined,
counter: 9,
friend: {
name: "jecy"
},
lastName: "lisasss",
age: 19,
movies: ["哈哈", "拉拉", "乖乖"]
}
}
render() {
const { message, names, aaa, counter, friend, lastName, age } = this.state
const fullName = lastName + names
const liEls = this.state.movies.map(movie => <li key={movie}>{movie}</li>)
return (
<div>
<h2>{message}</h2>
<h1>数组:</h1>
<h2>{names}</h2>
<h1>{aaa}</h1>
<h1>{counter}</h1>
<h1>{friend.name}</h1>
<h2>{10 + 20}</h2>
<h1>{fullName}</h1>
<h2>{age >= 18 ? '成年人' : '未成年人'}</h2>
<ul>{liEls}</ul>
<ul>{this.getMoviesEls()}</ul>
</div>
)
}
getMoviesEls() {
const liEls = this.state.movies.map(movie => <li>{movie}</li>)
return liEls
}
}
// 2. 创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
都是使用 {},没有那么多指令
jsx 绑定属性(统一使用大括号进行绑定)
基本属性
绑定 class 属性:最好使用 className,而不是使用 class
className =“{aaa bbb {aaaa}}” 这样做不行
字符串拼接
const className = `abc aaa ${isActive ? 'active' : ''}`
<h2 className={className}>哈哈哈哈</h2>
将所有的 class 放在数组中
const classList = ['aaa', 'bbb', 'ccc']
if (isActive) classList.push("active")
<h2 className={classList.join(" ")}>哈哈哈哈</h2>
绑定 style 样式属性:绑定对象类型(动态)
<h2 style={{ color: "red", fontSize: "50px" }}>hehhehhh</h2>
<body>
<div id="root"></div>
<script src="../lib//react.js"></script>
<script src="../lib//react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script type="text/babel">
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
message: "Hello World",
title: "哈哈哈",
imgURL: "https://bkimg.cdn.bcebos.com/pic/a6efce1b9d16fdfa4e685e5cb58f8c5494ee7b78?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2U5Mg==,g_7,xp_5,yp_5",
href: "https://www.baidu.com",
isActive: true,
}
}
render() {
const { message, title, imgURL, href, isActive } = this.state
// 写法一:字符串拼接
const className = `abc aaa ${isActive ? 'active' : ''}`
// 写法二:将所有的class放在数组中
const classList = ['aaa', 'bbb', 'ccc']
if (isActive) classList.push("active")
// 写法三:第三方库classnames
return (
<div>
{/*1. 基本属性绑定*/}
<h2 title={title}>我是h2元素</h2>
<img src={imgURL} alt="" />
<a href={href}>百度一下</a>
{/*2. 绑定class属性:最好使用className*/}
<h2 className={className}>哈哈哈哈</h2>
<h2 className={classList.join(" ")}>哈哈哈哈</h2>
{/*3. 绑定style属性:绑定对象类型 */}
<h2 style={{ color: "red", fontSize: "50px" }}>hehhehhh</h2>
</div>
)
}
}
// 2. 创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
onClick={this.btnClick}
- 在内部是独立函数调用,所以 this 为 undefinedonClick={this.btnClick.bind(this)}
onClick={this.btnClick}
- btnClick = () => {}
onClick={() => this.btnClick()}
<body>
<div id="root"></div>
<script src="../lib//react.js"></script>
<script src="../lib//react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script type="text/babel">
// this的四种绑定规则
// 1. 默认绑定:独立执行
// 2. 隐式绑定:被一个对象执行 obj.foo()
// 3. 显式绑定:call、apply、bind
// 4. new绑定:创建一个新对象并且赋值给this
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
message: "Hello World",
counter: 100
}
}
btn1Click() {
const { counter } = this.state
console.log("btnClick");
this.setState({
counter: counter + 1
})
}
render() {
const { message, counter } = this.state
return (
<div>
<h2>{message}</h2>
{/*只是表示一个引用,传给了button*/}
{/*严格模式下函数独立调用:undefined*/}
{/*<button onClick={this.btn1Click}>btnClick</button>*/}
<button onClick={() => this.btn1Click()}>btnClick</button>
<h2>当前计数:{counter}</h2>
</div>
)
}
}
// 2. 创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
onClick={(event) => this.btn1Click(event)}
onClick={(event) => this.btn2Click(event, "http", 18)}
<div id="root"></div>
<script src="../lib//react.js"></script>
<script src="../lib//react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script type="text/babel">
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
message: "Hello World"
}
}
btnClick(event, name, age) {
console.log(event, name, age);
}
render() {
const { message } = this.state
return (
<div>
{/*event参数的传递*/}
<button onClick={(event) => this.btnClick(event, "有理数", 12)}>btnClick</button>
</div>
)
}
}
// 2. 创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
class App extends React.Component {
constructor() {
super()
this.state = {
message: "Hello World",
movies: ["有理数", "shige", "dameinv"],
currentIndex: 0
}
}
movieClick(index) {
this.setState({
currentIndex: index
})
}
render() {
const { message, currentIndex } = this.state
return (
<div>
<h2>{message}</h2>
<ul>
{this.state.movies.map((movie, index) => {
return <li onClick={() => this.movieClick(index)} key={movie} className={currentIndex === index ? 'active' : ''}>{movie}</li>
})}
</ul>
</div>
)
}
}
<body>
<div id="root"></div>
<script src="../lib//react.js"></script>
<script src="../lib//react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script type="text/babel">
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
message: "Hello World",
movies: ["有理数", "shige", "dameinv"],
currentIndex: 0
}
}
movieClick(index) {
this.setState({
currentIndex: index
})
}
render() {
const { message, currentIndex, movies } = this.state
const liEls =
movies.map((movie, index) => {
return (
<li onClick={() => this.movieClick(index)} key={movie} className={currentIndex === index ? 'active' : ''}>{movie}</li>
)
})
return (
<div>
<h2>{message}</h2>
<ul>
{liEls}
</ul>
</div>
)
}
}
// 2. 创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
<body>
<div id="root"></div>
<script src="../lib//react.js"></script>
<script src="../lib//react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script type="text/babel">
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
message: "Hello World",
isReady: false,
friend: {
name: "有理数",
desc: "性别难爱好少"
}
}
}
render() {
const { message, isReady, friend } = this.state
// 1. 条件判断方式一:使用if进行条件判断并对变量进行赋值
let showElement = null
if (isReady) {
showElement = <h2>准备开始比赛吧~</h2>
} else {
showElement = <h1>抓紧时间准备吧~</h1>
}
return (
<div>
<h2>{message}</h2>
<p>这个人的比赛状态:</p>
{/*1. 方式一:根据条件给变量赋值不同的内容*/}
<h1>{showElement}</h1>
{/*2. 方式二:三元运算符*/}
<div>{isReady ? <button>开始战斗!</button> : <h3>赶紧准备!!</h3>}</div>
{/*场景:当某一个值有可能为undefined时,使用&&进行条件判断*/}
{/*3. 方式三:&&逻辑与运算*/}
<div>{friend && <div>{friend.name + " " + friend.desc}</div>}</div>
</div>
)
}
}
// 2. 创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
changeShow() {
this.setState({
isShow: !this.state.isShow
})
}
render() {
const { message, isShow } = this.state
return (
<div>
<button onClick={() => this.changeShow()}>切换</button>
{isShow && <h2>{message}</h2>}
{/* v-show效果 */}
<h1 style={{ display: isShow ? 'block' : 'none' }}>哈哈哈哈或或</h1>
</div>
)
}
<body>
<div id="root"></div>
<script src="../lib//react.js"></script>
<script src="../lib//react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script type="text/babel">
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
students: [
{ id: 111, name: "iosa", score: 99 },
{ id: 112, name: "liye", score: 49 },
{ id: 113, name: "hhye", score: 199 },
{ id: 114, name: "yesa", score: 149 },
]
}
}
render() {
const { students } = this.state
// 分数大于100的人进行展示
const filterStudents = students.filter(item => {
return item.score > 100
})
// 分数大于一百的前两个人进行展示[start,end)
const sliceStudents = filterStudents.slice(0, 2)
return (
<div>
<h2>学生列表数据</h2>
<div className="list">
{
students.filter(item => item.score > 100).slice(0, 2).map(item => {
return (
<div class="item" key={item.id}>
<h2>学号:{item.id}</h2>
<h2>姓名:{item.name}</h2>
<h2>分数:{item.score}</h2>
</div>
)
})
}
</div>
</div>
)
}
}
// 2. 创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
student.filter(item=>item.score > 100).slice(0,2).map(item=>{
return (
<div>
// key作用:提高diff算法效率
<h2 key={item.id}>{item.id}</h2>
</div>
)
}))
实际上,jsx 仅仅只是 React.createElement(component, props, …children) 函数的语法糖
createElement 需要传递三个参数:
参数一:type
参数二:config
参数三:children
默认 jsx 是通过 babel 进行语法转换的,所以我们之前写的jsx代码都需要依赖 babel
可以在 babel 的官网中快速查看转换的过程:https://babeljs.io/repl/#?presets=react
使用 jsx 更加方便阅读
ReactElement
对象ReactElement
对象组成了一个 JavaScript 的对象树 —— JavaScript 的对象树就是虚拟 DOM虚拟 dom 作用
通过 diff 算法以最?的代价更新变化的视图,没有更新所有的数据
跨平台渲染
//data.js
const books = [
{
id: 1,
name: "你不知道的JavaScript",
date: 2001,
price: 33,
count: 2
},
{
id: 2,
name: "算法入门大导轮",
date: 2003,
price: 99,
count: 2
},
{
id: 3,
name: "数据结构与算法",
date: 2002,
price: 53,
count: 9
},
{
id: 4,
name: "如何一夜成名",
date: 2006,
price: 999,
count: 233
},
{
id: 5,
name: "一只特立独行的猪",
date: 2009,
price: 23,
count: 1
}
]
function formatPrice(price) {
// 保留两位小数
return "¥" + Number(price).toFixed(2);
}
<body>
<div id="root"></div>
<script src="../lib//react.js"></script>
<script src="../lib//react-dom.js"></script>
<script src="../lib/babel.js"></script>
<script src="./data.js"></script>
<script src="./format.js"></script>
<script type="text/babel">
// 1. 定义App根组件
class App extends React.Component {
constructor() {
super()
this.state = {
message: "Hello Books",
books: books
}
}
changeCount(index, count) {
// react中不要直接修改原来的数据
// 对原来的数据进行浅拷贝
const newBooks = [...this.state.books]
// 通过newBooks进行修改
newBooks[index].count += count
// 执行 setState:render函数重新渲染
this.setState({ books: newBooks })
}
deleteBook(index) {
// 也是要对原来的数组进行浅拷贝
const newBooks = [...this.state.books]
// 处理数组的利器
newBooks.splice(index, 1)
this.setState({ books: newBooks })
}
// 购物车页面
renderBookList() {
const { books, message } = this.state
const totalPrice = books.reduce((preValue, item) => {
return preValue + item.count + item.price
}, 0)
return (
<div class="book">
<h2>{message}</h2>
<table>
<thead>
<tr>
<th>序号</th>
<th>书籍</th>
<th>日期</th>
<th>价格</th>
<th>数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{
books.map((item, index) => {
return (
<tr key={item.id}>
<td>{index + 1}</td>
<td>{item.name}</td>
<td>{item.date}</td>
<td>{item.price}</td>
<td>
{/*在按钮属性中进行限制:disabled = true*/}
<button onClick={() => this.changeCount(index, -1)} disabled={item.count <= 1}>-</button>
{item.count}
<button onClick={() => this.changeCount(index, 1)}>+</button>
</td>
<td>
<button onClick={() => this.deleteBook(index)}>删除</button>
</td>
</tr>
)
})
}
</tbody>
</table>
<h1>总价格:{formatPrice(totalPrice)}</h1>
</div>
)
}
renderEmpty() {
return <div><h1>hahhhh购物车为空哦</h1></div>
}
render() {
const { message, books } = this.state
// 根据条件调用函数
return books.length ? this.renderBookList() : this.renderEmpty()
}
}
// 2. 创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
react 基本用的都是 webpack,不用考虑 vite
npm i create-react-app -g
create-react-app --version
create-react-app 项目名称(不能有大写字母)
cd 01-test-react
yarn
管理,后面又改成了 npm
npm run start
import ReactDOM from "react-dom/client";
// 编写react代码,并且通过react渲染出来对应的内容
import App from "./App";
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<App/>);
HelloWorld.jsx
import React from "react";
class HelloWorld extends React.Component{
render() {
return (
<div>
<h2>hello world</h2>
<p>hello,你好世界!!!</p>
</div>
)
}
}
export default HelloWorld
import React from "react";
import HelloWorld from "./Components/HelloWorld";
// 编写一个组件
class App extends React.Component {
constructor() {
super();
this.state = {
message: "hello~~~",
};
}
render() {
const { message } = this.state;
return (
<div>
<h1>{message}</h1>
<HelloWorld></HelloWorld>
</div>
);
}
}
export default App