React学习笔记

React

官网:https://react.docschina.org

facebook开发的一套开源框架

react是构建用户界面的js库

jq是函数库,主要用于界面的dom操作

优势
  • 声明式定义主键:使用class|function关键字来定义react组件

  • 使创建交互式UI变得轻而易举,交互式UI,交互式是用户的一种行为,ui页面(让用户在界面上的行为变得轻而易举)

  • 组件化开发:让项目容易维护。复用率增强,提高开发效率。组件和组件之间是互不干扰的个体

  • 一次学习,随处编写

  • 工作高效

    内部使用的是虚拟dom,虚拟dom不能被界面渲染的dom,跟js的dom对象结构很像,其实就是js的dom对象的副本。虚拟dom和真实dom对比采用的是diff算法。

    虚拟dom和真实的dom之间是 映射关系,当我们的虚拟dom发生改变时,真实的dom也会跟着改变。最大的优势就是该更新的更新,不更新就不更新,这种渲染方式叫最小渲染,大大降低了前段页面的重构。

spa单页面应用和mpa多页面应用
s单页面应用

有点:不需要频繁向服务器请求页面

缺点:没有页面,数据没有单独的页面,都是ajax请求过来的,该页面不容易被百度搜索

mpa多页面应用

优点:便于百度搜索

缺点:请求量大

一个链接对应一个页面

jsx学习

react组件化开发,开发组件的过程中采用jsx语法

jsx语法

结构上跟html很像,但是本质还是js语言

babel工具 编译jsx语法

babel官网:http://www.babeljs.cn/

//jsx编译之前
<div class="app">hello word</div>
//jsx编译之后
React.createElement("div",{
    class:"app"
},"hello word");//返回结果就是虚拟dom 

代码部分

babel-cli是babel的一个脚手架工具

配置编译jsx的流程

1、创建babel/config.js|babelrc

2、项目初始化npm init -y 生成一个package.json文件

3、下载babel脚手架 @babel/cli npm install --save-dev @babel/cli(提供编译指令)和@babel/core(提供编译代码)

​ 1、babel脚手架的使用指令

​ 2、将a.js编译成b.js npx babel a.js -o b.js

​ 3、npm install --save-dev @babel/preset-react 告诉babel编译的语法是react

​ 4、在babelrc中添加我们的配置项

{"presets":["@babel/preset-react"]}

​ 5、最后执行npx babel a.js -o b.js

4、配置.babelrc

React安装

  • npm操作
  • package.jaon配置项

CDN链接

<script crossorigin src="https://unpkg.com/react@16/umd/reacrt.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>//将html编译成jsx

React提供相关的api

React-dom提供操作浏览器DOM的方法

ReactDOM.render()将jsx组件渲染到指定的节点容器,有两个参数,第一个参数是jsx组件,第二个参数是节点对象(document来获取)

注意:在script标签上要添加type属性:text/babel

<script type="text/babel">
	var html1=<div>hello word</div>;//jsx
	ReactDOM.render(html1,document.getElementById("app"));
</script>
React.createElement()

React.createElement()是jsx语法编译的结果,这个函数的返回值是一个虚拟DOM

<script type="text/babel">
	var html1=React.createElement("h1",null,"hello curry");
	ReactDOM.render(html1,document.getElementById("app"));
</script>

babel官网可以将html语法编译成jsx

image-20210222204235081[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x3hG8iQY-1614582601193)(D:\MyNote.~typoraJs.assets\image-20210222204249929.png)]

image-20210222204258832

定义组件

类组件-class 函数组件-function

  • 组件首字母必须大写,这是react用于区分组件和普通标签的方法

  • 组件中返回的jsx代码必须有一个顶层标签

类组件

class Person extends React.component{
	render(){
		return <div>hello word</div>
	}
}
//渲染
ReactDOM.render(<Person/>,document.getElementById("app"))

函数组件

function Person(){
	return <div>hello web</div>
}
ReactDOM.render(<Person/>,document.getElementById("app"))
组件嵌套

父组件嵌套一个子组件

组件当标签使用的时候,必须是闭合标签。

<script type="text/babel">
	class son extends React.Component{
		render(){
			return <div><p>这是子组件</p></div>
		}
	}
	class Father extends React.Component{
		render(){
			return <div><h3>这是父组件</h3><Son></Son></div>
			//或者写成<div><h3>这是父组件</h3><Son/></div>
		}
	}
	ReactDOM.render(<Father/>,document.getElementById("app"))
</script>

jsx语言

1、表达式

​ jsx是js 的拓展语言,本质还是js

​ 使用jsx中的表达式,需要写在{}中

​ jsx本身也是一个表达式

​ 无论是如

中的内容还是如id的属性,都可以使用{表达式}

//jsx表达式
var name="zhangsan"
var html=<div>hello curry</div>
//在render中调用直接return html即可
class Father extends React.Component{
	render(){
		return <div><h3>{name}</h3></div>
	}
}
ReactDOM.render(<Father/>,document.getElementById("app"))

2、属性

3、类名className

sx中不能使用class给元素添加类名,jsx本身也是js,在js中class是关键字,要使用className给元素添加类名

