React 类组件和函数组件

目录
1.类组件和函数组件
2.如何使用 props 和 state
3.如何绑定事件
4.复习 this+ 两个面试题

组件component

一.概念

Element VS Component (元素与组件)

//不成文的约定:元素小写,组件大写
const div=React.createElement('div',...)
这是一个React元素(小写)
const Div=()=>React.createElement('div',...)
这是一个React组件(大写)

什么是组件?
能跟其他物件组合起来的物件,就是组件,组件并没有明确的定义。
就目前而言,一个返回值是React元素的函数就是组件
Vue里,data、methods、render组合成的一个对象(构造选项)就可以表示一个组件

React两种组件
1.函数组件

function Welcome(props){return <h1>Hello,{props.name}</h1>
}
使用方法: <Welcome name="frank"/>

2.类组件

class Welcome extends React.Component {render() {return <h1>Hello, {this.props.name}</h1>}
}
使用方法: <Welcome name="frank"/>

<Welcome />会被翻译成什么?
<div />翻译为React.createElement('div') div是元素
<Welcome />翻译为React.createElement(Welcome) Welcome是函数
工具: babel online把标签翻译成JS

React.createElement的逻辑
React.createElement目前接收几种参数:
1.如果传入一个字符串’div’,则会创建一个div(虚拟DOM元素)
2.如果传入一个函数,则会调用该函数,获取其返回值
3.如果传入一个,则在类前面加个new(这会导致执行constructor),获取一个组件对象,然后调用对象的render方法,获取其返回值

class Welcome extends React.Component{ constructor(){super()this.state={n:0}}render(){return <div>hi</div>}
}
使用类
new Welcome()

二.使用React的2种组件

React2种组件的书写方式: class类组件和function函数组件。

例子

