【React】基本语法

发布于:2025-04-15 ⋅ 阅读:(25) ⋅ 点赞:(0)

  1. 什么是react ?
    用于构建用户界面的 JavaScript 库,主要用于构建UI。起源于facebook内部项目,facebook团队更名meta

  2. react特点 ?
    1)完全组件化。没有基础很难上手(vue是渐进式的)
    2)和ts结合比较好
    3)用于构建用户界面的 JavaScript 库(vue生态(cli vuex vue-router)都是本身开发团队参与开发和封装的,而react不是,react团队只做核心内容开发,它的生态都是第三方写的,封装灵活不像vue高度集成,所有都规范好了)
    4)跨平台,pc 移动都可以使用,react-native
    5)虚拟dom(react最早提出)。什么是虚拟dom?虚拟DOM是一种在内存中表示真实DOM结构的技术;通过比较虚拟DOM和真实DOM的差异,框架可以最小化更新操作,只在必要时更新DOM树中的变化部分。为什么说操作dom最损耗性能?(减少重绘重排,使用虚拟dom
    node={name:"",
prop:{},
text:"",
children:[
{},
{}
]
}
    6)对原生js,尤其es6,要求比较高
    7)使用了自己的jsx语法,目的是为了更加方便的写dom结构,react和别的框架的区别,html写在js里面。浏览器并不能识别jsx语法,react的项目都需要引入babel.js(将浏览器无法识别的语法解析成浏览器能够识别的语法)

  3. react 两大文件
    react: 核心包,提供创建元素,组件等功能;react-dom:提供了dom相关功能 ,虚拟dom,负责将创建的元素、组件渲染到页面

//CDN链接的方式引入
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

通过jsx的语法可以在js中写html

React.createElement("元素",{
	元素属性1:,
	元素属性2:},元素内容)

ReactDOM.render(text,document.getElementById("root")); //将指定的内容渲染在root根节点下
		
		
		
前提:浏览器无法识别jsx语法,需要babel解析。如果是script标签引入的话,必须加上<!-- <script type="text/babel"> -->

1.但是jsx的内容必须包裹在一个根元素内部,不能有两个根元素
2.单标签必须闭合( / 符号)
3.随便缩进
4.可以随便写变量,但是它的变量是放在单花括号中的( {}5.而且标签中可以调用函数,简单计算,三元运算
6.属性要使用变量,去掉"",在{}中放变量,<img src={src}/>
7.class的使用需要用className,因为class是关键词
8.在标签上添加style属性需要用到双花括号。外面的括号是包裹变量用到,设置样式的时候里面的花括号表示样式json对象用的
9.jsx中可以放哪些数据类型?
		let a=5 | "hello" | <div></div>;
		9.1  数字
		9.2  字符串
		9.3  布尔值,可以写成三元展示   let msg=true;   {msg?"真":"假"}
		9.4  数组,数组会直接展示数组中的内容   let msg=[1,2,3]
		9.5  对象,不能被直接展示,只能转成字符串后展示
				let msg={name:"月亮"};
				<h1 className="colorR" data-index="1">内容:{JSON.stringify(msg)}</h1>

10.事件
		1)事件属性是驼峰写法
		2)绑定的事件放在花括号中
		3)调用事件直接写事件名,不要打括号
		
11.注释
		{/* 内容 */}
<style>
	.colorR{
		color: red;
	}
</style>

<!--挂载的根节点-->
<div id="root"></div>

<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">

	/*React.createElement("元素",{
		元素属性1:值,
		元素属性2:值
	},元素内容)*/

	/*const text=React.createElement("h1",{
		title:"hello",
		id:"my1"
	},"初识react,hello")*/



	let fn=()=>{
		alert("哈哈哈哈")
	};
	let fn2=()=>{
		console.log("fn2")
	}
	let src="https://fanyi-cdn.cdn.bcebos.com/static/cat/asset/logo.2481f256.png";
	let msg={name:"月亮"};
	let num=100;
	let text=(<div>
		<h1 className="colorR" data-index="1">内容:{JSON.stringify(msg)}</h1>
		<img src={src}/>
		<div>{123+5}</div>
		<h2>{num>100?"大于100":"小于100"}</h2>
		{/*<p>{fn()}</p>*/}
		<span style={{color:"green",backgroundColor:"yellow"}}>内联样式</span>

		<button onClick={fn2}>事件</button>
	</div>)


	ReactDOM.render(text,document.getElementById("root")); 
