React框架技术点

作者:陆金龙    发表时间:2023-02-28 09:33   

关键词:虚拟DOM  组件系统  JSX  React state  React props   useEffect  

1. React简介

React起源于Facebook的内部项目,该公司对当时市场上的所有javascript MVC 框架都不满意,认为MVC只会让前端越来越复杂,因此开发了React,用来架设 Instagram 的网站,并于 2013 年 5 月开源。

React只关注视图层,专注于提供view层解决方案。官方对React的定位是:一个快速构建前端视图的javaScript库。

虚拟DOM

React引入了虚拟DOM(virtual DOM)的机制:在浏览器端用javascript实现了一套DOM API。

React把真实 DOM 树转换成 JavaScript 对象树(虚拟DOM),每当数据变化时,React都会重新渲染整个DOM树。

每次更新时,React将当前DOM树和上一次DOM树进行对比,得到DOM结构的区别。只针对变化的部分,进行浏览器DOM更新重绘效率高

组件系统

React最核心的思想是将页面中任何一个区域或者元素都可以看做一个组件。

组件(component)就是同时包含了html、css、js、image等元素的聚合体。

将界面分成了各个独立的小块,每一个块就是组件,这些组件之间组合、嵌套、就成了页面。

函数式编程

函数式编程是React的精髓。所谓函数式编程就是构建一个规则以减少冗余的代码,而这个规则可以被反复的使用。

React可以将需要重复构建的UI过程抽象为组件,根据传入参数的不同区渲染不同的页面。

JSX

JSX 是Facebook为react发明的一种类似于XML格式的语言,它是JavaScipt的语法拓展。

它使用XML标记的方式直接声明界面,然后再利用编译器转换成JS语言。

React 开发不一定使用 JSX ,但建议使用它。

2. React框架技术点

1)jsx语法

JSX基本语法:只有一个根节点,并用()包裹,类似于HTML标签写法。例如:

function App() {
   return (
      <div className="App">
       three.js
     </div>
   );
}

类名为className;行内样式为style={{}}对象形式;使用JavaScript表达式,表达式写在花括号 {} 中。例如:

<div className="box" title={变量名}></div>

<div style={ {color:'red', fontSize:120 } }>react jsx</div>

l JSX提供了创建React元素方法的语法糖:React.createElement(component, props, ...children)。例如:

   let element = React.createElement("h1",null,"Hello,world!")

l 使用JSX语法后,通过babel将JSX转化成JS语法。凡是在页面中直接使用 JSX 的地方,都要加上 type="text/babel"

2)React组件

组件创建的两种方式:函数组件和组件类。组件名一定要大写开头。

(1)函数组件:

函数组件使用function定义,通过 return语句返回组件。

function HelloMessage(props) {

     return <h1>Hello World!</h1>;

}

const element = <HelloMessage />;

ReactDOM.render(

     element,

     document.getElementById('example')

);

复合组件

function Name(props) {

    return <h1>网站名称:{props.name}</h1>;

}

function Url(props) {

     return <h1>网站地址:{props.url}</h1>;

}

function MultiComponent() {

     return (

     <div>

         <Name name="React文档" />

         <Url url="https://react.docschina.org/" />

     </div>

     );

}

(2)组件类

使用ES6 class来定义一个组件。组件类必须要实现一个 render 方法,这个render方法必须要返回一个 JSX 元素, JSX 元素只能包含一个顶层标签。

class Welcome extends React.Component {

   render() {

     return <h1>Component class!</h1>;

   }

}

const element = <Welcome />;

ReactDOM.render(

     element,

     document.getElementById('example')

);

(3)组件的生命周期

(A)函数组件模拟生命周期

函数组件没有生命周期函数。React.useEffect 可以模拟生命周期函数,useEffect可以相当于三个生命周期钩子 组件挂载、组件更新、组件卸载。函数组件创建执行时就相当于constructor。函数组件的返回值就是render的返回值。

函数组件没有state,通过useState解决没有state问题。useState(initialState)的第一个参数是初始状态。

import { useEffect,useState} from 'react'

通过useEffect模拟组件加载和组件卸载事件。

当useEffect的第二个参数传递 [] 数组的时候,hook只在组件挂载时运行一次,模拟componentDidMount。而return语句模拟componentWillUnMount。

useEffect(()=>{

   console.log('组件加载,执行一次');

   return ()=>{console.log('组件卸载')}

},[])

通过useEffect模拟 componentDidUpdate。

使用useEffect(()=>{})或者useEffect(()=>{},[n])

const [name,setName] = userState('Tom');

const [age,setAge] = userState(0);

state任意一个更新将触发函数执行

useEffect(()=>{

   console.log('state变化触发组件渲染,无论name或者age,每次有变化都执行');

})

指定只监测name值,当name值变化,才会触发函数

useEffect(()=>{

   console.log('name值变化触发组件渲染,每次name值变化执行');

},[name])

useEffect(()=>{

   console.log('age值变化触发组件渲染,每次age值变化执行');

},[age])

注:useEffect可以多个使用。

(B)组件类的生命周期:

constructor:构造函数,初始化数据state,对this的指向问题进行处理。

componentDidMount:UI渲染完毕后触发,一般用于DOM的操作以及发送请求的功能,加载数据。

render:会渲染出虚拟的DOM,也就是html文档结构。当在挂载的时候,这个函数就会执行,将虚拟的DOM节点在页面上生成。

componentWillUnmount:组件从页面消失,在此处清除定时器等操作。

this.setState会重新更新状态并重新渲染页面,因此,在render()中不能使用。

注意:

1.当组件中的this.setState({})以及props的数据更新时,页面将重新渲染。

2.当方法中调用this.forceUpdate()时,页面会强制重新渲染。

3)React状态

React 把组件看成是一个状态机(State Machines),只需更新组件的 state,就会根据新的 state 重新渲染用户界面。

this.state

类构造函数中初始化状态 this.state  = ...

 

在需要的时候更新state,使用this.setState

this.setState({ [field]:[value],[field1]:[value1] })

例如:

this.setState({date: new Date()});

注意:

在构造函数中定义并初始化state。至少要定义一个空值的state。

否则this.state都是null,后续就使用this.state会报错。

4)React属性

props和state 主要的区别在于 props 是不可变的。

可以设置默认值:

class HelloMessage extends React.Component {

  render() {

    return (

      <h1>Hello, {this.props.name}</h1>

    );

  }

}

HelloMessage.defaultProps = {

  name: 'Tom'

};

const element = <HelloMessage />;

// 或者

// const element = <HelloMessage  name='Jack' />;

ReactDOM.render(

  element,

  document.getElementById('example')

);

5)React事件

绑定属性的命名采用驼峰式写法,而不是小写。

传入一个函数作为事件处理函数,而不是一个字符串。

<button onClick={activateLasers}>

  激活按钮

</button>

不能使用返回 false 的方式阻止默认行为, 必须明确使用 preventDefault

function ActionLink() {

  function handleClick(e) {

    e.preventDefault();

    console.log('链接被点击');

  }

  return (

    <a href="#" onClick={handleClick}>

      点我

    </a>

  );

}