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>© 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.0React 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的功能
 
-  
各个组件之间的关系

注意:Link和Route组件必须被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>
    );
  }
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!