</script>

函数组件 / class组件的语法、父子组件传参、事件

1)class组件
			语法定义方式:
						class 组件名首字母大写 extends React.Component{
							render(){
								return 模板
							}
						}
						
2)函数组件
			语法定义方式:
						function 函数名(){
							return (模板)
						}

						或简写:

						const 组件名=()=>模板


组件的使用:
			<组件名></组件名><组件名/>


版本16.8之前的函数组件和类组件的区别:
						生命周期 	状态(数据管理) 	ref 	this 				                     用途
			函数组件 	  没有           没有        没有    普通函数this指向会变化,需要用箭头函数      布局,UI组件
			class组件      有             有          有     this指向class组件的实例                    常用组件


版本16.8之后作者加入了hook,函数组件什么 都可以做:
			两种组件的呈现没有多少区别了,甚至于函数组件会显得更简洁,因为class组件所有的东西都会写在类里面,最后class比较大
			函数组件的好处就是每个函数都可以分离出来,需要的时候调用或者传参就好了(具体使用哪个看公司是否有要求)


父子组件传参:
			函数组件中props传递参数,但是父组件传递参数,子组件props接受的参数只能读取,不能赋值


事件:
			1.<button onClick={this.changeColor1}>点击修改1</button>
				如果函数不是箭头函数,this指向就会有问题
				如果函数中不使用this就不会有问题
				如果要使用this,解决方式就是将函数变成箭头函数

			2.<button onClick={this.changeColor2.bind(this)}>点击修改2</button>
				直接将正确的this传递给函数,函数调用不会报错

			3.<button onClick={this.changeColor3.bind(this,1,2,3)}>点击修改3</button>
				在传参的时候使用


事件对象event:
			在react中事件对象是react自己封装的
			1.阻止冒泡  event.stopPropagation()
			2.阻止默认行为  event.preventDefault()
			3.键码  event.keyCode

			event对象的获取:
							<script>
								myEvent1(event){   /*不传参*/
									console.log(event);
								}
								myEvent2=(ev)=>{	/*箭头函数*/
									console.log(ev);
								}
								myEvent3(a,b,c,event){	/*传参,event写在最后获取*/
									console.log(a,b,c,event);
								}
							</script>
<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">

	/*-------------class组件--------------*/
	//-------语法,父子组件传参------
	/*class Child extends React.Component{
		render(){ //React中的render()函数是渲染的生命周期函数,负责渲染组件的输出‌
			console.log(this.props); //通过props获取到父组件传递过来的参数
			return <div>
				<h5 style={{color:this.props.color}}>子组件:{this.props.tit}</h5>
			</div>
		}
	}

	class Com extends React.Component{ //组件名首字母要大写
		render(){
			return <div>
				<h2>父组件</h2>
				<p>这是一个class组件</p>
				<Child color="red" tit="红组件"/>{/!*父组件使用的时候需要传递参数给子组件,告诉颜色*!/}
				<Child color={"green"} tit={"绿组件"}/>
			</div>
		}
	}*/



	//-------事件------
	class Com extends React.Component{
		constructor() {
			super();
			this.state={ //当前组件的状态
				tit:"这是class组件需要用到的状态",
				color:"red"
			}
		};
		changeColor1=()=>{ //不写成箭头函数的话this执行有问题,导致找不到setState
			// this.state.color="green"; //错误方式,不能通过赋值的方式修改状态
			this.setState({
				color:"green"
			})
		};
		changeColor2(){
			this.setState({
				color:"green"
			})
		};
		changeColor3(a,b,c){
			console.log(a,b,c);
			this.setState({
				color:"green"
			})
		};
		myEvent1(event){
			console.log(event);
		};
		myEvent2=(ev)=>{
			console.log(ev);
		};
		myEvent3(a,b,c,event){
			console.log(a,b,c,event);
		};
		render(){
			return <div style={{color:this.state.color}}>
				{this.state.tit}
				<button onClick={this.changeColor1}>点击修改1</button>
				<button onClick={this.changeColor2.bind(this)}>点击修改2</button>
				<button onClick={this.changeColor3.bind(this,1,2,3)}>点击修改3-带参</button>
				<button onClick={this.myEvent1}>事件对象1</button>
				<button onClick={this.myEvent2}>事件对象2</button>
				<button onClick={this.myEvent3.bind(this,1,2,3)}>事件对象3-带参</button>
			</div>
		}
	}





	/*-------------函数组件--------------*/
	//-------语法------
	/*function Com(){
		return (<div>
			<p>这是一个函数组件</p>
		</div>)
	}*/

	/*const Com=()=><div>
		<p>这是一个箭头函数组件</p>
	</div>*/


	//-------父子组件传参------
	// const Child=(props)=><div style={{color:props.color}}>函数式的子组件:{props.tit}</div>;
	/*const Child=(props)=>{
		// props.tit="哈哈哈"; //props的属性只能读取不能赋值
		return <div style={{color:props.color}}>函数式的子组件:{props.tit}</div>;
	}

	const Com=()=><div>
		<p>函数式的父组件</p>
		<Child color="red" tit="红组件"/>
		<Child color={"green"} tit={"绿组件"}/>
	</div>;*/



	const root=ReactDOM.createRoot(document.querySelector("#root"));
	root.render(<Com/>);