import React from "react";
import ReactDOM from "react-dom";function App() { return ( <div className="App"> 爸爸<Son /> </div>);
}class Son extends React.Component { constructor() { super(); this.state = { n: 0};}add() {// this.state.n += 1 为什么不行this.setState({ n: this.state.n + 1 }); }render() {return ( <div className="Son">儿子 n: {this.state.n}<button onClick={() => this.add()}>+1</button> <Grandson /></div>);}
}const Grandson = () => {//声明一个state初始值为0,用n代表0,用setN对0进行修改,每次setN时都会得到一个新的n(不是改变原有的n)const [n, setN] = React.useState(0); //析构写法return (<div className="Grandson">孙子 n:{n}<button onClick={() => setN(n + 1)}>+1</button></div>);
};const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

如何使用 props(外部数据)?

类组件和函数组件使用 props:
类组件直接读取属性this.props.xxx
函数组件直接读取参数props.xxx
外部数据props不能写,只能读。

一.class类组件添加外部数据props
1’ 传字符串
传: 接收方添加messageForSon="字符串"
接收: {this.props.messageForSon}
2’ 传变量
传: 接收方添加messageForSon={1+1}
接收: {this.props.messageForSon}

例子:爸爸传props给Son

function App() {const a=10return (<div className="App">爸爸<Son messageForSon="儿子你好" /> //<Son messageForSon={a} /></div>);
}
class Son extends React.Component {render() {return (<div className="Son">我是儿子,我爸对我说「{this.props.messageForSon}」<Grandson messageForGrandson="孙贼你好" /></div>);}
}

二.函数组件
同样的,要么使用""表示字符串,要么使用{}表示JS的表达式。

1’ 传字符串
传: 接收方添加messageForGrandson="字符串"
接收: 需要传一个参数props 和 接收{props.messageForGrandson}
React会自动把messageForGrandson="字符串"变成一个对象然后放到第一个参数props里,props可自定义,叫x也行,一般叫props。
2’ 传变量
传: 接收方添加messageForGrandson={a}
接收: {props.messageForGrandson}

例子:儿子传props给Grandson

class Son extends React.Component {render() {var a=10return (<div className="Son">我是儿子,我爸对我说「{this.props.messageForSon}」<Grandson messageForGrandson="孙贼你好" /> //<Grandson messageForGrandson={a} /> 添加messageForGrandson</div>);}
}
const Grandson = props => { var a=10return (<div className="Grandson">我是孙子,我爸对我说「{props.messageForGrandson}」//接收string或变量</div>);
};

如何使用 state(内部数据)?

类组件和函数组件使用 state:
类组件this.state读,this.setState
函数组件useState返回数组,第一项读,第二项写

一.类组件如何使用内部数据state?
关注数据时关注它的3个条件:1.如何初始化?2.如何读?3.如何写?

class Son extends React.Component {constructor() {super();this.state = { //1.初始化n: 0};}add() {// this.state.n += 1 为什么不行?this.setState({ n: this.state.n + 1 }); //2.写}render() {return (<div className="Son">儿子 n: {this.state.n} //3.读<button onClick={() => this.add()}>+1</button><Grandson /></div>);}
}

this.state.n += 1为什么不行?
因为Vue会监听n,而React根本不会监听n,所以就算n变化了React也不知道.
那怎么才能通知React我修改了数据呢?
setState。数据不可变的思维:不要改变以前的对象,要改的话你就产生一个新的对象。React理念就是数据不可变,你如果要改变就产生一个新的对象,新的对象去容纳新的东西,然后传给setState。

add() {//this.state.n +=1//this.setState(this.state); //这种虽然也生效但不要用,违反了数据不可变的思维this.setState({ n: this.state.n + 1 }); }

这就是在类组件里,如何使用state:
1.在constructor的super下面进行初始化
2.读的时候用this.state.n
3.写的时候用this.setState,最好用一个新的对象,而不是在原有的对象上修改。

牛X的前端用setState(函数),他一般会写成一个函数。

add() {//this.setState({ n: this.state.n + 1 }); //console.log(this.state.n) //打印出0,setState不会马上改变n的值,而是等一会console执行完后才去覆盖n的值。//所以说,setState是异步的更新UI的过程,不会立即执行而是过一会执行,新手不理解易bug,老手为了避开这个问题这样写,避免混淆新的、旧的state。this.setState( state => { //旧的nconst n=state.n+1console.log(n)return { n } //新的n})  }

这种写法能更好的理解旧state、新state,而且不容易出错,避免异步造成的误解。
使用state时注意一个事情,setState不会马上改state,最好使用函数去读新的值,它会让你更容易区分新旧state。

二.函数组件如何使用内部数据state?
关注数据时关注它的3个条件:1.如何初始化?2.如何读?3.如何写?

const Grandson = () => {const [n, setN] = React.useState(0); //1.初始值//你返回的这个数组的第1项就是用来读的,第2项就是用来写的。一个读接口一个写接口,就2项。名字可写但一般就叫n、setN。return (<div className="Grandson">孙子 n:{n} //2.读<button onClick={() => setN(n + 1)}>+1</button> //3.写,setN永远不会改变n,它会产生一个新的n。</div>);
};

类组件的setState会等一会再改变state,函数组件的setN永远都不会改变n。

函数组件注意事项
1.跟类组件类似的地方
也要通过setX(新值)来更新UI
2.跟类组件不同的地方
没有this,一律用参数和变量,搞不懂this的就可以用函数组件。

Vue 对比 React

两种编程模型
Vue: 我对数据的修改会直接映射到UI上。Vue监听了n的变化,当n变化时,Vue就把n出现的地方全部都变一遍。
React: 一开始给我个state{n:0},我把这个state变成一个UI。
如果你想改变n,要注意不能修改之前的n。应该直接新建一个新的对象,对应一个新的UI。
React就会将这2个UI进行对比(DOM diff)区别,然后进行局部更新。

复杂 state 怎么处理

所谓复杂就是state是个对象,如果state是个复杂的对象怎么办?

如果state里不止有n怎么办?
一.类组件里有nm
1.类组件的setState会自动合并第一层属性:
当类组件里有nm时,setState时可以只setState一部分,因为它会自动延用之前的属性。
2.类组件的setState不会合并第二层属性
二.函数组件里有nm
函数组件的setState不会自动合并,当多个setState放一起时要记得用...操作符把之前的复制过来。函数组件的setState完全不会帮你自动合并,不管你是第一层还是第二层,要合并只能自己用…操作符。

一.类组件里有nm

1.类组件的setState会自动合并第一层属性
例子

function App() {return (<div className="App">爸爸<Son /></div>);
}class Son extends React.Component {constructor() {super();this.state = {n: 0,m: 0};}addN() {this.setState({ n: this.state.n + 1 });// m 会被覆盖为 undefined 吗?}addM() {this.setState({ m: this.state.m + 1 });// n 会被覆盖为 undefined 吗?}render() {return (<div className="Son">儿子 n: {this.state.n}<button onClick={() => this.addN()}>n+1</button>m: {this.state.m}<button onClick={() => this.addM()}>m+1</button><Grandson /></div>);}
}const Grandson = () => {const [n, setN] = React.useState(0);return (<div className="Grandson">孙子 n:{n}<button onClick={() => setN(n + 1)}>+1</button></div>);
};const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

总结:类组件里的setState,如果你对其中一部分进行修改那么其他的部分会自动延用上一次的值,而不会被undefined覆盖。

addN() {this.setState({ n: this.state.n + 1 });
/*相当于写this.setState({...this.state, n: this.state.n + 1 });当只设置n时,m会自动延用上一次的值,m不会被覆盖为undefinedReact会自动帮你写`...this.state`:把之前所有值拷过来再将n变成n+1
*/}

2.类组件的setState不会合并第二层属性

类组件的setState会自动合并第一层属性,但是不会合并第二层属性。
解决方法: 使用Object.assign或者...操作符,二选一。

1’ 使用...操作符(推荐)

class Son extends React.Component {constructor() {super();this.state = {n: 0, //第1层,设置n时不要管mm: 0,user: {name: "frank", //第2层,设置name时必须管ageage: 18}};}...changeUser() {this.setState({//m和n不会被置空user: {...this.state.user, //防止age被置空的解决方法name: "jack"//坑:age会被置空,解决方法:`...this.state.user`}});}render() {return (<div className="Son">儿子 n: {this.state.n}<button onClick={() => this.addN()}>n+1</button>m: {this.state.m}<button onClick={() => this.addM()}>m+1</button><hr /><div>user.name: {this.state.user.name}</div><div>user.age: {this.state.user.age}</div><button onClick={() => this.changeUser()}>change user</button><Grandson /></div>);}
}

...操作法是React经常会用到的技巧

2’ 使用Object.assign

class Son extends React.Component {constructor() {super();this.state = {n: 0,m: 0,user: {name: "frank",age: 18}};}changeUser() {//Object.assign把之前user的所有属性复制到新对象上const user = Object.assign({}, this.state.user); //等价于const user={...this.state.user}user.name = "jack";this.setState({// m 和 n 不会被置空user: user});}render() {return (<div className="Son">儿子 n: {this.state.n}<button onClick={() => this.addN()}>n+1</button>m: {this.state.m}<button onClick={() => this.addM()}>m+1</button><hr /><div>user.name: {this.state.user.name}</div><div>user.age: {this.state.user.age}</div><button onClick={() => this.changeUser()}>change user</button><Grandson /></div>);}
}const Grandson = () => {const [n, setN] = React.useState(0);return (<div className="Grandson">孙子 n:{n}<button onClick={() => setN(n + 1)}>+1</button></div>);
};

二.函数组件里有nm

同样的需求下,用函数组件更简便,类组件已经过时了,尽量用函数组件
例子

//第1种写法
const Grandson = () => {const [n, setN] = React.useState(0);const [m, setM] = React.useState(0);return (<div className="Grandson">孙子 n:{n}<button onClick={() => setN(n + 1)}>n+1</button>m:{m}<button onClick={() => setM(m + 1)}>m+1</button></div>);
};

函数组件另一种不推荐的写法,你会发现m被质空:

//不要这样写,当你setState`n`时,`m`就会`undefined`.
const Grandson = () => {const [state, setState] = React.useState({n:0,m:0});return (<div className="Grandson">孙子 n:{state.n}<button onClick={() => setState({n:state.n + 1})}>n+1</button>m:{state.m}<button onClick={() => setState({m:state.m + 1})}>m+1</button></div>);
};

如果你要用函数组件的setState就不要搞个对象在这里。如果你非要弄个对象那每次赋值时要记得先拷贝之前的。

//第2种写法
const Grandson = () => {const [state, setState] = React.useState({n:0,m:0});return (<div className="Grandson">孙子 n:{state.n}<button onClick={() => setState({...state,n:state.n + 1})}>n+1</button>m:{state.m}<button onClick={() => setState({...state,m:state.m + 1})}>m+1</button></div>);
};

总结:类组件会自动合并第1层,不会合并第2层。函数组件不会自动合并。所以不要依赖自动合并。

事件绑定

React组件里事件绑定的各种写法:onClick, onKeyPress…

一.类组件的事件绑定
<button onClick={()=>this.addN()}>
示例

//最终写法:这种写法this不会变成window
class Son extends React.Component {addN=()=> this.setState({n:this.state.n+1}) //绑定
//上面的写法是下面的语法糖,2种写法完全等价
//constructor(){//  this.addN = () => this.setState({n:this.state.n+1})
//}render(){<button onClick={this.addN()}> //使用}
}

constructor里的thisthis.addN 指的是当前对象。
这种写法函数会被定义到对象本身身上,这意味着每个Son组件都有自己的addN,如果有两个Son,就有2个addN。

//补充
//1.箭头函数上的this是不会变的,因为箭头函数不支持this
addN=()=>{this.setState({n:this.state.n+1})}//2.constructor里的this`this.addN `指的是当前对象Son。
class Son extends React.Component {constructor(){this.addN = () => this.setState({n:this.state.n+1})}
}

复习this

1.this的值到底是什么?给this定性
2.你怎么还没搞懂this? 如何确定this
3.JS里为什么会有this? 为什么要设计this
为什么this会变/不会变?
所有函数的this都是参数,由调用决定,所以可变
唯独箭头函数的this不变,因为箭头函数不接受this
React的特点:能不做的,我都不做。
Vue的特点:能帮你做的,都帮你做了。
this面试题1

this面试题2

总结
React是面向类和函数,Vue更像是面向对象。
React提供的是JSX语法(2点):
1.普通属性用标签
2.非普通属性也就是跟JS相关的,都写在{}里。
{}之外都是标签,{}之内是JS。

面试题
React与Vue的区别?
相同点
1.都是对视图的封装,React是用类和函数表示一个组件,而Vue是通过构造选项构造一个组件。
2.都提供了createElement的XML简写,React提供的是JSX语法,而Vue是提供的是template模版写法(语法巨多)
不同点
React是把HTML放在JS里写(HTML in JS),而Vue是把JS放在HTML里写(JS in HTML)

更多文章,请点击 我的博客

React 类组件和函数组件相关推荐

  1. React 中ref 的使用(类组件和函数组件)以及forwardRef 与 useImperativeHandle 详解

    前言 在一个父组件中,我们想要获取到其中的节点元素或者子组件实例,从而直接调用其上面的方法.Class 类组件和函数组件是两种不同的写法. 1. Class 组件中使用ref 在 React 的 Cl ...

  2. react基础入门,类组件和函数组件,state,props,refs

    React入门 目录 React入门 React入门 Vue跟React的异同点 相同点 不同点 Vue小建议 1. 不需要响应式的数据应该怎么处理? 2. Key 3. 数据结构 React 教程 ...

  3. react render相关 【类组件、函数组件 】

    [类组件] 大概就是如果是class的写法,并且extends React.component 就要手动写render [函数组件] 如果是const App = ()=> {} 那么就酸函数组 ...

  4. React父组件调用子组件的方法【class组件和函数组件】

    在react组件之间的通信是通过props属性来完成的,比如父组件需要将数据传递给子组件,那么组件在渲染子组件的时候,直接将数据作为子组件的属性传参: <Child onChildEvent={ ...

  5. antd 函数组件_React - 组件:函数组件

    目录: 1. 组件名字首字母一定是大写的2. 返回一个jsx3. jsx依赖React,所以组件内部需要引入React4. 组件传参 a. 传递.b. 接收. function Component( ...

  6. antd 函数组件_react函数组件中引用antd<Form/>组件demo

    ```xml import React, { forwardRef, useEffect } from 'react'; import { Input, Select, Row, Col, Butto ...

  7. onclick=两个函数_[译]React函数组件和类组件的差异

    [译]React函数组件和类组件的差异 原文: https://overreacted.io/how-are-function-components-different-from-classes/ 在 ...

  8. react之纯函数、函数组件、类组件、纯组件

    一.纯函数 Pure Function 定义:一个函数的返回结果只依赖于它的参数,并且在执行的过程中没有副作用,我们就把该函数称作纯函数. - 特点: 1.函数的返回结果只依赖与它的参数(同一个输入只 ...

  9. react中类组件传值,函数组件传值:父子组件传值、非父子组件传值

    父子组件传值.非父子组件传值: 类组件传值 父子 组件传值 子 传 父: 子组件:事件的触发sendMsg=()=>{this.props.person();}父组件:<Child per ...

最新文章

  1. 腾讯云 cloudbase 云开发使用笔记
  2. 开发最前沿:项目案例实战之桥模式
  3. js 加入debug后可以进入controller_新手入门Nest.js(四) 控制器路由
  4. signature=d3634edefd0f91592d1c7b65bef4a31d,Additional file 14
  5. CUDA、SU、MPI和Madagascar混合编程的Makefile文件配置
  6. adb 查看屏幕大小_蚂蚁森林自动收取能量、偷取能量、浇水(使用adb、python)...
  7. java查找一个数等于一组数中哪些数字相加的和_快速入门二分查找
  8. oracle下创建id自增长
  9. Python装饰器的原理与应用
  10. Html文档与基本语法和规范
  11. 从排序开始(三)归并排序
  12. LaTeX报告用模板
  13. Java 数据字典的实现
  14. 记录下selenium登陆126邮箱
  15. 软件测试薪资标准,软件测试月薪过万需要具备哪些技能?
  16. matplotlib折线图与柱状图绘制在一起
  17. Docker 安装最新版禅道16.5版本 原创
  18. x41t下使用工行华虹u盾
  19. 从零开始学习 wireshark过滤规则 8月19日
  20. Python计算机视觉之全景图像拼接

热门文章

  1. 2017年微商软文推广写作技巧
  2. 高效软文营销写作技巧:产生共鸣方是王道
  3. heic转换jpg软件
  4. 初学者python编辑器_Thonny:适合初学者的Python编辑器
  5. Word / PowerPoint Alt + = 快捷键失效问题
  6. 南方电网招聘计算机考题,2019年南方电网人才招聘笔试真题计算机类题库(156)...
  7. 硕士毕业论文该如何开题?
  8. 京东神券:新年满500-40、1000-80、3000-240神券,每满200-30京贴 新年补贴 可叠万券
  9. Ubuntu 安装Flatabulous扁平化风格的桌面主题
  10. kad连接不上解决方法