var div='div1'
class Father extendsReact.Component{
	render(){
		return <div id={div} className="div2">hello howie</div>
	}
}
ReactDOM.render(<Father/>,document.getElementById("app"))
4、jsx表达式 数组自动展开
var arrs=[<p key="1">zhangsan</p>,<p key="2">python</p>,<p key="3">php</p>]
class Father extends React.component{
	render(){
		return <div classNmae="div2">{arrs}</div>
	}
}
ReactDOM,render(<Father/>,document.getElementById("app"))
5、三元运算
var b1=true
class Father extends React.Component{
	render(){
		//法1
		return <div className="div2">{b1?<h3>hello word</h3>:null}</div>
		//法2
		return <div className="div2">{b1&&<h3>hello</h3>}</div>
	}
}
6、jsx的循环

使用map方法,不要使用for循环

//jsx表达式 循环
var arrs=[{id:1,name:"curry",age:20},{id:2,name:"curry",age:20},{id:3,name:"curry",age:20}]
class Person extends React.Component{
	render(){
		return <div>
			<ul>
				{
					arrs.map(function(p,index){
						return <li key={index}> {p.name},{p.age}						</li>
					})
				}
			</ul>
		</div>
	}
}
ReactDOM,render(<Person/>,document.getElementById("app"))
for循环
<script type="text/babel">
    class Hello extends React.Component {
        render(){
        var list = (length) => {
          var res = [];
          for(var i = 0; i < length; i++) {
            res.push(<h2 key={i}>hello react</h2>)
          }
          return res
        }
        return (
          <div>hello {list(this.props.length)}
          </div>
        )
      }
    }
var helloData = 5
    ReactDOM.render(
      <Hello length = {helloData}/>,
      document.getElementById('root')
    );

7、事件

on+事件名 给组件标签添加事件

  • 事件名 首字母必须大写
  • 类组件中的jsx中的this指向组件实例对象
//在class外的function函数
function sayHello(){
	console.log("Hello")
}
//在class内部的function函数
class Person extends React.Component{
	sayGoodbye(){
		console.log("Goodbye")
	}
	render(){
		return <div>
			<button onClick={sayHello}>点击Hello</button>
			<button onClick={this.sayGoodbye}>点击Hello</button>
		</div>
	}
}
ReactDOM.render(<Person/>,document.getElementById("app"))
8、函数传参
  • 默认传递一个参数是事件对象

    传递参数的方法一

class Person extends React.Component{
	fn(e,event){
		//输出hello
		console.log(e)
		//输出事件对象
		console.log(event)
	}
	render(){
		console.log(this)
		return <div>
			//传递参数方法一
				<button onClick={(e)=>{this.fn("hello",e)}}>点击					</button>
		</div>
	}
}

传递参数方法二

<button onClick={this.函数名.bind(null,"word")}>按钮</button>
9、props

我们在使用组件的时候可以向组件传递数据,在组件可以使用props这个对象来调用数据

  • props在组件内部只是可读的,不能被修改
  • 如果props的数据源被修改,在组件被得到的props数据也会随着修改(数据驱动DOM)
类组件
class Person extends React.Component{
	render(){
		return <div>
			<p>hello</p>
			//输出curry
			<p>{this.props.name}</p>
		</div>
	}
}
//name="curry自动添加到props属性中
ReactDOM.render(<Persom name="curry"/>,
document.getElementById("app"))
函数组件
function Person(props){
	console.log(props)
	return <div>
		<p>{props.name}</p>
	</div>
}
ReactDOM.render(<Person name="curry"/>,
document.getElementById("app"))
设置props初始值

类组件

class Person extends React.Component{
	//初始化props
	static defaultProps={
		name:"curry"
	}
	render(){
		console.log(this)
		return <div>
				//输出curry
				<p>{this.props.name}</p>
			</div>
	}
}
ReactDOM.render(<Person/>,document/getElementById("app"))

函数组件

function Person(props){
	return <div>
		<p>{props.name}</p>
	</div>
}
//初始化props
Person.defaultProps={
	name:"curry"
}
ReactDOM.render(<Person/>,document/getElementById("app"))
props.children

props.children就是我们在调用组件时填充在组件标签里面的内容。

class Person extends React.Component{
	render(){
		console.log(this)
		return
			<p>{this.props.children}</p>
	}
}
ReactDOM.render(<Person name="curry"><h1>我是peops.children<h1></Person>,document.getElementById("app"))

props的注意事项

  • props用于传递数据,这个数据是一个单向传递,从根节点组件向它的子孙组件传递,逆向传递是不被允许的
  • 子孙组件如果想修改根节点组件的状态,则需要根节点组件给子孙组件传递事件方法
事件函数传递

事件函数中的this问题

  • 事件函数中的this不是我们组件实例对象,而是undefined
  • 在构造器constructor里我们需要对事件函数进行this绑定,否则函数中的this都是undefined
