react基本语法总结?

x33g5p2x  于2022-05-11 转载在 其他  
字(20.5k)|赞(0)|评价(0)|浏览(495)

1、js和jsx有什么区别,为什么要使用jsx

  1. // ①jsx的使用
  2. <script type="text/babel">
  3. const VDOM = <h1 id='title'>hell,react</h1>
  4. ReactDOM.render(VDOM, document.getElementById('test'))
  5. </script>
  1. js的使用
  2. <script type="text/javascript">
  3. const VDOM = React.createElement('h1', {id:'title'}, 'hello react')
  4. ReactDOM.render(VDOM, document.getElementById('test'))
  5. </script>
  1. 使用js而不使用jsx的原因是:程序员写jsx会使代码更加简洁,而使用js来创建虚拟DOM,则会显得更加繁琐。虽然在jsx在执行bable转化的使用,仍然转化成js

2、react虚拟dom和真实dom的区别?

  1. <script type="text/babel">
  2. const VDOM = <h1>hello,react</h1>
  3. const TDOM = document.getElementById('test')
  4. ReactDOM.render(VDOM, document.getElementById('test'))
  5. console.log('虚拟DOM:',VDOM)
  6. console.log('真实DOM:',TDOM)
  7. debugger;
  8. </script>
  1. 1、虚拟dom其实只是一个对象
  2. 2、虚拟dom比较“轻”, 真实dom比较"重",原因是react中的虚拟dom只是将抽离出一些可以用得到的属性,但是在真实dom中会加载全部属性。
  3. 3、虚拟dom存放在内存中,等到使用完成后,就会转化成真实dom,呈现在真实的页面上。

3、什么是XML,为什么会将XML换成json

  1. <students>
  2. <name>TOM</name>
  3. <age>20</age>
  4. </students>
  1. 缺点:数据保存少,需要消耗的空间多,所有才有了JOSN数据类型

4、JSX语法

  1. 1、定义虚拟dom的时候,不需要写引号
  2. 2、标签中混入js表达式时要使用{}
  3. 3、样式的类名指定不要使用class,而是使用className
  4. 4、内联样式,需要使用style={{color:value}}的形式去写
  5. 5、只有一个根标签
  6. 6、标签必须闭合
  7. 7、标签首字母
  8. (1)若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错
  9. (2)若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错、

5、在jsx中使用的是js表达式,注意和js语句之间的区别

  1. <script type="text/babel">
  2. const data = ['vue','react', 'angular']
  3. const VDOM = (
  4. <ul>
  5. {
  6. // 使用大括号中间放的是js表达式,注意和js语句之间的区别
  7. data.map((item,index)=> {
  8. return <li key={index}>{item}</li>
  9. })
  10. }
  11. </ul>
  12. )
  13. ReactDOM.render(VDOM, document.getElementById('test'))
  14. </script>
  1. js表达式有:
  2. 1a
  3. 2a + b
  4. 3arr.map()
  5. 4function test()
  6. 5、函数调用 demo(1)
  7. js语句有:
  8. 1if语句
  9. 2for循环语句
  10. 3switch语句

5、函数式组件

  1. 1、基本实现
  2. <script type="text/babel">
  3. //创建函数式组件
  4. function MyComponent () {
  5. return <h2>这里是函数式组件</h2>
  6. }
  7. //执行render渲染操作
  8. ReactDOM.render(<MyComponent/>, document.getElementById('test'))
  9. </script>
  10. 执行函数式组件的步骤流程:
  11. 1、先找到MyComponent函数式组件
  12. 2、然后将返回的虚拟dom渲染成真实的dom
  13. 3、最后展示到页面上

6、类组件

  1. <script type="text/babel">
  2. class MyComponent extends React.Component {
  3. render() {
  4. console.log(this)
  5. return <h1>这里是类组件的实现</h1>
  6. }
  7. }
  8. ReactDOM.render(<MyComponent/>, document.getElementById('test'))
  9. </script>
  1. 注意事项:
  2. 1、需要继承React.Component
  3. 2、可以没有构造函数。

类式组件的执行流程

  1. 1React解析先找到MyComponent组件
  2. 2、发现该组件是通过类进行定义的,首先通过new一个实例对象,然后调用实例对象中的render方法。
  3. 3、将render返回的虚拟dom转化成真是的dom,随后展示到页面上。

