react-组件

react 02 - 组件

react中的组件定义方式有两种: 函数组件(无状态/UI组件) 类组件(状态组件/容器组件)
react组件一定要有返回值: 描述页面展示内容的React元素(jsx)

2.1 组件的创建方式

函数组件创建

函数组件本质: 就是一个函数

  • 要满足一下要求:
  1. 函数名首字母要大写,因为jsx要求在组件调用的时候首字母要大写
  2. 函数组件可以接受一个参数,此参数可以是任意类型的数据,用来获取父组件的数据(父子组件传值细说)
  3. 函数必须返回一个jsx,并且jsx必须要有一个顶层元素包裹,也可以返回null, 18之后还可以返回undefined
  4. 定义好的函数一定要通过默认导出: export default 函数名
import React from 'react';
const AppFunction = () => {
  return (
    
具体的页面内容
); } export default AppFunction;

安装插件: js jsx Snippets ===> rfc 可以快速创建模版代码

类组件创建

类组件: 一个类

  • 要求:
  1. 只能使用es6中的类来定义类组件, 类名必须要大写
  2. 此类必须继承一个 React.Component 父类
  3. 此类中必须要重写 render方法,且此方法中必须要返回return一个 jsx/null/undefined
  4. 此类要导出,默认导出
import React from "react";

class App extends React.Component {
   render(){
    return (
      

class组件

) } } export default App

快捷方式: rcc
函数具有二义性 : 在js中函数可以被当作构造函数通过new来调用,为了和类区分用new.target来判断是否是被new执行的

function Person(){
// 用new.target 来禁用函数被new, 只能当作函数来调用
    if(new.target){
        throw new Error('如果不是通过new执行的就返回undefined, 报次错误')
    }
}

2.2 react父子组件传值

在react中一个函数一个类就是一个组件,区别与vue(一个文件就是一个组件),所以react中可以有多个组件

  • 函数组件的父子间传值
  1. 单向数据流,只能父向子传值,父组件通过在调用子组件的时候添加自定义属性来传值
  2. 子组件接受props参数来获取父组件的传值, 可以直接接受props对象,也可以解构并赋予初值
  3. 子组件中props的值是只读的,不可修改
import React from 'react';

// const Child = (props) => {  // 两种接受props的方式,一种可以直接接受整个props,但有个问题 ,在子组件中使用的时候,要通过对象调用的方式一个一个向外拿
const Child = ({title,num ='第二种:props是个对象,所以可以直接将里面的内容结构出来,还可以结构的同时进行赋初值'}) => {
  // console.log(props)
  return (
    
{/*

子组件 --{props.title}

*/}

子组件 --{title} {num}

); } const AppProps01 = () => { const title = '我是父组件传过来的标题' const num = undefined return (

父组件

{/* 父组件,他是通过自定义属性的方式向子组件传递数据‘props’ props是只读属性并且是单向数据流,只能父传递给子 ,子只能读取值,不能修改值 */} {/* 调用自组建 */}
); } export default AppProps01;
  • 类组件的父子间传值
  1. props单向数据流,父向子传值,只读属性
  2. 区别去函数组件中的传值方式: 类组件中的自定义属性传值时传递的是在类中定义的成员属性,并且一定要注意加this
  3. 子组件在接受父组件传过来的值时,在render函数中通过this.props成员属性来获取值,props依旧是对象形式的值,可以解构
import React, { Component } from 'react';
// 类组件间传值
class Child extends Component {
  //  类组件中的子组件通过成员属性 this.props 来获取父组件中传过来的值
  //  this.props 是一个对象
  render() {
    // console.log(this.props)
    const {title} = this.props
    return (
      

class子组件 -- {title}

); } } class AppClassProps01 extends Component { // es8以后的成员属性,可以不用在construct中定义 title = 'class父类中的标题' render() { return (

class父组件

{/* 在类组件中,获取成员属性和成员方法时 ,一定要通过this来获取 */}
); } } export default AppClassProps01;

面试题: TS中已经可以用联合属性来解决问题问什么还要用多态?

2.3 react事件

react中的事件分为原生事件和合成事件: 原生就是通过addEventLisenter的js操作进行的,而合成事件: 直接定义在react中的事件会被react处理,语法上有一些不同

要求

  1. 事件的命名严格采用小驼峰命名法
  2. jsx语法中当要传入一个函数作为事件的处理函数时,不能加小括号
  3. 在使用类组件时,还要注意this的指向问题,函数组件中没有这个问题

2.3.1 函数组件

import React from 'react';

const clickHandler2 = () => ()=>{
  console.log('webg == 我必搞')
}

 //定义在组件函数的上面,const var let 没有限制
 var clickHandler = () =>{
  console.log('clickHandler')
 }