</script>

react 生命周期

1.组件挂载前(18版本已经没有了)componentWillMount
2.组件挂载后 componentDidMount(发起ajax请求)
3.组件更新前(18版本已经没有了)componentWillUpdate
4.组件更新后 componentDidUpdate
5.组件卸载前 componentWillUnmount(清除组件的定时器)


不管是在vue或者react或者小程序中,都是通过数据来决定页面的内容是否渲染,而不是通过节点删除或新增来操作
<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">

	class Com extends React.Component{
		constructor() {
			super();
			this.state={
				tit:"测试生命周期",
				color:"red"
			}
		};
		changeColor=()=>{
			this.setState({
				color:"green"
			})
		};
		render(){
			return <div>
				<h2 style={{color:this.state.color}}>{this.state.tit}</h2>
				<button onClick={this.changeColor}>点击修改</button>
			</div>
		};


		/*生命周期*/
		componentDidMount(){
			console.log("挂载后")
		};
		componentDidUpdate(){
			console.log("数据更新后")
		};
		componentWillUnmount(){
			console.log("销毁前")
		}
	}



	const root=ReactDOM.createRoot(document.querySelector("#root"));
	root.render(<Com/>);

</script>

根据状态(数据)动态渲染组件 / 列表渲染 / 表单渲染

动态渲染组件:

<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<!--点击对应按钮,显示对应组件-->
<script type="text/babel">

	class Com1 extends React.Component{
		render(){
			console.log(this.props.mystatus);
			if(this.props.mystatus===1){
				return <div>
					Com1
				</div>
			}else{
				return <div>
					Com2
				</div>
			}
		}
	};

	class Com extends React.Component{
		constructor() {
			super();
			this.state={
				status:1  //status值是 1 和 2,分别展示不同的内容
			}
		}
		//按钮触发的事件,可以不用写在这外面,可直接写在按钮上
		render(){
			return <div>
				<button onClick={()=>{
					this.setState({
						status: 1
					})
				}}>按钮1</button>
				<button onClick={()=>{
					this.setState({
						status: 2
					})
				}}>按钮2</button>

				{/*引入子组件,同时像子组件传递参数,子组件根据参数决定展示什么内容*/}
				<Com1 mystatus={this.state.status}/>
			</div>
		}
	}

	ReactDOM.createRoot(document.querySelector("#root")).render(<Com/>);
</script>

列表渲染:

<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<!--列表渲染-->
<script type="text/babel">

	class Com extends React.Component{
		constructor() {
			super();
			this.state={
				list:[
					{
						name:"庄寒雁",
						age:31
					},
					{
						name:"傅云夕",
						age:30
					},
					{
						name:"月亮",
						age:25
					},
					{
						name:"太阳",
						age:100
					},
					{
						name:"太阳",
						age:100
					}
				],
				// arr:[1,2,3]  //直接展示 123
				arr:[<h5>1</h5>,<h5>2</h5>,<h5>3</h5>]
			}
		}
		render(){
			let list=this.state.list.map((v,i)=>{  /*map()方法会返回一个新数组[]*/
				return <p key={i}>我叫{v.name},今年{v.age}</p>
			})
			//简写:
			{/*let list = this.state.list.map((v, i) => <p key={i}>我叫{v.name},今年{v.age}岁</p>)*/}

			console.log(list); //[<p>我叫{v.name},今年{v.age}岁</p>,<p>我叫{v.name},今年{v.age}岁</p>]

			return <div>
				{/*{this.state.arr}*/}
				{list}
			</div>
		}
	}


	ReactDOM.createRoot(document.querySelector("#root")).render(<Com/>);
