目录
三、组件的三大核心属性 state、props、refs与事件处理
2、函数的柯里化函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。
(四)、区别:旧的生命周期废弃了三个生命周期(will),新的新增俩个(get)
一、React基本使用
一、创建虚拟dom,渲染虚拟dom到页面上,不直接操作dom,减轻浏览器的负担。
二、创建虚拟dom的两种方式:
1、通过jsx(bable可以将jsx转为js;jsx可以将js代码格式转化,本质是用js的方法来完成)jsx是js的一种语法糖。
2、使用js(通过react的creatElement()等方法来创建,比较复杂)
三、虚拟dom实质是什么 ?
一个js的Object 普通对象,他的属性方法没有真实dom那么多,但足够在react里面使用
<script type="text/babel">
var tital = '前端js框架列表'
var data = ['Angular', 'React', 'Vue'] //数组react会帮忙遍历,对象不会
// 1、建立虚拟dom
var vdom = (
<div>
<h1>{tital}</h1>
<ul>
{/*jsx 里面不能用js语句,只能用js表达式;可以遍历数组
---注释写法*/}
{
data.map(function (item,index) {
return <li key={index}>{item}</li>
})
}
</ul>
</div>
)
// 2、渲染虚拟dom到页面
ReactDOM.render(vdom, document.getElementById('first'));
console.log('vdom 类型',typeof(vdom)); //vdom 类型 object
</script>
二、面向组件编程
一、组件和模块
模块/js模块:实现复杂功能的js代码模块化!提高js代码复用率
组件:实现 局部功能效果区域(代码+资源集合)模块化,提高代码复用率
二、定义组件的方式
(一)、函数式创建组件
<script type="text/babel">
// 1、函数式--使用于简单组件(没有state)
function Demo(propos){
console.log('函数式');
return <h1>hello,{propos.name}</h1>
}
ReactDOM.render(
<Demo name="runoob"/>,
document.getElementById('exm')
)
</script>
(二)、类式创建组件
<script type="text/babel">
// 2、类--使用于复杂组件(有state)
class Welcome extends React.Component {
render(propos) {
// 这里的this为 Welcome组件实例对象(即类似:let wel = new Welcome()中的wel)
console.log('this',this);
return <h1>Hello</h1>;
}
}
ReactDOM.render(
<Welcome/>,
document.getElementById('exm')
)
</script>
三、组件的三大核心属性 state、props、refs与事件处理
一、state
一、含义及作用:
1)state是组件对象最重要的属性,值是对象(可以包含多个key-value 的组合)
2)组件被称为"状态机" ,通过更新组件的state来更新对应的页面显示(重新渲染组件)
二、类式创建组件中:无论构造函数、render函数、以及自定义函数 中的this都为组件实例对象!!! 所以如果想调用自定义函数,则需要改变this的指向!
类中直接的自定义函数是不会绑到组件实例对象上的!即通过this拿不到自定义函数。方法有:
1、构造器其中重新定义一个函数,并更改他的指向。
2、使用箭头函数
但是需要注意的是,在自定义函数中(构造函数中可以)不能通过this直接更改this.state中的值,并不会重新触发render,react并不认可!!!需要借助api(setState) ;
render里面更新状态会重新调用!
三、state的简写形式
class Welcome extends React.Component {
// 类中除了可以写构造器和方法外,还可以写 直接赋值语句(不要写类型,对于类中写死的固定值或固定的初始值 可以有效的简化代码)
state = {
isChinese: true,
langage: 'Chinese',
county: 'China'
}
}
二、props(标签属性)
1、含义
2、作用
3、属性可以限制;限制方式有两种,写在类中和类外
4、props属性可以用于函数式
三、refs与事件处理
(一)、ref属性(不要过度使用)
1、理解
组件内的标签可以通过定义ref属性来标识自己(类似id属性)
2、形式
(1)、字符串形式(不建议可能存在效率问题,且已经过时)
(2)、回调形式 (存在调用次数问题,可以解决)
内联
<input placeholder="点击显示" ref={(currentNode) => { this.iptNode = currentNode; console.log('currentNode', currentNode); }} >
</input>
{/* 外绑定函数 */}
<input placeholder="点击显示" ref={this.getCurrentNode} ></input>
<button onClick={this.altValue}>点击</button>
可以解决被执行两次的情况
(3)、createRef()
(二)、事件处理![](https://img-blog.csdnimg.cn/d87b6afbaaa346a38ae42c19db49a7f1.png)
<input onBlur={this.altValue2} placeholder="失焦 显示"></input>
altValue2= (e)=>{
let event = e || event
alert(event.target.value)
}
四、受控组件、非受控组件 (收集表单数据)
1、受控组件:(拿到后保存起来再调用)
随着表单改变,将值传到state中,然后在页面渲染或者拿到作用时直接调用即可!(双向绑定)
2、非受控组件:(拿到后做出反应)
通过ref拿到node节点!进而获取value值或者其他操作!
五、高阶函数和函数的柯里化
1、高阶函数
1.若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。
如:Promise、setTimeout、数组方法map()、foreach()等
2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
2、函数的柯里化
函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。
上面高阶函数的2讲的就是!
不用柯里化或高阶函数,也可以实现
六、React生命周期
(一)、理解
1、组件从创建到死亡它会经历一些特定的阶段。e 1.组件从创建到死亡它会经历一些特定的阶段.E型
2 、React组件中包含一系列勾子函数(生命周期回调函数),会在特定的时刻调用。
3.我们在定义组件时,会在特定的生命周期回调函数,中做特定的工作。
(二)、生命周期-旧
1、初始化阶段:由ReactDoM.render()触发---初次渲染
1. constructor()
2. componentwi11Mount()
3. render()
4.componentDidMount()
5.componentwi11Unmount()
2.更新阶段:由 组件内部this.setSate() 或 父组件重新render触发
1. shouldcomponentUpdate()
2.componentw11update()
3. render()
4.componentDidUpdate()
5.componentwi11Unmount()
3.卸载组件:由ReactDOM.unmountComponentAtNode()触发
练习题:
<!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">
<!-- 先引入 基础库 -->
<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>
<!-- 将jsx 转为js -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="period"></div>
<script type="text/babel">
// 子组件
// 子组件
// 创建组件
class Period extends React.Component {
constructor(props) {
super(props);
this.state = {
sum: 0
}
console.log('constructor');
}
add = () => {
this.setState({
sum: this.state.sum + 1
})
}
death = () => {
ReactDOM.unmountComponentAtNode(document.querySelector('#period'))
}
forceU = () => {
// 强制更新
this.forceUpdate()
}
// 钩子函数---组件将要挂在是调用
componentWillMount() {
console.log('componentWillMount');
}
// 钩子函数---组件挂载完毕时调用
componentDidMount() {
console.log('componentDidMount');
}
// 钩子函数---询问 组件更新调用?默认为真
shouldComponentUpdate() {
console.log('shouldComponentUpdate');
return true
}
// 钩子函数---组件挂载完毕时调用
componentWillUpdate() {
console.log('componentWillUpdate');
}
// 钩子函数---子组件将接受props参数时调用; 但是有个问题,第一次接收参数不会被调用
componentWillReceiveProps() {
console.log('componentWillReceiveProps');
}
// 钩子函数---组件挂载时调用
render() {
console.log('render');
let sum = this.state.sum
return (
<div>
<h1>和为{sum}</h1>
<button onClick={this.add}>点击+1</button>
<button onClick={this.death}>卸载</button>
<button onClick={this.forceU}>强制更新</button>
<i>{this.props.text}</i>
</div>
)
}
// 钩子函数---组件挂载完毕时卸载用
componentWillUnmount() {
console.log('componentWillUnmount');
}
}
// 父组件
class Parent extends React.Component {
state = {
text: '我是父组件第 1 次传过来的text'
}
changeText = () => {
this.setState({
text: '我是父组件第 2 次传过来的text'
})
}
render() {
return (
<div>
我是父组件
<button onClick={this.changeText}>换text</button>
<br />
<br />
<br />
<Period text={this.state.text} />
</div>
)
}
}
// 渲染组件
ReactDOM.render(
<Parent />,
document.querySelector('#period')
)
</script>
</body>
</html>
(三)、新生命周期
1.初始化阶段:由ReactDOM.Render()触发---初次渲染
1.constructor() 构造函数()
2. getDeifivedStateFromProps
3.render()
4.ComponentDidMount()
2.更新阶段:由组件内部this.setSate()或父组件重新render触发
1.getDerivedStateFromProps
2. shouldComponentUpdate()
3.render()
4.getSnapshotBeforeUpdate
5. componentDidUpdate()
3.卸载组件:由ReactDOM.unmountcomponentAtNode()触发
1.componentwillUnmount() 组件卸载
<!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">
<!-- 先引入 基础库 -->
<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>
<!-- 将jsx 转为js -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="period"></div>
<script type="text/babel">
// 子组件
// 子组件
// 创建组件
class Period extends React.Component {
constructor(props) {
super(props);
this.state = {
sum: 0
}
console.log('constructor');
}
add = () => {
this.setState({
sum: this.state.sum + 1
})
}
death = () => {
ReactDOM.unmountComponentAtNode(document.querySelector('#period'))
}
forceU = () => {
// 强制更新
this.forceUpdate()
}
// 钩子函数--- 从props中得到派生的state ------> state在任何时候收 props 的影响! 一般不用
static getDerivedStateFromProps(props, state) {
console.log('getDerivedStateFromProps');
// return null; //返回状态对象 或者 null
return props;
}
// 钩子函数---组件挂载完毕时调用
componentDidMount() {
console.log('componentDidMount');
}
// 钩子函数---询问 组件更新调用?默认为真
shouldComponentUpdate() {
console.log('shouldComponentUpdate');
return true
}
// 钩子函数--- 在页面渲染之前得到一些快照(任何类型数据都可以) ,并将return 值传递给 componentDidUpdate
getSnapshotBeforeUpdate() {
console.log('getSnapshotBeforeUpdate');
return '---snapshot--'
}
componentDidUpdate(prevProps, prevState, snapshotValue) {
console.log('componentDidUpdate', snapshotValue);
}
// 钩子函数---组件挂载时调用
render() {
console.log('render');
let sum = this.state.sum
return (
<div>
<h1>和为{sum}</h1>
<button onClick={this.add}>点击+1</button>
<button onClick={this.death}>卸载</button>
<button onClick={this.forceU}>强制更新</button>
<i>{this.props.text}</i>
</div>
)
}
// 钩子函数---组件挂载完毕时卸载用
componentWillUnmount() {
console.log('componentWillUnmount');
}
}
// 渲染组件
ReactDOM.render(
<Period />,
document.querySelector('#period')
)
</script>
</body>
</html>