反向代理

  • 官方文档

  • 一般来讲,所有的网站和服务器都是设有跨域限制的,但我们自己做项目时的运行和调试基本是部署在本地服务器上的(localhost:3000),如果此时的前端页面向设有跨域限制的后端服务器请求数据,就会受到同源规则的限制,无法获取数据,也就是存在了跨域问题,那如何解决呢?

  • 我们知道,服务器向服务器请求数据是不存在跨域问题的,因此我们可以使用本地服务器向远端服务器请求数据,再由本地的服务器向本地的项目提供数据,这就解决了跨域问题,也就是我们所说的反向代理
    image

实现流程

  1. 安装中间件
npm install http-proxy-middleware --save
  1. src目录下创建setupProxy.js文件
    image

  2. 设置setupProxy.js

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
app.use(
/*
前缀可以自己设置,但是要配置重写pathRewrite,将自己设置的前缀删去且发送请求的url
也需要带上自己写的前缀,一般用于辨别我们自己设置的请求类型的分类和每一个远端服务器(重要)
*/
'/api',//api是需要转发的请求(所有带有/api前缀的请求都会转发给3000,即本地服务器)
createProxyMiddleware({//配置代理服务器
target: 'https://i.maoyan.com',//需要做服务器代理的域名(让本地服务器向指定域名请求数据)
changeOrigin: true,
/*
changeOrigin设置为true时,服务器收到的请求头中的host为:https://i.maoyan.com
changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
changeOrigin默认值为false,但我们一般将changeOrigin值设为true
*/
})
);

// 可以设置多个代理(不同的服务器)
// app.use(
// '/前缀', //api是需要转发的请求(所有带有/api前缀的请求都会转发给3000)
// createProxyMiddleware({
// target: 'https://xxx.com', //配置转发目标地址(能返回数据的服务器地址)
// changeOrigin: true, //控制服务器接收到的请求头中host字段的值
// pathRewrite: {'^/前缀': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(将数据变成html文件)
// }),
// );
};
  1. 前端页面向指定服务器请求数据(省去域名)
import React, { Component } from 'react'
import axios from 'axios'//引入axios

export default class App extends Component {

// 使用生命周期向设有跨域请求的服务器发送请求
componentDidMount(){
// 省去域名,直接截取'/api'前缀以及后面的url,请求域名在setupProxy中做代理配置
axios.get('/api/mmdb/movie/v3/list/hot.json?ct=%E6%AD%A6%E6%B1%89&ci=57&channelId=4')
.then(res=>{
console.log('请求的数据',res);
})
}

render() {
return (
<div>
反向代理
</div>
)
}
}

结果展示:

  1. 没有配置代理(setupProxy.js)时,请求数据失败,存在跨域问题
    image

  2. 配置了代理(setupProxy.js)成功请求到数据!
    image

CSS Module

  • ReactCSS的规则都是全局的,任何一个组件的样式规则,都对整个页面有效,这可能会导致大量的冲突。也就是说如果我有两个css文件,它们的中的一些样式名是一样的,那么就会被覆盖,简单的解决办法就是将样式的命名变得复杂且不重复,但这样样式多了也很难避免重复,且命名也不会太好看。
  • 那么这个时候就推荐使用CSS ModulesCSS Modules 的做法就是通过配置将.css文件进行编译,编译后在每个用到css的组件中的css类名都是独一无二的,从而实现CSS的局部作用域。

在组件中的两种样式使用方法

  1. 全局样式 (默认)
样式文件命名规则:  xxx.css 
引入方式: import 'xxx.css' (直接在组件间引入并使用)

用法:<div className='styleName'> (直接在组件中调用我们样式文件中的类型即可)
  1. 局部样式(css modules
文件命名规则:  xxx.module.css (多加上一个module)
引入方式:import xxx from 'xxx.module.css' (引入一个样式对象,里面保存着我们的样式)

用法:<div className={xxx.styleName}> (以对象的形式调用)

注:css modules会默认给类名加上一个唯一标识符(哈希字符串),从而实现类名不重复

css modules语法:

  1. :global(.className)

CSS Modules 允许使用:global(.className)的语法,声明一个全局规则。凡是这样声明的class,都不会被编译成哈希字符串。代码如下:

.title {
color: red;
}
/* 全局.title的类名都会变成绿色生效 */
:global(.title) {
color: green;
}
  1. :local(.className)

CSS Modules 还提供一种显式的局部作用域语法:local(.className)

下面代码等同于上面的代码:

:local(.title) {
color: red;
}
:global(.title) {
color: green;
}
  1. 继承

继承在 CSS Modules 中,一个选择器可以继承另一个选择器的规则,这称为”组合”(”composition“)。使用 composes 属性进行继承

.className {
background-color: skyblue;
}
.title {
composes: className;
color: yellowgreen;
}

继承属性同样可以跨文件实现对应的样式继承

/* 跨文件样式继承 */
.title {
composes: className from './xxx.module.css';
color: red;
}

组件使用样式

import React from 'react'
import style from './style/test.module.css';//引入样式

export default function App() {
console.log('cssModule样式对象',style);
return (
// 使用cssModule样式
<h1 className={style.title}>
Hello React!!!
</h1>
)
}

最终会看到红色的h1在蓝色的背景上
image