7、设置点击事件

  1. 1ES6中的事件默认开启局部严格模式
  2. 2 babel在进行转化js文件的时候,会避免this指向window,而是让this的值赋值给undefined
  1. <script type="text/babel">
  2. class MyComponent extends React.Component {
  3. constructor(props) {
  4. super(props)
  5. this.state = {
  6. isHot : false
  7. }
  8. this.changeWeather = this.changeWeather.bind(this)
  9. }
  10. render() {
  11. const {isHot} = this.state
  12. return <h1 onClick={this.changeWeather}>今天天气真{isHot ? '炎热' : '寒冷'}</h1>
  13. }
  14. changeWeather() {
  15. this.setState({
  16. isHot:!this.state.isHot
  17. })
  18. }
  19. }
  20. ReactDOM.render(<MyComponent/>,document.getElementById('test'))
  21. </script>
  1. //注意事项:
  2. 1、在调用函数的时候注意this的指向,可以使用bind
  3. 2、更改state中的值的时候,必须使用setState函数来进行更改,传入的参数是对象,是抽取更改不是全部覆盖。
  4. 3、在执行过程中,构造函数执行1次,render函数执行1 + nn为修改的次数),changeWeather函数执行n次,n为点击的次数。

8、apply和call以及bind之间的区别?
1、bind方法

  1. 1bind第一个参数为this指向的对象,第二个参数到第n个参数均为传入的值
  2. 2bind的传入参数之后,需要再次进行调用
  3. 3、每次执行bind方法时都会新建一个函数
  4. 4、自己实现简单的bind方法
  5. 5、如果直接在bind后面只有一个括号,不能实现函数调用。
  6. Function.prototype.my_bind = function (context) {
  7. let self = this
  8. return function () {
  9. return self.apply(context, arguments)
  10. }
  11. }
  12. function add (c, d) {
  13. return this.x + c + d
  14. }
  15. console.log(add.bind({x:100}, 10, 1)())

二、call方法

  1. 1、第一个参数是this指向的对象,第二个参数到第n个参数是需要传入的值。
  2. 2、方法.call()可以实现函数调用。

三、apply方法

  1. 1 第一个参数是this指向的对象,第二个参数是一个数组,也可以是arguments
  2. 2、方法.apply()也可以实现函数调用

9、触发事件的简写形式

  1. <script type="text/babel">
  2. class Weather extends React.Component {
  3. state = { ----------------------------------①
  4. isHot:true
  5. }
  6. render() {
  7. const {isHot} = this.state
  8. return <h1 onClick={this.changeWeather}>今天天气是{isHot ? '炎热' : '寒冷'}</h1>
  9. }
  10. changeWeather = () => { --------------------------②
  11. this.setState({
  12. isHot:!this.state.isHot
  13. })
  14. }
  15. }
  16. ReactDOM.render(<Weather />, document.getElementById('test'))
  17. </script>
  1. 1、如果某一些属性不需要外部来传入,可以像①处这样写
  2. 2、可以将方法也不放在原型对象上,直接放在该类中,这里需要使用箭头函数,类似于图中的②
  3. 3、注意事件的书写格式上,需要将onclick写成onClick

11、类组件中的props属性

  1. <script type="text/babel">
  2. class Person extends React.Component {
  3. render() {
  4. const {name,age,sex} = this.props
  5. console.log(this)
  6. return (
  7. <ul>
  8. <li>姓名:{name}</li>
  9. <li>性别:{sex}</li>
  10. <li>年龄:{age}</li>
  11. </ul>
  12. )
  13. }
  14. }
  15. ReactDOM.render(<Person name="董礼" age="20" sex="男" />, document.getElementById('test'))
  16. </script>
  1. 1、在每一个实例组件对象中都会存在一个属性props
  2. 2、可以直接在组件进行传值

11、对象解构

  1. <script>
  2. let p1 = {name:'张三',age:20, sex:'男'}
  3. let p2 = {...p1}
  4. p1.name = '李四'
  5. console.log(p1) //{name:'李四',age:20, sex:'男'}
  6. console.log(p2) //{name:'张三',age:20, sex:'男'}
  7. </script>
  1. 对象如果想要结构必须使用{...对象名},这样得到的就是另一个对象。

