React-Hoc高阶组件与css-in-js技术

Hoc高阶组件

Higher - Order Components:在原有组件基础之上加工后新生成得到的新组件。【高阶组件】

const NewComponent = HOC(YourComponent)

通俗的来讲,高阶组件就相当于手机壳,通过包装组件,增强组件功能。

HOC实现步骤:

  • 创建一个函数

  • 指定函数参数,参数应该以大写字母开头

  • 在函数内部创建一个类组件,提供复用的状态(如有)及逻辑代码,并返回

  • 在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件(可选,如有)

  • 调用该高阶组件方法,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面

比如,我们想要我们的组件通过自动注入一个版权信息:

import React, { Component, Fragment } from "react";

const withCopyright = (Cmp) => {
    return class Hoc extends Component {
        render() {
            return (
                <Fragment>
                    <Cmp></Cmp>
                    <div>&copy; 2020 千峰教育</div>
                </Fragment>
            );
        }
    };
};

export default withCopyright;

// Fragment是一个伪标签,渲染的时候是不会显示在页面中的,因此也不会影响视图显示

使用方式:

import React, { Component } from "react";
// 引入HOC函数
import Hoc from './Hoc/Hoc_copyright'

class App extends Component {
    render() {
        return (
            <div>
                <h1>网站首页</h1>
            </div>
        );
    }
}

export default Hoc(App);

案例: 

import React, { Component } from "react";
import { Fragment } from "react";
/**
 * 高阶组件: 把组件包装 扩展原有组件的功能
 * 实现步骤
 * 1.创建一个函数
 * 2.函数参数为组件形参
 * 3.在函数内部创建一个类组件,提供**复用**的状态(如有)及逻辑代码,并返回
 * 4.在返回的类组件找中将传入的参数组件进行加工并渲染
 *
 */
class App extends Component {
  render() {
    return <div>App</div>;
  }
}
// 第二步 Cmp 参数 为 组件参数
const WithCopy = (Cmp) => {
  // 第一步 创建一个WithCopy的函数
  return class Hoc extends Component {
    // 第三步 在内部生成一个类组件 并返回
    render() {
      return (
        // 写法一
        // <div>
        //   <Cmp></Cmp>
        //   <div>版权信息</div>
        // </div>
        // 写法二
        <Fragment>
          <Cmp></Cmp>
          <div>版权信息</div>
        </Fragment>
      );
    }
  };
};

const WithColor = (Cmp) => {
  return class Hoc extends Component {
    render() {
      return (
        <div style={{ backgroundColor: "aqua" }}>
          <Cmp></Cmp>
        </div>
      );
    }
  };
};

export default WithColor(WithCopy(App)); // 第四步 进行组件合并

这样只要我们有需要用到版权信息的组件,都可以直接使用withCopyright这个高阶组件包裹即可。

当然,也可以使用ES7的装饰器(ES7的一个新语法,它可以对一些对象进行装饰包装然后返回一个被包装过的对象,可以装饰的对象包括:类,属性,方法等)来实现高阶组件的效果,需要在package.json文件中增加如下配置:

"plugins": [
  [
          "@babel/plugin-proposal-decorators",
          {
              "legacy": true
          }
  ]
]

①默认情况下装饰器语法在react中是不被支持的,如果直接用会报错

Support for the experimental syntax 'decorators-legacy' isn't currently enabled

②开启装饰器的支持(需要配置babel),需要解压react封装在react-scripts项目中配置

git add .
git commit -m xxx
npm run eject

③需要在package.json文件中给babel增加如下配置(加完之后需要重启项目)

"plugins": [
     [
         "@babel/plugin-proposal-decorators",
         {
             "legacy": true
         }
     ]
]

 ④装饰器语法

@方法名

案例:

import React, { Component } from "react";
import { Fragment } from "react";
/**
 * 高阶组件: 把组件包装 扩展原有组件的功能
 * 实现步骤
 * 1.创建一个函数
 * 2.函数参数为组件形参
 * 3.在函数内部创建一个类组件,提供**复用**的状态(如有)及逻辑代码,并返回
 * 4.在返回的类组件找中将传入的参数组件进行加工并渲染
 *
 */