</script>

表单渲染:

表单分为受控表单和非受控表单:
							受控表单: onChange  ev.target.value
							非受控表单: defaultValue
<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<!--表单渲染-->
<script type="text/babel">

	class Com extends React.Component{
		constructor() {
			super();
			this.state={
				val:"输入框的初始数据"
			}
		}
		valChange=(ev)=>{
			console.log(ev.target.value); //ev.target指向事件源(表示当前这个event对象是谁触发的)
			this.setState({
				val:ev.target.value
			})
		}
		render(){
			return <div>
				<input type="text" value={this.state.val} onChange={this.valChange}/> {/*受控表单*/}
				<input type="text" defaultValue={this.state.val}/> {/*非受控*/}
				{this.state.val}
			</div>
		}
	}


	ReactDOM.createRoot(document.querySelector("#root")).render(<Com/>);
</script>

<!--
	1. 输入框的值绑定在页面的状态中:this.state.val
	2. react的语法要求,需要一个onChange函数
		2.1 valChange函数(通过event对象获取了当前输入框的值)
		2.2 将获取的值,重新设置给状态:this.state.val
	输入框输入的值就是状态中的值
-->

class组件中的ref、ref回调函数

ref:可以获取到dom真实节点,但是并不推荐,有需要才用

<div id="root"></div>
<script src="./js/react.development.js"></script>
<script src="./js/react-dom.development.js"></script>
<script src="./js/babel.min.js"></script>
<script type="text/babel">

	/*
		1.props单向数据流,以声明式渲染组件,而ref是命令式操作组件,命令式破坏了原本的数据流,不要滥用ref
		2.无论vue还是react或微信小程序,思路都不应该是操作节点,大部分的时候都应该是通过数据的改变来使页面变化,而非操作节点
		3.react中ref的使用方法(不能在函数式组件上用,原因:函数式组件上没有实例)
	*/

	/*
		ref回调函数:ref属性它接受一个回调函数,它在组件被加载或者卸载的时候会立即执行

		1.当html元素添加ref属性,ref回调函数接收底层的dom元素作为参数
		2.当组件添加ref属性时,ref回调函数接收当前组件实例作为参数
		3.当组件卸载的时候,会传入null
		4.ref回调会在componentDidMount 或者 componentDidUpdate这些生命周期回调之前执行
	*/



	/*class MyRef extends React.Component{
		constructor() {
			super();
			this.myInput=React.createRef()
		}
		myFocus=()=>{
			console.log(this.myInput.current) //找到input节点
			this.myInput.current.focus();
		}
		render(){
			return <div>
				<input type="text" defaultValue="123" ref={this.myInput}/>
				<input type="button" value="获取焦点" onClick={this.myFocus}/>
			</div>
		}
		componentDidMount(){
			console.log(this.myInput.current)
		}
	}*/




	//ref回调函数
	/*class MyRef extends React.Component{
		constructor() {
			super();
			this.myInput=null;
		}
		setInputRef=(element)=>{
			console.log(element) //input元素
			this.myInput=element;
		}
		myFocus=()=>{
			this.myInput.focus()
		}
		render(){
			return <div>
				<input type="text" defaultValue="123" ref={this.setInputRef}/>
				<button onClick={this.myFocus}>聚焦</button>
			</div>
		}
	}*/




	//通过ref获取子组件的节点,以及子组件内部真正挂载的节点
	class ChildInput extends React.Component{
		render(){
			return <div>
				<input type="text"/>
			</div>
		}
	}
	class MyRef extends React.Component{
		render(){
			return <div>
				<ChildInput ref={"child"}/>
			</div>
		}
		componentDidMount(){
			console.log(this.refs.child)
			console.log(ReactDOM.findDOMNode(this.refs.child)) //访问真正的dom
		}
	}



	ReactDOM.createRoot(document.querySelector("#root")).render(<MyRef/>)
</script>

网站公告

今日签到

点亮在社区的每一天
去签到