可以在给类组件传入参数时进行解构处理

  1. 原因:因为该文件是reactbabel一起结合使用的,只能在组件标签中使用对象的解构。
  1. <script type="text/babel">
  2. class Person extends React.Component {
  3. render () {
  4. const {name, age, sex} = this.props
  5. return (
  6. <ul>
  7. <li>姓名:{name}</li>
  8. <li>年龄:{age}</li>
  9. <li>性别:{sex}</li>
  10. </ul>
  11. )
  12. }
  13. }
  14. let p1 = {name:"张三", age:'20', sex: "男"}
  15. ReactDOM.render(<Person {...p1}/>, document.getElementById('test'))
  16. </script>

12、
设置传入props的数据类型以及是否被需要,并且可以设置props的属性默认值。

  1. <script type="text/babel">
  2. class Person extends React.Component {
  3. render() {
  4. const { name, age, sex ,speak} = this.props
  5. console.log(speak)
  6. return (
  7. <ul>
  8. <li>姓名:{name}</li>
  9. <li>年龄:{age + 1}</li>
  10. <li>性别:{sex}</li>
  11. </ul>
  12. )
  13. }
  14. }
  15. // 设置类型
  16. Person.propTypes = {
  17. name:PropTypes.string.isRequired,
  18. age:PropTypes.number.isRequired,
  19. sex:PropTypes.string.isRequired,
  20. speak:PropTypes.func,
  21. }
  22. // 设置默认值
  23. Person.defaultProps = {
  24. name:'董沐辰',
  25. age:20,
  26. sex:'女'
  27. }
  28. const p1 = {}
  29. ReactDOM.render(<Person {...p1}/>, document.getElementById('test'))
  30. ReactDOM.render(<Person name="李四" age={20} sex="男" speak = {speak}/>, document.getElementById('test1'))
  31. function speak() {
  32. console.log('我要说话')
  33. }
  1. 1、这里还可以给函数类型限制,注意函数类型限制的类型必须是func,数字和字符串类型的限制必须使用小写。
  2. 2、如果需要给组件标签传入js代码,则必须使用{}来表示。

13、将该组件类中的属性设置为类的静态属性

  1. <script type="text/babel">
  2. class Person extends React.Component {
  3. render() {
  4. const {name,age,sex} = this.props
  5. return (
  6. <ul>
  7. <li>姓名:{name}</li>
  8. <li>年龄:{age}</li>
  9. <li>性别:{sex}</li>
  10. </ul>
  11. )
  12. }
  13. static propTypes = {
  14. name:PropTypes.string.isRequired,
  15. sex:PropTypes.string,
  16. age:PropTypes.number
  17. }
  18. static defaultProps = {
  19. name:'张三',
  20. }
  21. }
  22. let p1 = {name:'张三',age:20, sex:'男'}
  23. ReactDOM.render(<Person {...p1}/>, document.getElementById('test'))
  24. </script>

14、类中的构造器

  1. //组件类的构造器的作用:
  2. <script type="text/babel">
  3. class Person extends React.Component {
  4. constructor(props) {
  5. super(props)
  6. console.log('constructor', this.props)
  7. }
  8. render() {
  9. const {name,age,sex} = this.props
  10. return (
  11. <ul>
  12. <li>姓名:{name}</li>
  13. <li>年龄:{age}</li>
  14. <li>性别:{sex}</li>
  15. </ul>
  16. )
  17. }
  18. static propTypes = {
  19. name:PropTypes.string.isRequired,
  20. sex:PropTypes.string,
  21. age:PropTypes.number
  22. }
  23. static defaultProps = {
  24. name:'张三',
  25. }
  26. }
  27. let p1 = {name:'张三',age:20, sex:'男'}
  28. ReactDOM.render(<Person {...p1}/>, document.getElementById('test'))
  29. </script>
  1. 官网上的constructor的两种用法:
  2. 1、通常,在react中,构造函数仅用于以下两种情况。
  3. 通过给this.state赋值对象类初始化内部的state
  4. 为事件处理函数绑定实例。
  5. 第一个我们使用属性实现,第二个我们使用箭头函数实现
  6. 其实构造函数可以不进行使用,如果我们想要在构造函数中使用this.props,则必须传入props以及使用super(props)进行传值、