// 第二步 Cmp 参数 为 组件参数
const WithCopy = (Cmp) => {
  // 第一步 创建一个WithCopy的函数
  return class Hoc extends Component {
    // 第三步 在内部生成一个类组件 并返回
    render() {
      return (
        // 写法一
        // <div>
        //   <Cmp></Cmp>
        //   <div>版权信息</div>
        // </div>
        // 写法二
        <Fragment>
          <Cmp></Cmp>
          <div>版权信息</div>
        </Fragment>
      );
    }
  };
};

const WithColor = (Cmp) => {
  return class Hoc extends Component {
    render() {
      return (
        <div style={{ backgroundColor: "aqua" }}>
          <Cmp></Cmp>
        </div>
      );
    }
  };
};

// @  装饰器语法 扩展原有类功能  
@WithColor
@WithCopy
export default class App extends Component {
  render() {
    return <div>App</div>;
  }
}


css-in-js技术

1、简介

CSS-in-JS是一种技术,而不是一个具体的库实现。简单来说CSS-in-JS就是将应用的CSS样式写在JavaScript文件里面,而不是独立为一些css,scss或less之类的文件,这样你就可以在CSS中使用一些属于JS的诸如模块声明,变量定义,函数调用和条件判断等语言特性来提供灵活的可扩展的样式定义。CSS-in-JS在React社区的热度是最高的,这是因为React本身不会管用户怎么去为组件定义样式的问题,而Vue有属于框架自己的一套定义样式的方案。

  • 在js文件中写css就是css-in-js技术

  • 好处:

    • 支持一些js的特性

      • 继承

      • 变量

      • 函数

    • 支持框架的特性

      • 传值特性

styled-components 应该是CSS-in-JS最热门的一个库,通过styled-components,你可以使用ES6的标签模板字符串语法,为需要styled的Component定义一系列CSS属性,当该组件的JS代码被解析执行的时候,styled-components会动态生成一个CSS选择器(比较随意的),并把对应的CSS样式通过style标签的形式插入到head标签里面。动态生成的CSS选择器会有一小段哈希值来保证全局唯一性来避免样式发生冲突。

  • 通过ES6里面的模版字符串形式写css样式(遵循之前css样式代码的写法)

  • 每个样式选择器都会在编译之后自动被添加上一个hash值(全局唯一)

使用styled-components前需要安装,安装的命令如下:

npm i -S styled-components

由于css后期会在模版字符串中编写,默认情况下vscode是没有css样式代码片段的(写样式的时候是没有代码提示的),为了提高css代码在模版字符串中编写的效率,此处强烈建议安装一个vscode的扩展:vscode-styled-components。

在React中写样式的方式一共有:

  • import "xxx.css"

  • styled-components

  • 行内标签style属性

  • index.html中Link标签

  • index.html的style标签

2、定义样式与使用

定义

import styled from "styled-components";
const Title = styled.div`
    font-size: 110px;
    color: pink;
    font-family: 华文行楷;
    background-color: black;
`;
export { Title };

使用

在使用的时候成员会被当作组件去使用(首字母大写)

import React, { Component, Fragment } from "react";
// 就像使用常规 React 组件一样使用 Title
import { Title } from "./assets/style/style";
​
class App extends Component {
    render() {
        return (
            <Fragment>
                <Title>桃之夭夭,灼灼其华。</Title>
            </Fragment>
        );
    }
}
​
export default App;

3、样式继承

styled-components中也可以使用样式的继承,其继承思想与react的组件继承相似:

  • 继承父的样式

  • 重载父的样式

样式继承
import styled from "styled-components";

const Button = styled.button`
    font-size: 20px;
    border: 1px solid red;
    border-radius: 3px;
`;
// 一个继承 Button 的新组件, 重载了一部分样式
// 继承会合并与父的样式,但是如果遇到样式冲突(相同),会以自己的为准
const Button2 = styled(Button)`
    color: blue;
    border-color: yellow;
`;

export { Button, Button2 };

 使用

import React, { Component, Fragment } from "react";

import { Button, Button2 } from "./assets/style/style";

class App extends Component {
    render() {
        return (
            <Fragment>
                <Button>我是第1个按钮</Button>
                <Button2>我是第2个按钮</Button2>
            </Fragment>
        );
    }
}

export default App;

案例(基础样式案例):

