React 学习笔记4 Diffing/脚手架

发布于:2025-09-03 ⋅ 阅读:(18) ⋅ 点赞:(0)

目录

Diffing算法

key

脚手架

create-react-app

安装

项目结构

hello world Demo


Diffing算法

当页面上显示的内容更新时/初始化时,React会将需要更新/初始化的内容形成虚拟DOM,并和之前的虚拟DOM(如果有)进行比较,把需要更新的内容推到页面上,而不是整个DOM全部都更新。

key

key是虚拟DOM的一个标识,在对比更新时,key可以用于判断新旧虚拟DOM中前后节点是否是同一个。如果在旧虚拟DOM中找到了与新虚拟DOM中一样的key,则可以确定这两个节点是同一个,如果虚拟DOM中的内容没变,则直接复用,如果虚拟DOM中的内容改变了,则生成新的DOM并进行替换。如果旧虚拟DOM中没有和新虚拟DOM一样的key,会将这个DOM生成并渲染到页面。

如果将index索引值作为Key,在组数数据更新时,可能会产生效率问题。如果数据添加到组数最末尾,不会破坏前面的数据顺序,那么并不会影响效率,但是,如果数据插入了数组最前方或者数据中间某个位置,这会导致数组中元素的index和之前并不一致,diffing算法在进行比较时,会拿着两个其实并不一致的DOM对比,并认为数据发生了改变,会生成新的真实DOM并进行渲染,会重新渲染数据,而不是复用,产生效率问题。而且,如果标签内部含有输入类DOM(input输入框、radio单选器、checkbox、select等),当使用Index作为索引值时,动态插入数据时,如果数据并不是插入最末尾,输入框中的数据也会由于前后Index相同的DOM元素其实并不是同一个,导致Input数据发生错乱。

如果不存在对数据的逆序加入、删除等操作,使用index作为key并不会产生问题的,但是,一旦数据的顺序发生改变,使用index作为Key就会产生问题。

脚手架

create-react-app

create-react-app是React提供的一个脚手架,脚手架可以用于快速创建基于某个库的模板项目。包含了基础的需要的配置,并且可以下载好所需的相关依赖。使用脚手架,可以实现模块化、组件化、工程化。

安装

1.全局安装 npm install -g create-react-app