15、函数式组件

  1. <script type="text/babel">
  2. function Person(props) {
  3. const {name, age, sex} = props
  4. return (
  5. <ul>
  6. <li>姓名:{name}</li>
  7. <li>年龄:{age}</li>
  8. <li>性别:{sex}</li>
  9. </ul>
  10. )
  11. }
  12. Person.propTypes = {
  13. name:PropTypes.string.isRequired,
  14. age:PropTypes.number,
  15. sex:PropTypes.string
  16. }
  17. Person.defaultProps = {
  18. name:'李四',
  19. age:300,
  20. sex:'女'
  21. }
  22. ReactDOM.render(<Person/>, document.getElementById('test'))
  23. </script>
  1. 在函数是组件中,需要注意的事项:
  2. 1、目前函数式组件没有this,但是只能得到props属性。
  3. 2、函数式组件中没有staterefs
  4. 3、函数式组件可以通过给组件传属性,最终传入props中,并且可以给属性设置类型限制和设置默认值。

16、refs和ref的使用

  1. <script type="text/babel">
  2. class Demo extends React.Component {
  3. set = () => {
  4. const {input1} = this.refs
  5. alert(input1.value)
  6. }
  7. bule= () => {
  8. const {input2} = this.refs
  9. alert(input2.value)
  10. }
  11. render() {
  12. return (
  13. <div>
  14. <input ref="input1" type="text" placeholder="点击"/>&nbsp;
  15. <button onClick={this.set}>点击我触发左侧事件</button>&nbsp;
  16. <input ref="input2" onBlur={this.bule} type="text" placeholder="失去焦点"/>
  17. </div>
  18. )
  19. }
  20. }
  21. ReactDOM.render(<Demo/>, document.getElementById('test'))
  22. </script>
  1. 1、可以通过ref来获取该标签。
  2. 2refs中包含了这个类组件对象中的全部的ref

17、ref使用回调函数的形式,ref=字符串的形式效率太低。

  1. <script type="text/babel">
  2. class Person extends React.Component {
  3. set = () => {
  4. const {input1} = this
  5. alert(input1.value)
  6. }
  7. blur = () => {
  8. const {input2} = this
  9. alert(input2.value)
  10. }
  11. render() {
  12. return (
  13. <div>
  14. <input ref={(currentNode)=> {this.input1 = currentNode}} type="text" placeholder='点击'/>
  15. <button onClick={this.set}>点击</button>
  16. <input ref={(currentNode) => {this.input2 = currentNode}} type="text" onBlur ={this.blur} placeholder='失去焦点'/>
  17. </div>
  18. )
  19. }
  20. }
  21. ReactDOM.render(<Person/>, document.getElementById('test'))
  22. </script>
  1. 1、如果ref=回调函数,比如使用{}把其括起来。
  2. 2、并且使用箭头函数的形式,因为箭头函数中的this指向的是这个实例对象本身。
  3. 3ref传入的参数是该节点的对象,使用this.input = currentNode ,是向这个实例对象上面赋值.
  4. 4、最后在触发的方法中使用解构对this进行解构即可。
  5. 5、这里中的refreact自动帮我们调用的函数。

18、ref设置内联函数和绑定函数的区别
1、内联函数

  1. 当页面发生改变的时候,页面会重新渲染,内联函数会执行两次,第一次传入的currentNode的值是null,第二次传入的是才是这个节点。
  1. <script type="text/babel">
  2. class Demo extends React.Component {
  3. state = {
  4. isHot:true
  5. }
  6. set = ()=> {
  7. const {input1} = this
  8. alert(input1.value)
  9. }
  10. changeWeather=() => {
  11. this.setState({
  12. isHot: !this.state.isHot
  13. })
  14. }
  15. render () {
  16. const {isHot} = this.state
  17. return (
  18. <div>
  19. <h1>天气是{isHot ? '炎热' : '寒冷'}</h1>
  20. <input type="text" ref={(currentNode)=> {this.input1 = currentNode;console.log('@@',currentNode)}}/>
  21. <button onClick={this.set}>点击展示数据</button>
  22. <button onClick={this.changeWeather}>点击修改天气</button>
  23. </div>
  24. )
  25. }
  26. }
  27. ReactDOM.render(<Demo/>, document.getElementById('test'))
  28. </script>