import React, { Component } from "react";
import "./assets/css/App.css"; // 引入外部样式
// 引入 style-component
import styled from "styled-components";

// 方法三 
const LineOne = styled.div`
  color: aqua;
`;
export default class App extends Component {
  render() {
    return (
      <div>
        {/* 方法一 style 属性 */}
        <div style={{ fontSize: 24 + "px", color: "aqua" }}>第一行</div>
        {/* 方法二 外部引入  若是外部子组件类名相同 则样式相同 不存在作用域限制 存在污染情况*/}
        <div className="lineOne">第二行</div>
        {/* 方法三 安装 styled-components  在组件内部使用  存在隔离  解决全局样式污染*/}
        <LineOne>
          <div>第二行</div>
        </LineOne>
      </div>
    );
  }
}

 

4、属性传递

属性传递:样式值的动态传参(组件传值)

基于css-in-js的特性,在styled-components中也允许我们使用props(父传子),这样一来,我们可以对部分需要的样式进行传参,很方便的动态控制样式的改变。

属性传递(JS中接收)
import styled from "styled-components";

// 参数传递
const Input = styled.input`
    color: ${(props) => props.inputColor || "red"};
`;

export { Input };
动态传递参数
import React, { Component, Fragment } from "react";

import { Input } from "./assets/style/style";

class App extends Component {
    render() {
        return (
            <Fragment>
                <Input defaultValue="are you ok?" inputColor="blue"></Input>
            </Fragment>
        );
    }
}

export default App;

案例(styled-components):

import React, { Component } from "react";
// 引入 style-component
import styled from "styled-components";

// 方法三 
const LineOne = styled.div`
  color: aqua;
`;
// 1.样式继承
const Line4 = styled(LineOne)`
  background-color: blue;
`;

// 属性传递
const MyColor = styled.div`
  color:  ${(props) => props.color || "red"};
`;
export default class App extends Component {
  render() {
    return (
      <div>
        {/* 方法三 安装 styled-components  在组件内部使用  存在隔离  解决全局样式污染*/}
        <LineOne>
          <div>第二行</div>
        </LineOne>
        {/*  styled-components高级写法 */}
        {/* 1.样式继承 */}
        <Line4>
          第四行
        </Line4>
        {/* 2.动态传递参数 */}
        <MyColor color="pink">
          第五行
        </MyColor>
      </div>
    );
  }
}

路由预热

1、介绍

React Router官网:Home v6.21.1 | React Router

使用用React Router前需要先进行安装:

npm i react-router-dom@5.3.0

React Router现在的主版本是5,思想:一切皆组件

2、路由的使用

2.1、相关组件