(如果提示网络错误,可以先设置npm config set registry http://registry.npmjs.org/

2.创建项目 create-react-app 项目名

3.进入项目名文件夹,启动项目 npm start

项目结构

public 静态资源文件,存放页面、公共图片、样式等

------index.html 应用主页面,组件都渲染到这个页面上,整个项目下只有一个html文件

------mainfest.json 应用加壳配置

------robots.txt 爬虫规则,当前网站被爬取时,规定哪些数据可以被爬取,哪些不行

src 

------App.css APP组件样式

------App.js 生成App组件,组件首字母大写

------App.test.js APP组件测试文件

------index.css 通用样式,也可以放入public下,并在html中引入

------index.js 入口文件

------reportWebVitals.js 记录页面性能,内部使用web-vitals库,使用时需要自己编写配置,并不是完全配好的

------setupTests.js 用于组件测试,也是需要自己配置,使用了库jest-dom

public-index.html

src-index.js

hello world Demo

在react中,.js和.jsx文件import时可以省略扩展名

import './App.css';
import React from 'react'

class App extends React.Component{
  render(){
    return (
      <div>
        <h2>hello world</h2>
      </div>
    )
  }
}


export default App;

在实际编写项目时,一般在src下创建components文件,把组件放入components文件中,每个组件一般也都是一个文件夹,里面放置组件的js和组件的其他资源文件等,最后在App组件中引入使用。

src/components/Hello/hello.css

h2{
    background-color: aquamarine;
}

src/components/Hello/index.jsx

import {Component } from 'react'
import './hello.css'

export default class Hello extends Component{
    render(){
        return (
            <div>
                <h2>Hello</h2>
            </div>
        )
    }
}

src/components/World/world.css

.world{
    background-color:blueviolet;
}

src/components/World/index.jsx

import {Component } from 'react'
import './world.css'

export default class Hello extends Component{
    render(){
        return (
            <div>
                <h2 className='world'>World</h2>
            </div>
        )
    }
}

src/App.js

import './App.css';
import React from 'react'
import Hello  from './components/Hello'
import World from './components/World'
class App extends React.Component{
  render(){
    return (
      <div>
        <Hello/>
        <World/>
      </div>
    )
  }
}


export default App;

如果组件文件以js结尾,有时候,js结尾的文件并不是全是组件,一般为了区分组件和一般js文件,可以让组件的js文件名首字母大写,或者让组件文件以.jsx为扩展名。

样式模块化

对于两个组件,如果他们各有自己的css文件,且css文件中存在冲突的命名,则后引入的样式会覆盖先引入的文件,为了避免这种情况,首先,要给css的名字之前先加上module,然后,在引入样式时,给引入的样式命名,然后给组件中标签配置样式时,配置命名.样式,就可以避免冲突。

hello.module.css

.h2Demo{
    background-color: aquamarine;
}

hello/index.jsx

import {Component } from 'react'
import hello from './hello.module.css'

export default class Hello extends Component{
    render(){
        return (
            <div>
                <h2 className={hello.h2Demo}>Hello</h2>
            </div>
        )
    }
}

world.module.css

.h2Demo{
    background-color:blueviolet;
}

world/index.jsx

import {Component } from 'react'
import world from './world.module.css'

export default class Hello extends Component{
    render(){
        return (
            <div>
                <h2 className={world.h2Demo}>World</h2>
            </div>
        )
    }
}

对一个jsx文件,里面的内容框架是固定的,可以通过一些代码片段快速生成框架,不需要自己完全手敲。要实现这种效果,需要先安装插件:

然后再敲rcc,就能生成react类式组件的框架,

import React, { Component } from 'react'

export default class index extends Component {
  render() {
    return (
      <div>index</div>
    )
  }
}

敲rfc能生成函数式组件的框架。

import React from 'react'

export default function index() {
  return (
    <div>index</div>
  )
}

在插件的details部分,可以查看其他的代码片段:

组件化流程

1. 拆分组件:把界面拆分成一个个组件

2. 实现静态组件

使用组件实现静态页面的效果

3. 实现动态组件

3.1能够动态显示初始化数据

3.2能够交互

父组件给子组件传值

通过props传递。

父组件App.js

import './App.css';
import React from 'react'
import World from './components/World'
class App extends React.Component{
  state = {
    dataList:[
      {id:'001',name:'a',flag:true},
      {id:'002',name:'b',flag:true},
    ]
  }
  

  
  render(){
    return (
      <div>
        <World dataList={this.state.dataList}/>
      </div>
    )
  }
}


export default App;

子组件World/index.jsx

import {Component } from 'react'
import world from './world.module.css'

export default class Hello extends Component{
    render(){
        console.log(this.props.dataList)
        return (
            <div>
                <h2>1</h2>
            </div>
        )
    }
}

子组件给父组件传值

通过函数,父组件先通过props给子组件传递一个函数,子组件调用函数时,以参数的形式给父组件传递数据。

父组件App.js

import './App.css';
import React from 'react'
import Hello  from './components/Hello'
import World from './components/World'
class App extends React.Component{
  state = {
    dataList:[
      {id:'001',name:'a',flag:true},
      {id:'002',name:'b',flag:true},
    ]
  }
  
  setList = (dataObj)=>{
    let newList = [dataObj,...this.state.dataList]
    console.log(newList)
    this.setState({dataList:newList})
  }
  
  render(){
    return (
      <div>
        <Hello setList={this.setList}/>
        <World/>
      </div>
    )
  }
}


export default App;

子组件Hello/index.jsx

import {Component } from 'react'

export default class Hello extends Component{
    setData = ()=>{
        this.props.setList(
            {id:'003',name:'c',flag:false}
        )
    }

    render(){
        return (
            <div>
                <button onClick={this.setData}>click</button>
            </div>
        )
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到