2、绑定函数 如果使用绑定函数的时候,当页面发生变化的时候,只会执行一次,并且传给currentNode的值,就是该节点。

  1. <script type="text/babel">
  2. class Demo extends React.Component {
  3. state = {
  4. isHot:true
  5. }
  6. set = ()=> {
  7. const {input1} = this
  8. alert(input1.value)
  9. }
  10. changeWeather=() => {
  11. this.setState({
  12. isHot: !this.state.isHot
  13. })
  14. }
  15. sss = (currentNode) => {
  16. this.input1 = currentNode
  17. console.log('@@', currentNode)
  18. }
  19. render () {
  20. const {isHot} = this.state
  21. return (
  22. <div>
  23. <h1>天气是{isHot ? '炎热' : '寒冷'}</h1>
  24. <input type="text" ref={this.sss}/>
  25. <button onClick={this.set}>点击展示数据</button>
  26. <button onClick={this.changeWeather}>点击修改天气</button>
  27. </div>
  28. )
  29. }
  30. }
  31. ReactDOM.render(<Demo/>, document.getElementById('test'))
  32. </script>

两者中第一个在开发中使用的频率高
第三种实现ref的方式

  1. <script type="text/babel">
  2. class Demo extends React.Component {
  3. myRef = React.createRef()
  4. myRef1 = React.createRef()
  5. set = ()=> {
  6. alert(this.myRef.current.value)
  7. }
  8. blur = () => {
  9. alert(this.myRef1.current.value)
  10. }
  11. render() {
  12. return (
  13. <div>
  14. <input ref={this.myRef} type="text" placeholder='点击'/>
  15. <button onClick={this.set}>点击</button>
  16. <input onBlur={this.blur} ref={this.myRef1} type="text" placeholder='失去焦点'/>
  17. </div>
  18. )
  19. }
  20. }
  21. ReactDOM.render(<Demo/>, document.getElementById('test'))
  22. </script>
  1. 1、这里使用React.createRef()这个API来进行创建。
  2. 2、在类对象实例上进行设置。
  3. 3、每一个React.createRef()只能使用一次。

19、react中的事件处理

  1. 1、注意事件的大小写,例如点击事件必须写成onClick
  2. 原因:因为需要考虑到事件的兼容性问题,并且和原来的事件区分开。
  3. 2React中事件是通过事件委托的方式处理的(将事件委托给最外层的元素)使用的原理是事件冒泡。
  4. 为了高效
  5. 3、可以通过event.target得到发生事件的DOM元素的对象,原因是不能过度的使用ref
  1. <script type="text/babel">
  2. class Demo extends React.Component {
  3. blur = (event) =>{
  4. console.log(event.target.value)
  5. }
  6. render() {
  7. return (
  8. <div>
  9. <input onBlur= {this.blur} type="text"/>
  10. </div>
  11. )
  12. }
  13. }
  14. ReactDOM.render(<Demo/>, document.getElementById('test'))
  15. </script>

20、事件委托

  1. 1、事件委托利用的原理是事件冒泡。
  2. 2、事件委托减少操作dom的次数,可以极大解决性能的问题。
  3. 3、事件委托可以减少设置事件,减少内存占有。

21、非受控组件

  1. <script type="text/babel">
  2. class Form extends React.Component {
  3. submitForm = (event) => {
  4. event.preventDefault()
  5. const {username, password} = this
  6. alert(`提交的用户姓名为:${username.value},用户密码为:${password.value}`)
  7. }
  8. render() {
  9. return (
  10. <form action="https://www.baidu.com" onSubmit ={this.submitForm}>
  11. 用户名:<input type="text" name="username" ref={c=> this.username = c}/>
  12. 密码:<input type="password" name="password" ref={c=> this.password = c}/>
  13. <button>点击提交</button>
  14. </form>
  15. )
  16. }
  17. }
  18. ReactDOM.render(<Form/>, document.getElementById('test'))
  19. </script>
  1. 1、当在form表单中提交的时候,触发的事件是onSubmit事件。
  2. 2event.preventDefault()表示阻止默认事件。
  3. 3、非受控组件就是什么时候需要用到ref表示的标签什么时候取出来即可。