const AppFunction01 = () => {
  return (
    
{/* 1, 函数名用小驼峰 2, 绑定的事件方法不能加小括号,并且如果将执行的函数体放在jsx下面(组件函数的后面)的时候,一定要用function 来定义函数 3, 因为return会中断后面的代码执行,要用function来声明方法,是的变量提升并赋值 */} {/* 如果想用小括号,那么事件绑定的是一个函数体就可以 */}
); } // function clickHandler(){ // console.log('clickHandler') // } // 小括号触发事件 // function clickHandler2(){ // return function(){ // console.log('wgb==我必搞') // } // } // function clickHandler2(){ // return ()=>{ // console.log('wbg === 我必搞') // } // } export default AppFunction01;

2.3.2 类组件

思考两个问题 1,this的指向问题 2,call、apply、bind的作用和用法都是什么

import React, { Component } from 'react';

class AppFunction02 extends Component {

  clickHandle1(){
    console.log('clickHandle1')
  }

  clickHandle3(){
    return ()=>{
      console.log('clcikHandler3')
    }
  }
  num = 100
  clickHandle4(){
    return ()=>{
      console.log( this.num )  // 这样不报错
    }
    // console.log(this.num)  // 这样就报错了,为什么, 解决方案可以用bind来改变this指向,为社么可以用bind解决
  }

  clickHandle5(){
    console.log(this.num)
  }

  render() {
    return (
      
{/* 类组件中的方法定义,不用关注方法的书写顺序是在return前还是return后 */} {/* 同样的如果要加小括号,可以用柯里化函数 */} {/* 类组件中有函数的调用有this指向问题 , */}
); } clickHandle2(){ console.log('clickHandle2') } } export default AppFunction02;

2.3.3合成事件

react将原生事件进行处理:将所有的事件都绑定到挂在节点,目的: 对事件进行统一代理,使dom上不用绑定事件也可以用react挟持事件触发来实现操作,进行性能优化 , 这样可以通过对原事件的优先级定义来确定真是事件的优先级,再进而确定真实事件内触发的更新是什么优先级,最终确定对应更新应在什么时机更新可以解决跨平台问题,抹平浏览器差异
react16之前绑定到body上,缺点: 只能有一个委托节点
16之后委托到挂载节点元素中(root),可以有多个委托节点,如果有多入口的操作应用时,可以分开委托(root1 , root2 ,…)
事件的执行分为: 捕获阶段 --> 目标阶段 --> 冒泡阶段

以类来举例

import React, { Component } from "react";

 class APPs extends React.Component {
  click() {
    console.log("合成-冒泡- click1")
  }
  clickCapture() {
    console.log('合成-捕获-click2')
  }
  componentDidMount() {
    // addEventListener("事件类型" , function(){事件函数} , boolean(true : 捕获阶段执行 / false: 冒泡阶段执行))
    document.getElementById('btn').addEventListener('click', () => {
      console.log('原生- 冒泡 - btnClick')
    }, false)

    document.getElementById('btn').addEventListener('click', () => {
      console.log('原生 - 捕获 - btnClick')
    }, true)

    document.getElementById('root').addEventListener('click', () => {
      console.log('原生 - 冒泡 - 顶层元素click')
    } , false )

    document.getElementById('root').addEventListener('click', () => {
      console.log('原生 - 捕获 - 顶层元素click')
    } , true )

    document.body.addEventListener('click' , () => {
      console.log('原生 - 冒泡 - bodyClick')
    } ,false )

    document.body.addEventListener('click' , ()=>{
      console.log('原生 - 捕获 - bodyClick')
     } , true)
  }
  render() {
    return (
      
) } } export default APPs

合成事件和原生事件相结合的具体执行顺序: body-原生-捕获 —> 目标元素上级各节点绑定合成事件的捕获(capture) —> root-原生-捕获 (这两个阶段可以看作委托的合成事件在挂载节点先执行,然后执行挂在节点的原生捕获) —> 目标元素-原生-捕获 —> 目标元素-原生-冒泡 —> 目标元素上级个节点绑定的合成事件的冒泡执行 —> root-原生-冒泡(捕获的回程冒泡)—> body-原生-冒泡
react中合成事件的冒泡函数就是正常默认的函数,捕获阶段的函数为: 莫某Capture事件
原生事件的绑定: addEventLisenter(‘事件类型’ , 事件函数 , true/false 控制冒泡/捕获执行) 默认为false=== 冒泡执行,true===捕获执行

2.3.4 事件阻止

event.stopPropergation() event.stopImmediatePropergation()

  1. 相同点: 都是用来阻止事件传播的
  2. 不同点: stopPropergation: 阻止当前元素之后的父级元素的冒泡事件执行,但是自身的其他事件的冒泡依旧可以执行, 而stopImmediatePropergation在js顺序执行到此事件时, 后面所有的事件都不在执行,包括当前元素自身的冒泡事件, 但书写顺序在此事件之前的冒泡事件不受影响(阻止当前元素中的未执行事件)

2.3.5合成事件模拟 — 实际就是做事件委托

react中为了减少元素增删时,相应绑定事件的销毁和再创建带来的性能损耗,将事件做成了合成事件,其实现原理如下

我是一个按钮

你可能感兴趣的:(react,react.js,javascript,前端)