//子组件
class Person extends React.Component{
	constructor(){
		super()
		this.click=this.click.bind(this)
	}
	click(){
		this.props.onma()
	}
	render(){
		return <div>
			<button onClick={this.click}>事件点击</button>
		</div>
	}
}
//根节点组件
class App extends React.Component{
	fn(){
		console.log("我来自父组件")
	}
	render(){
		return <div>
			<Person onma={this.fn}></Person>
		</div>
	}
}
ReactDOM.render(<App/>,document.getElementById("app"))
state

state是组件自身的一个状态,组件内部自己的数据

组件的加载流程(组件的生命周期函数)

首先执行组件的构造器constructor()处理组件内部的状态

其次执行render()得到一个虚拟DOM

最后执行componentDidMount()插入我们真是DOM

类组件

class App extends React.Component{
	constructor(){
		super()
		//添加state状态
		this.state={
			name:"curry"
		}
	}
	render(){
		return <div>
			<span>{this.state.name}</span>
		</div>
	}
}
ReactDOM.render(<App/>,document.getElementById("app"))

函数组件不能直接添加state属性,要使用后面的Hooks知识点。

state注意

  • state是组件内部的数据状态
  • 读取state状态直接使用this.state
  • 更改state需要使用setState
class App extends React.Component{
	constructor(){
		super()
		//添加state状态
		this.state={
			name:"curry"
		}
		//事件函数中的this绑定
		this.click=this.click.bind(this)
	}
	click(){
		//this放心食用
		this.setSate({
			name:"Howie"
		})
	}
	render(){
		return <div>
			<span>{this.state.name}</span>
			//添加一个按钮调用click函数来更改state.name
			<button onClick={this.click}>点击更改state</button>
		</div>
	}
}
ReactDOM.render(<App/>,document.getElementById("app"))
数据双向绑定

组件内部的state状态发生改变,更新我们视图中元素的状态,视图中元素的状态发生改变也会影响组件中state的状态。

input表单演示数据双向绑定

class App extends React.Component{
	constructor(){
		super()
		//添加state状态
		this.state={
			name:"curry"
		}
		//绑定this
		this.changed=this.changed.bind(this)
	}
	changed(event){
		this.setState({
			name:event.target.value
		})
	}
	render(){
		reutrn <div>
			<span>{this.state.name}</span>
			<div>
				<input type="text" onChange={this.changed} value={this.state.name}/>
			</div>
		</div>
	}
}
ReacrDOM,render(<App/>,document.getElementById("app"))
组件生命周期

生命周期就是组件加载的一个流程

  • 初始化组件
  • 渲染组件
  • 更新组件
  • 删除组件

研究组件的声明周期

  • mounting家在组建

    • constructor()构造器函数 初始化数据状态 比如state

    • render() 返回一个Virtual DOM

    • componentDidMount() DOM节点插入之后调用的声明函数

      • 可以做网络请求

      • setState()更改数据状态

        class App extends React.Component{
        	constructor(){
        		super()
        		this.state={
        			name:"curry"
        		}
        		console.log("组件初始化")
        	}
        	render(){
        		console.los("render")
        		return <div>
        			<p>{this.state.name}</p>
        		</div>
        	}
        	componentDidMount(){
        		console.log("组件插入之后")
        	}
        }
        ReactDOM,render(<App/>,document.getElementById("app"))
        
  • updating更新组件 当状态数据(props或state)发生变化的时候会触发

    • 再次执行render函数

    • componentDidUpdate()数据状态更新之后会调用

      • 可以做DOM操作

      • 网络请求(如,当props未发生变化时,则不会执行网络请求)

        componentDidUpdate(prevProps){
        	//典型用法(不要忘记比较props)
        	if(this,props,userID!=precProps.userID){
        	this,fetchData(this.props.userID);
        	}
        }
        
      • setState()

  • unmounting卸载组件

    • componentWillUnmount()组件卸载之前会调用这个方法

    • componentWillUnmount()会在组件卸载以及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除timer,取消网络请求或清除在componentDidMount()中创建的订阅等。

    • ReactDOM.unmountComponentAtNode(container)

      • 用于卸载我们的组件

      • 参数就是我们插入组件的容器,dom对象,这个dom对象就是我们document.getElementById()获取的根节点

//组件卸载之前会调用的方法
componentWillUnmount(){
	
}
render(){
	return <div>
		<button onClick={()=>(ReactDOM.unmoutComponentAtNode(document.getElementById("app")))}>卸载组件</button>
	</div>
}

记比较props)
if(this,props,userID!=precProps.userID){
this,fetchData(this.props.userID);
}
}
```

- setState()
  • unmounting卸载组件

    • componentWillUnmount()组件卸载之前会调用这个方法

    • componentWillUnmount()会在组件卸载以及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除timer,取消网络请求或清除在componentDidMount()中创建的订阅等。

    • ReactDOM.unmountComponentAtNode(container)

      • 用于卸载我们的组件

      • 参数就是我们插入组件的容器,dom对象,这个dom对象就是我们document.getElementById()获取的根节点

//组件卸载之前会调用的方法
componentWillUnmount(){
	
}
render(){
	return <div>
		<button onClick={()=>(ReactDOM.unmoutComponentAtNode(document.getElementById("app")))}>卸载组件</button>
	</div>
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值