22、受控组件

  1. <script type="text/babel">
  2. class Form extends React.Component {
  3. state = {
  4. username:'',
  5. password: ''
  6. }
  7. nameChange = (event) => {
  8. this.setState({
  9. username:event.target.value
  10. })
  11. }
  12. passChange = (event) => {
  13. this.setState({
  14. password:event.target.value
  15. })
  16. }
  17. render() {
  18. return (
  19. <form action="">
  20. 姓名:<input type="text" onChange={this.nameChange}/>
  21. 密码:<input type="password" onChange={this.passChange}/>
  22. </form>
  23. )
  24. }
  25. }
  26. ReactDOM.render(<Form/>, document.getElementById('test'))
  27. </script>

受控组件和非受控组件的区别

  1. 1、受控组件,随时都能获取到组件中对应的值,类似于vue中的数据的双向绑定。
  2. 2、非受控组件,只有需要的时候才能获取到组件中对应的值,例如当提交表单时,才会获取表单中的对应的input框中的值。
  3. 3、而且我们在项目中最好使用受控组件。

对上面的受控组件进行化简

  1. <script type="text/babel">
  2. class Form extends React.Component {
  3. state = {
  4. username:'',
  5. password:''
  6. }
  7. saveFormData = (data) => {
  8. return (event) => {
  9. this.setState({
  10. [data]:event.target.value
  11. })
  12. }
  13. }
  14. render() {
  15. return (
  16. <form action="">
  17. 用户名:<input type="text" onChange = {this.saveFormData('username')}/>
  18. 密码:<input type="text" onChange = {this.saveFormData('password')}/>
  19. </form>
  20. )
  21. }
  22. }
  23. ReactDOM.render(<Form/>, document.getElementById('test'))
  24. </script>

设置saveFormData通过对其传入属性名,从而进行封装,避免代码冗余
23、高阶函数

  1. 定义:如果一个函数传入的参数是一个函数,或者返回的是一个函数,这两类满足其一,即可成该函数为高阶函数。

柯里化:

  1. //代码如下所示即为柯里化,或者正如saveFormData这个函数就是柯里化
  2. function set(a) {
  3. return function (b) {
  4. return function (c) {
  5. return a + b + c
  6. }
  7. }
  8. }
  9. console.log(set(1)(2)(4))

在不使用柯里化和高阶函数的前提下,重写上述代码

  1. <script type="text/babel">
  2. class Form extends React.Component {
  3. state = {
  4. username: '',
  5. password: ''
  6. }
  7. saveFormData(dataType, event) {
  8. this.setState({
  9. [dataType]:event.target.value
  10. })
  11. }
  12. render() {
  13. return (
  14. <form action="">
  15. 用户名:<input type="text" onChange = {event=>this.saveFormData('username', event)}/> ----------------①
  16. 密码:<input type="text" onChange = {event =>this.saveFormData('password', event)}/> ----------------——②
  17. </form>
  18. )
  19. }
  20. }
  21. ReactDOM.render(<Form />, document.getElementById('test'))
  22. </script>

24、react生命周期

  1. <script type="text/babel">
  2. class Life extends React.Component {
  3. state = {
  4. opacity: 1
  5. }
  6. remove = () => {
  7. // 卸载组件
  8. ReactDOM.unmountComponentAtNode(document.getElementById('test'))
  9. }
  10. // 组件挂载完毕
  11. componentDidMount() {
  12. console.log('组件挂载完毕')
  13. this.timer = setInterval(() => {
  14. let {opacity} = this.state
  15. opacity -= 0.1
  16. this.setState({
  17. opacity
  18. })
  19. if(opacity <= 0){ //这里不使用opacity == 0的原因是:因为js中小数相减存在误差
  20. this.setState({
  21. opacity:1
  22. })
  23. }
  24. },200)
  25. }
  26. // 在卸载组件之前
  27. componentWillUnmount() {
  28. console.log('组件卸载之前')
  29. clearInterval(this.timer)
  30. }
  31. render() {
  32. console.log('render')
  33. return (
  34. <div>
  35. <h1 style={{opacity:this.state.opacity}}>学不会React生命周期怎么办</h1> --------------------①
  36. <button onClick={this.remove}>不活了</button>
  37. </div>
  38. )
  39. }
  40. }
  41. ReactDOM.render(<Life/>, document.getElementById('test'))
  42. </script>
  1. 1ReactDOM.unmountComponentAtNode(document.getElementById('test'))表示卸载某一个组件。
  2. 2componentDidMount表示组件挂在成功。
  3. 3componentWillUnmount表示组件将要被写在之前。
  4. 4、组件中的render函数是在组件第一次渲染,以及后面的状态state中的值发生变化的时候,执行调用。
  5. 5、执行顺序是render -> componentDidMount -> componentWillUnmount
  6. 6、注意在掺入样式的时候需要使用双括号,正如①所示
  7. 出现错误:Can't perform a React state update on an unmounted component.
  8. 原因是无法在没有挂载的组件中修改state中的值。本例中是在清空之前关闭定时器。