如前面介绍里说的,自Router 4之后的思想是一切皆组件,所以在正式开始学习React路由前需要先对几个组件要有所掌握:

  • Router组件(别名,真实是不存在的,为了简写路由模式的组件名称):包裹整个应用(单个具体的组件/根组件),一个React应用只需要使用一次

    • 注意:在react中,不存在类似于vue的路由配置文件,对于前端路由模式的选择,我们可以通过该组件完成

    • Router类型: HashRouter和BrowserRouter

      • HashRouter: 使用URL的哈希值实现 (localhost:3000/#/first)

      • BrowserRouter:使用H5的history API实现(localhost:3000/first)

    • 区别

      • 两者在开发阶段,除了地址栏上的表现形式不一样以外,其它没区别

      • 两者在生产阶段,hash路由可以直接上生产,无需做任何配置,而history模式则上生产需要配置的,配置服务器环境,否则项目是不能刷新的,一刷新会404

  • Link组件:用于指定导航链接(a标签)就是做声明式导航的(类似于vue中的router-link组件

    • 最终Link会编译成a标签,而to属性会被编译成 a标签的href属性

  • Route组件:指定路由展示组件相关信息(组件渲染)【路由规则】{path: xx,component:xxx}

    • path属性:路由规则,这里需要跟Link组件里面to属性的值一致

    • component属性:展示的组件

    • 语法:<Route path="路径" component={组件}></Route>

    • 该组件除了具备定义路由规则功能外,还有类似于vue中router-view的功能

各个组件之间的关系

注意:LinkRoute组件必须被Router组件给包裹,否则报错。

案例:

import React, { Component } from "react";
/**
 * React-router 中一切皆组件
 * 跳转标签 Link to url 地址
 * NavLink 跳转标签 会有一个选择css类名
 * Route 渲染容器 切换的组件渲染显示的地方 路由映射关系
 * Router BrowserRouter 历史路由
 *        HashRouter hash路由
 */
import { Link, Route ,NavLink} from "react-router-dom";

import pageA from "./pages/pageA";
import pageB from "./pages/pageB";

export default class App extends Component {
  render() {
    return (
      <div>
        <ul>
          <li>
            <Link to="/a">去A页面</Link>
          </li>
          <li>
            <NavLink to="/b">去B页面</NavLink>
          </li>
        </ul>
        <hr />
        <Route path="/a" component={pageA}></Route>
        <Route path="/b" component={pageB}></Route>
      </div>
    );
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/306069.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

三分钟轻松搞懂 HashMap 死循环问题!

三分钟轻松搞懂 HashMap 死循环问题&#xff01; HashMap 死循环发生在 JDK 1.7 版本中&#xff0c;形成死循环的原因是 HashMap 在 JDK 1.7 使用的是头插法&#xff0c;头插法 链表 多线程并发 HashMap 扩容&#xff0c;这几个点加在一起就形成了 HashMap 的死循环。 前置…

Adding Conditional Control to Text-to-Image Diffusion Models——【代码复现】

官方实现代码地址&#xff1a;lllyasviel/ControlNet: Let us control diffusion models! (github.com) 一、前言 此项目的使用需要显存大于8G&#xff0c;训练自己的ControlNet或需要更大&#xff0c;因此请注意查看自身硬件是否符合。 在此之前请确保已经安装好python以及…

【UE Niagara学习笔记】05 - 喷射火焰顶部的蓝色火焰

在上一篇博客&#xff08;【UE Niagara学习笔记】04 - 火焰喷射时的黑烟效果&#xff09;的基础上继续实现在火焰喷射的起点位置生成蓝色火焰的效果。 目录 效果 步骤 1. 创建新的发射器 2. 减少粒子生成数量 3. 减小粒子初始大小 4. 减少粒子喷射距离 5. 减少粒子初始…

在Linux上搭建Maven仓库

目录 一、下载安装包二、安装maven三、修改配置文件settings.xml四、配置环境变量五、测试maven是否可用 一、下载安装包 我在这里为大家准备好了apache-maven-3.5.0-bin.tar.gz&#xff0c;百度网盘下载链接如下&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1bGun…

python编程使用selenium模拟登陆淘宝实例代码

selenium简介 selenium 是一个web的自动化测试工具&#xff0c;不少学习功能自动化的同学开始首选selenium &#xff0c;相因为它相比QTP有诸多有点&#xff1a; * 免费&#xff0c;也不用再为破解QTP而大伤脑筋* 小巧&#xff0c;对于不同的语言它只是一个包而已&#xff0c…

AFL进阶教学——插桩、执行、覆盖率收集与反馈(解析)

AFL&#xff08;American Fuzzy Lop&#xff09;是一个面向安全的模糊测试工具&#xff0c;它使用编译时插桩技术和遗传算法&#xff0c;可以自动发现触发目标二进程程序的测试用例&#xff0c;从而大大提高测试代码的功能覆盖率。本文主要讲述AFL是如何实现插桩的&#xff0c;…

提升网络安全重要要素IP地址

在数字化时代&#xff0c;网络安全已经成为人们关注的焦点。本文将深入探讨网络安全与IP地址之间的紧密联系&#xff0c;以及IP地址在构建数字世界的前沿堡垒中的关键作用。 网络安全是当今数字社会中不可忽视的挑战之一。而IP地址&#xff0c;作为互联网通信的基础协议&#…

RT-Thread:ADC 框架应用,通过 STM32CubeMX 配置 STM32 ADC驱动

关键词&#xff1a;ADC,RT-Thread ADC,STM32 ADC应用 说明&#xff1a;本笔记是记录如何开启 RT-Thread 框架的ADC功能&#xff0c;使用系统自带的ADC函数&#xff0c;并通过 STM32CubeMX 配置 STM32 ADC驱动 。 1. 打开board.h 文件&#xff0c;找到ADC 使用配置的流程&…

Dell 机架式服务器 - 高级定制服务

Dell 机架式服务器 - 高级定制服务 1. Dell Technologies2. 机架式服务器 - 高级定制服务2.1. Servers & Storage (服务器及存储) -> Servers2.2. Rack Servers (机架式服务器)2.3. Shop2.4. PowerEdge Rack Servers (PowerEdge 机架式服务器)2.5. PowerEdge R760 Rack …

SpringBoot 注解超全详解

使用注解的优势&#xff1a; 采用纯java代码&#xff0c;不在需要配置繁杂的xml文件 在配置中也可享受面向对象带来的好处 类型安全对重构可以提供良好的支持 减少复杂配置文件的同时亦能享受到springIoC容器提供的功能 1 注解详解&#xff08;配备了完善的释义&#xff0…

数据库的导入导出以及备份

1.数据库的导出和导入 一.navicat导入导出 导入&#xff1a;右键➡运行SQL文件 导出选&#xff1a;中要导出的表➡右键➡转储SQL文件➡数据和结构 mysqldump命 1. 进入navicat安装目录的bin目录&#xff0c;cmd打开命令窗口 2. mysql -u用户名 -p ➡ 输入密码 3. creat…

Python基础知识:整理7 字典的定义及其相关操作

1 字典的定义 # 1. 字典的定义 # 定义字典的字面量 # {key: value, key: value, ......, key: value}# 定义字典变量 # my_dict {key: value, key: value, ......, key: value}# 定义空字典 # my_dict {} # my_dict dict()定义重复Key的字典 my_dict1 {"张三": …

Proxmox VE 超融合集群销毁Ceph Pool

作者&#xff1a;田逸&#xff08;formyz&#xff09; 销毁Ceph Pool的目的 一套五节点的Proxmox VE超融合集群&#xff0c;当初为有效利用资源&#xff0c;配备了Nvme高性能磁盘和大容量的SATA机械磁盘&#xff08;如图所示&#xff09;&#xff0c;高性能Nvme磁盘用于虚拟机…

图像中部分RGB矩阵可视化

图像中部分RGB可视化 今天室友有个需求就是模仿下面这张图画个示意图&#xff1a; 大致就是把图像中的一小部分区域的RGB值可视化了一下。他居然不知道该怎么画&#xff0c;我寻思这不直接秒了。 import cv2 as cv import numpy as np import matplotlib.pyplot as pltclass …

构建高效秒杀系统的设计原理及注意事项

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

OpenFegin日志增强

OpenFeign配置日志增强功能 OpenFeign提供了日志打印功能&#xff0c;我们可以通过配置来调整日恙级别&#xff0c;从而了解Feign 中 Http请求的细节。 说白了就是对Feign接口的调用情况进行监控和输出 日志级别 NONE&#xff1a;默认的&#xff0c;不显示任何日志; BASIC&…

Android平板浏览器远程Ubuntu服务器使用code-server编程写代码

文章目录 1.ubuntu本地安装code-server2. 安装cpolar内网穿透3. 创建隧道映射本地端口4. 安卓平板测试访问5.固定域名公网地址6.结语 1.ubuntu本地安装code-server 准备一台虚拟机,Ubuntu或者centos都可以&#xff0c;这里以VMwhere ubuntu系统为例 下载code server服务,浏览器…

一文快速学会Docker软件部署

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;首期文章 &#x1f4da;订阅专栏&#xff1a;Docker 希望文章对你们有所帮助 做项目的时候&#xff0c;感觉很多地方的配置都特别…

RK3568上如何使用MPP进行硬解码

目录 前言正文一、FFmpeg 拉流处理二、RK3568 mpp硬解码1、简介2、普通mpp解码流程3、核心代码 END、总结的知识与问题1、一直出现jitter buffer full 这样的问题2、如何打印帧率&#xff1f;3、分析av_packet_alloc、av_init_packet、av_packet_unref、av_packet_free、av_fra…

zookeeper 与eureka区别

CAP定理 在分布式系统的发展中&#xff0c;影响最大的莫过于CAP定理了&#xff0c;是分布式系统发展的理论基石。 2000年&#xff0c;加州大学的计算机科学家 Eric Brewer提出了CAP猜想 2002 年&#xff0c;麻省理工学院的 Seth Gilbert 和 Nancy Lynch 从理论上证明了 CAP 猜…