React 学习笔记4 Diffing/脚手架

目录

Diffing算法

key

脚手架

create-react-app

安装

项目结构

[hello world Demo](#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时可以省略扩展名

javascript 复制代码
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

javascript 复制代码
h2{
    background-color: aquamarine;
}

src/components/Hello/index.jsx

javascript 复制代码
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

javascript 复制代码
.world{
    background-color:blueviolet;
}

src/components/World/index.jsx

javascript 复制代码
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

javascript 复制代码
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

javascript 复制代码
.h2Demo{
    background-color: aquamarine;
}

hello/index.jsx

javascript 复制代码
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

javascript 复制代码
.h2Demo{
    background-color:blueviolet;
}

world/index.jsx

javascript 复制代码
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类式组件的框架,

javascript 复制代码
import React, { Component } from 'react'

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

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

javascript 复制代码
import React from 'react'

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

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

组件化流程

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

  2. 实现静态组件

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

  1. 实现动态组件

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

3.2能够交互

父组件给子组件传值

通过props传递。

父组件App.js

javascript 复制代码
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

javascript 复制代码
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

javascript 复制代码
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

javascript 复制代码
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>
        )
    }
}
相关推荐
做cv的小昊3 小时前
计算机图形学:【Games101】学习笔记05——着色(插值、高级纹理映射)与几何(基本表示方法)
笔记·opencv·学习·计算机视觉·图形渲染·几何学
车载测试工程师3 小时前
CAPL学习-CAN相关函数-统计API函数
网络·网络协议·学习·capl·canoe
好奇龙猫4 小时前
【AI学习-comfyUI学习-第二十四节-open(contorlnet多重处理)+图生图openpose-各个部分学习】
人工智能·学习
wanzhong23335 小时前
CUDA学习5-矩阵乘法(共享内存版)
深度学习·学习·算法·cuda·高性能计算
我是刘成6 小时前
基于React Native 0.83.1 新架构下的拆包方案
react native·react.js·架构·拆包
梦6507 小时前
Vue 组件 vs React 组件深度对比
javascript·vue.js·react.js
PNP Robotics7 小时前
PNP机器人受邀参加英业达具身智能活动
大数据·人工智能·python·学习·机器人
iconball7 小时前
个人用云计算学习笔记 --24 虚拟化、KVM 基础使用与热迁移实验、VMware ESXi笔记
运维·笔记·学习·云计算
是小菜呀!7 小时前
基于深度学习的图像检索系统项目实践
笔记
全栈前端老曹9 小时前
【ReactNative】页面跳转与参数传递 - navigate、push 方法详解
前端·javascript·react native·react.js·页面跳转·移动端开发·页面导航