25、声明周期

  1. <script type="text/babel">
  2. class Count extends React.Component {
  3. // 构造函数
  4. constructor(props) {
  5. console.log('现在执行constructor中的函数')
  6. super(props)
  7. }
  8. state = {
  9. count:1
  10. }
  11. changeCount = () => {
  12. let {count} = this.state
  13. this.setState({
  14. count:++count
  15. })
  16. }
  17. // 组件挂载之前
  18. componentWillMount() {
  19. console.log('现在执行componentWillMount中的函数')
  20. }
  21. // 组件挂载完成
  22. componentDidMount() {
  23. console.log('现在执行componentDidMount中的函数')
  24. }
  25. render() {
  26. console.log('现在执行render中的函数')
  27. return (
  28. <div>
  29. <h1>当前的数字是:{this.state.count}</h1>
  30. <button onClick ={this.changeCount}>点击+1</button>
  31. </div>
  32. )
  33. }
  34. }
  35. ReactDOM.render(<Count/>, document.getElementById('test'))
  36. </script>

最终的结果是:

  1. 现在执行constructor中的函数
  2. 现在执行componentWillMount中的函数
  3. 现在执行render中的函数
  4. 现在执行componentDidMount中的函数

26、countcount,以及count = count++以及count = ++ count之间的区别

  1. 1count++和++count都具有自增1的效果。
  2. 2count=count++没有自增的效果。
  3. 3count=++count有自增的效果。

29、setState()执行步骤

注意:当执行到shouldComponentUpdate的时候,需要返回一个Boolen值为true才能继续。
30、forceUpdate()进行强制更新状态

  1. 使用场景:当不需要更改状态,但是想要强制更新调用render可以通过forceUpdate进行。

31、关于父子渲染中触发的生命周期函数

  1. <script type="text/babel">
  2. class Father extends React.Component {
  3. state = {
  4. myCar : '保时捷'
  5. }
  6. changeCar = () => {
  7. this.setState({
  8. myCar:'奔驰C300'
  9. })
  10. }
  11. render() {
  12. return (
  13. <div>
  14. <h1>我有一辆车</h1>
  15. <button onClick ={this.changeCar}>我要换车</button>
  16. <Son myCar = {this.state.myCar}/>
  17. </div>
  18. )
  19. }
  20. }
  21. class Son extends React.Component {
  22. render() {
  23. console.log('render')
  24. return (
  25. <div>
  26. <h4>我是子组件</h4>
  27. <h4>{this.props.myCar}</h4>
  28. </div>
  29. )
  30. }
  31. componentWillReceiveProps(props) {
  32. console.log("componentWillReceiveProps")
  33. console.log(props)
  34. }
  35. shouldComponentUpdate() {
  36. console.log('shouldComponentUpdate')
  37. return true
  38. }
  39. componentWillUpdate() {
  40. console.log('componentWillUpdate')
  41. }
  42. componentDidUpdate() {
  43. console.log("componentDidUpdate")
  44. }
  45. }
  46. ReactDOM.render(<Father/>, document.getElementById('test'))
  47. </script>
  1. 注意:componentWillReceiveProps第一次传入值的时候,不触发,第二次才进行触发
  2. shouldComponentUpdate必须return true才能向下进行。

32、getDerivedStateFromProps

  1. static getDerivedStateFromProps(nextProps,nextState){
  2. if(nextProps.value!==undefined){
  3. return {
  4. current:nextProps.value
  5. }
  6. }
  7. return null
  8. }
  1. 简单来说,getDerivedStateFromProps的执行时机就是在组件初始化的时候以及组件后续更新的时候。同时getDerivedStateFromProps也可以最早的在父传子的时候获取到父组件传递给子组件的属性。由此可见,getDerivedStateFromProps很好的代替了componentWillMount以及componentWillReceiveProps

