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 (
                
                    
                    
© 2020 千峰教育
); } }; }; export default withCopyright; // Fragment是一个伪标签,渲染的时候是不会显示在页面中的,因此也不会影响视图显示

使用方式:

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

class App extends Component {
    render() {
        return (
            

网站首页

); } } export default Hoc(App);

案例: 

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

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 (
            
                桃之夭夭,灼灼其华。
            
        );
    }
}
​
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 (
            
                
                我是第2个按钮
            
        );
    }
}

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 (
      
{/* 方法一 style 属性 */}
第一行
{/* 方法二 外部引入 若是外部子组件类名相同 则样式相同 不存在作用域限制 存在污染情况*/}
第二行
{/* 方法三 安装 styled-components 在组件内部使用 存在隔离 解决全局样式污染*/}
第二行
); } }

 

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 (
            
                
            
        );
    }
}

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 (
      
{/* 方法三 安装 styled-components 在组件内部使用 存在隔离 解决全局样式污染*/}
第二行
{/* styled-components高级写法 */} {/* 1.样式继承 */} 第四行 {/* 2.动态传递参数 */} 第五行
); } }

路由预热

1、介绍

React-Hoc高阶组件与css-in-js技术_第1张图片

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

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

npm i [email protected]

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属性:展示的组件

    • 语法:

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

各个组件之间的关系

React-Hoc高阶组件与css-in-js技术_第2张图片

注意: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 (
      
  • 去A页面
  • 去B页面

); } }

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