❤️ Author: 老九
☕️ 个人博客:老九的CSDN博客
🙏 个人名言:不可控之事 乐观面对
😍 系列专栏:
文章目录
React
- 需要引入三个依赖包,React,React-dom,babel(这个包是因为React使用jsx语法编写,而jsx语法浏览器不识别,所以需要一个包将代码转换为javascript代码)
- 在React18之前,使用的是ReactDOM.render()来渲染页面,React18之后用createRoot之后再.render实现
<!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>
<div id="app"></div>
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
//React18之前,React
ReactDOM.render(<h2>Hello World</h2>, document.querySelector("#root"));
//React18之后
const app = ReactDOM.createRoot(document.querySelector("#app"));
app.render(<h2>Hello React!</h2>);
</script>
</body>
</html>
小案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
<!-- 添加依赖 -->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
// 编写React代码
const root = ReactDOM.createRoot(document.getElementById("root"));
// 将文本定义成变量
let message = "Hello world!";
//监听按钮的点击
function btnClick() {
message = "Click";
rootRender();
}
rootRender();
function rootRender() {
root.render(
<div>
<h2>{message}</h2>
<button onClick={btnClick}>修改文本</button>
</div>
);
}
</script>
</body>
</html>
使用组件(类组件)
- 通过封装成组件,增加代码的内聚性,将**数据,方法,渲染内容(render方法)**三者放在一个组件里面
补充:
1.默认函数this绑定的是window,在严格模式下绑定的是undefined
2.为什么改变this绑定不能用call或者apply
3.super函数执行步骤
如何封装一个组件
- 如何封装一个组件?
数据存放在什么位置、更新数据(setState)
- 数据分为参与界面更新的数据和不参与界面更新的数据
参与界面更新的数据要放在当前对象的state中,更新数据的时候有两步,第一是修改message数据值,第二是重新执行render函数,但是this.setState方法就把重新渲染render函数的步骤默认执行的
在类中的方法,默认是严格模式,this是undefined。如果是babel转换过的代码,也必然是严格模式,this也是undefined
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
<!-- 添加依赖 -->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
class App extends React.Component {
//组件数据
constructor() {
super();
this.state = {
message: "hello world",
name: "why",
age: "18",
};
}
//组件方法(实例方法)
btnClick() {
this.setState({
message: "hello react",
});
}
//渲染内容render方法
render() {
return (
<div>
<h2>{this.state.message}</h2>
<button onClick={this.btnClick.bind(this)}>修改文本</button>
</div>
);
}
}
const root1 = ReactDOM.createRoot(document.getElementById("root"));
root1.render(<App />);
</script>
</body>
</html>
小案例(电影列表展示)
- JSX大括号里不能写对象,可以写数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
<!-- 添加依赖 -->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
const root = ReactDOM.createRoot(document.getElementById("root"));
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
movies: ["星际穿越", "流浪地球", "大话西游", "独行乐曲"],
};
}
render() {
return (
<div>
<h2>电影列表</h2>
<ul>
{this.state.movies.map((movie) => (
<li>{movie}</li>
))}
</ul>
</div>
);
}
}
root.render(<App />);
</script>
</body>
</html>
计数器案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
<!-- 添加依赖 -->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
const root = ReactDOM.createRoot(document.querySelector("#root"));
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
message: "hello world",
counter: 100,
};
// this.increment = this.increment.bind(this)
// this.decrement = this.decrement.bind(this)
}
render() {
//js的解构语法
const { message, counter } = this.state;
return (
<div>
<h2>当前计数:{counter}</h2>
<button onClick={this.increment.bind(this)}>+1</button>
<button onClick={this.decrement.bind(this)}>-1</button>
</div>
);
}
increment() {
this.setState({
counter: this.state.counter + 1,
});
}
decrement() {
this.setState({
counter: this.state.counter - 1,
});
}
}
root.render(<App />);
</script>
</body>
</html>
JSX语法
- 正常我们如果这样写JS代码的话,浏览器是会报错的,但是我们如果在babel中这样写,babel就会自动帮我们转换,转成了React.createElement()这种形式,浏览器就会识别这种函数
- 其实就是将html的代码写在了js上面,然后通过render函数进行渲染,它用于描述我们的UI界面,完成可以和js融合在一起使用
为什么React选择了JSX
- 因为渲染逻辑本质上与其他UI逻辑存在耦合,比如UI需要绑定事件,UI需要展示数据状态,在某些状态发生改变时,有需要改变UI,所以React将html,css都放在了JS中,将它们组合在了一起,这个地方就是组件(类组件或者函数组件)
书写规范
-
1.jsx的结构中(return括号里)只能由一个根元素
-
2.JSX结构样式通常惠包裹一个(),为了方便我们阅读,将整个JSX当作一个整体,实现换行
-
3.注释:
JSX插入的内容
-
Number,String,Array类型是可以直接插入的,并且可以直接显示
-
如果是undefined,null,boolean类型在界面上显示为空
-
Object类型写在jsx大括号中不显示
-
可以插入表达式,
-
可以插入三元运算符
-
可以执行一个函数(这个注意和只传入函数的指针区别,传入函数指针不加小括号,需要bind绑定this,而传入执行函数直接在传入的函数后面加小括号,就直接执行函数了,跟this绑定是无关的)
JSX绑定基本属性
JSX绑定class属性
- 如果是静态类,写成className
- 如果是动态加载Class,有两种方式,一种是模板字符串,一种是数组
动态绑定样式
- 如果动态绑定样式,在JSX中写一个对象,注意只有在JSX作为子元素插入内容的时候不能写成对象,但是作为属性是可以写成对象的,并且JS不支持“-”,所以需要写成驼峰式
JSX本质及原理
因为jsx的语法浏览器是不识别的,这段代码是经过babel转换的,每当遇到一个标签,都会转换成React.createElement(“div”,{classNamexxxx},[]),之后就会形成一个树结构的元素,每个元素都是一个对象,这个树结构就是虚拟DOM,实际上JSX就是React.createElement(component,props,…children)的函数的语法糖,通过React.createElement最终创建出来一个ReactElement对象,React利用这个对象组成了一个javascript对象树,这个对象树就是虚拟DOM
vue中的话,专门有代码用来解析templete,解析完templete之后就会生成一个render函数,render函数中调用了大量的h函数,调用完h函数,生成了大量的一个一个的对象,对象和对象之间产生联系,最终生成了一个虚拟DOM
createElement传递的参数
React事件绑定
this问题:如果函数方法中用到了this,那么这个this就是undefined,因为this.btn1Click是传入了函数的指针
this底层是这样的原理:一些列操作之后,click变量就相当于是obj.foo指向的指针,然后调用click()函数之后,这个是this的默认指向,因为babel中默认是严格模式,所以this的指向就是undifined了
实际开发中这样的this指向的就是undefined
bind方式绑定
ES6的 class fields方式绑定
- 就相当于把函数赋值给变量
直接传入箭头函数
那为什么不直接写this.btn3Click()呢?因为如果直接写的话,就直接调用btn3Click了,而不是传入函数指针了
事件绑定案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.active{
color:red;
}
</style>
</head>
<body>
<div id="root"></div>
<!-- 添加依赖 -->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
const root = ReactDOM.createRoot(document.querySelector("#root"));
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
movies:["1","2","3"],
currentIndex:0
};
}
itemClick(index){
this.setState({
currentIndex : index
})
}
render() {
const {movies,currentIndex} = this.state
return (
<div>
<ul>
{
movies.map((item,index) =>{
return (
<li
className={currentIndex === index ?'active':''}
key={item}
onClick={(event)=>this.itemClick(index)}
>
{item}
</li>
)
})
}
</ul>
</div>
);
}
}
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
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
class App extends React.Component {
constructor() {
super();
this.state = {
message: "Hello, world!",
};
}
btnClick(event, name, age) {
console.log("btnClick", event, name, age);
}
render() {
return (
<div>
<button
/**箭头函数第一个括号里面只传event,其他的参数写在方法的括号里面**/
onClick={(event) => {
this.btnClick(event, "kobe", 19);
}}
>
按钮
</button>
</div>
);
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<App />);
</script>
</body>
</html>
条件渲染
- 一共有二种方式,React中的条件渲染跟Vue中的****v-if相同
vue中的v-show的效果相当于display:block和none的切换 - 第一种直接使用if,else进行赋值
- 第二种方式是使用三元运算符
{/*方式二:三元运算符*/}
<div>{isReady ? <button>开始战斗!</button>:<h3>开始准备</h3>}</div>
条件渲染案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.active{
color:red;
}
</style>
</head>
<body>
<div id="root"></div>
<!-- 添加依赖 -->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
message:"hello world",
isShow:true
};
}
changeShow(){
this.setState({isShow : !this.state.isShow})
}
render() {
const {message,isShow} = this.state
let showElement = null
if(isShow){
showElement = <h2>{message}</h2>
}
return (
<div>
<button onClick={()=>{this.changeShow()}}>切换</button>
{showElement}
</div>
);
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<App />);
</script>
</body>
</html>
条件渲染v-show的效果和v-if的效果案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.active{
color:red;
}
</style>
</head>
<body>
<div id="root"></div>
<!-- 添加依赖 -->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
message:"hello world",
isShow:true
};
}
changeShow(){
this.setState({isShow : !this.state.isShow})
}
render() {
const {message,isShow} = this.state
let showElement = null
if(isShow){
showElement = <h2>{message}</h2>
}
return (
<div>
{/*v-show的效果*/}
{/*style后面的第一个大括号是jsx的语法,第二个大括号是如果里面是个对象,就再加一个大括号*/}
<h2 style={{display : isShow? 'block' : 'none'}}>哈哈哈哈哈</h2>
{showElement}
<button onClick={()=>{this.changeShow()}}>切换</button>
</div>
);
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<App />);
</script>
</body>
</html>
列表渲染
- 展示列表最多的方式就是使用高阶函数map,需要绑定key
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
</style>
</head>
<body>
<div id="root"></div>
<!-- 添加依赖 -->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
message: "学生列表数据",
students: [
{ id: 111, name: "why", score: 199 },
{ id: 112, name: "kobe", score: 98 },
{ id: 113, name: "james", score: 199 },
{ id: 114, name: "curry", score: 188 },
],
};
}
render() {
const {message , students} = this.state
const filterStudents = students.filter((item) =>{
return item.score > 100
})
const sliceStudents = filterStudents.slice(0,2)
return (
<div>
<h2>{message}</h2>
<div>
{
sliceStudents.map((item)=>{
return (
<div key={item.id}>
<h2>学号: {item.id}</h2>
<h3>姓名: {item.name}</h3>
<h1>分数: {item.score}</h1>
</div>
)
})
}
</div>
</div>
);
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<App />);
</script>
</body>
</html>
————————————————————————
♥♥♥码字不易,大家的支持就是我坚持下去的动力♥♥♥
版权声明:本文为CSDN博主「亚太地区百大最帅面孔第101名」的原创文章