33、getSnapshotBeforeUpdate

  1. getSnapshotBeforeUpdate取代了componentWillUpdate
  2. 发时机为update发生的时候,在render之后、dom渲染之前返回一个值,作为componentDidUpdate的第三个参数。
  1. 简答的应用场景:
  2. //s比如列表更新后新的数据不断插入到数据前面,如何保证可视区依旧是之前看到的呢?(详细案例可以查看官网)
  3. getSnapshotBeforeUpdate(){
  4. return this.refs.wrapper.scrollHeight
  5. }
  6. componentDidUpdate(prevProps,prevState,preHeight){
  7. this.refs.wrapper.scrollTop+=this.refs.wrapper.scrollHeight-preHeight
  8. }
  9. .....

35、diff算法

  1. diff算法实现步骤:
  2. 1、首先获取状态更改的信息,将全部的状态数据转化成新的虚拟DOM
  3. 2 将新的虚拟DOM和原来的虚拟DOM进行比对,根据key的值进行比对。
  4. 3、如果key相同,并且其中的内容也相同,则直接使用原来的虚拟DOM
  5. 4、如果key没有相同的,则直接将新的虚拟DOM渲染成真实DOM
  6. 5、如果key相同,并且其中也存在其他标签,也需要进行其他标签的比对,如果相同则继续使用。
  7. 6diffing算法最低层次是标签。
  8. 7diffing算法一般的keyid或者其他具有唯一性的值作为键。

36、React脚手架

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8" />
  5. <!-- %PUBLIC_URL%作用就是指明图标所在文件是public文件 -->
  6. <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
  7. <!-- 进行移动端适配 -->
  8. <meta name="viewport" content="width=device-width, initial-scale=1" />
  9. <!-- 设置安卓中的搜索框中的颜色 -->
  10. <meta name="theme-color" content="#000000" />
  11. <!-- 设置搜索引擎的搜索关键字 -->
  12. <meta
  13. name="description"
  14. content="Web site created using create-react-app"
  15. />
  16. <!-- ios手机中添加某一个特定的网页添加到手机主屏幕后的图标 -->
  17. <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
  18. <!-- 用于手机加壳 -->
  19. <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
  20. <title>React App</title>
  21. </head>
  22. <body>
  23. <!-- 当浏览器中不支持js的时候,才展示该标签 -->
  24. <noscript>You need to enable JavaScript to run this app.</noscript>
  25. <!-- 页面渲染的跟路径 -->
  26. <div id="root"></div>
  27. </body>
  28. </html>

37、CSS模块化

  1. 出现的原因:
  2. 当不同组件中的Css样式中存在重名的情况,当最终引入到APP.js中只会导致后面组件的样式会将前面组件的样式覆盖掉。

解决方案:

  1. 给每一个css样式文件中间添加一个modules
  2. 并且引入的时候类似于引入js

看下方的代码:

  1. import { Component } from "react";
  2. import HelloCss from './Hello.module.css'
  3. export default class Hello extends Component {
  4. render() {
  5. return (
  6. <h1 className={HelloCss.Welcome}>hello组件</h1>
  7. )
  8. }
  9. }

38、React中配置代理
第一种配置代理的方法:

  1. package.json中增添了一个属性proxyhttp://localhost:5000

具体如下图所示

  1. package.json中追加的如下配置:
  2. 优点:配置简单,前端请求资源时可以不加任何前缀。
  3. 缺点:不能配置多个代理。

配置方法二:

  1. src下创建配置文件:src/setupProxy.js
  1. 编写setupProxy.js配置具体代理规则:
  2. const proxy = require('http-proxy-middleware')
  3. module.exports = function(app) {
  4. app.use(
  5. proxy('/api1', { //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
  6. target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
  7. changeOrigin: true, //控制服务器接收到的请求头中host字段的值
  8. /*
  9. changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
  10. changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
  11. changeOrigin默认值为false,但我们一般将changeOrigin值设为true
  12. */
  13. pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
  14. }),
  15. proxy('/api2', {
  16. target: 'http://localhost:5001',
  17. changeOrigin: true,
  18. pathRewrite: {'^/api2': ''}
  19. })
  20. )
  21. }
  1. 说明:
  2. 1、优点:可以配置多个代理,可以灵活的控制请求是否走代理。
  3. 2、缺点:配置繁琐,前端请求资源时必须加前缀。

相关文章