跨域

  • 跨域就是请求的url中的“协议”、“域名”、“端口号”其中任何一种不一样都是属于跨域。解决跨域的主要的四种方法是jsonp、跨域资源共享CORS(Cross-Origin Resource Sharing)、proxy代理、webpack中间件。
jsonp解决跨域
  • jsonp只能解决get方法。
  • 在这里设置两个不同的域名,即http://localhost:3000与http://localhost:3001,端口号不同即为跨域。
    为jsonp启动两个不同服务,前端端口号为3000,利用node.js实现,设置代码如下:
const express = require("express");
const app = express();
const path = require("path");
const port = 3000;

app.use(express.static(path.join(__dirname, "public")));

app.get("/", (req, res) => res.send("Hello World!"));

app.listen(port, () => console.log(`3000端口号,启动成功!!`));

后端设置的端口号为3001,代码如下

const express = require('express')
const app = express()
const port = 3001

app.get('/test', (req,res)=>{
    // 接收客户端传递光来的函数名称
    const params = req.query.callback;
    // 将函数名称对应的函数调用返回给客户端
    const fn = params+"({name:'zs'})";
    res.send(fn)
})
app.listen(port, () => console.log(`3001端口号,启动成功!!`))

分别启动之后,在前端中设置如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button id="btn1">发送请求</button>
    <script>
         function fn(data) {
             console.log('客户端的fn被调用了!')
             console.log(data)
         }

        const btn1 = document.querySelector('#btn1');
        btn1.onclick = function () {
             jsonp({
                 url: 'http://localhost:3001/test?callback=fn'
             })
        }
        function jsonp(options) {
            // 动态创建script标签
            const script = document.createElement('script');
            // 设置非同源地址
            script.src = options.url 
            document.body.appendChild(script)
            // 为script标签添加onload事件,否则每发送一次请求就会在body里添加一个script,最终会导致body中有很多的script标签
            script.onload = function () {
                document.body.removeChild(script)
            }
        }
    </script>
</body>

</html>

运行结果
在这里插入图片描述
可以将前端代码封装一下

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button id="btn1">发送请求</button>
    <button id="btn2">发送请求</button>
    <script>
       
        const btn1 = document.querySelector('#btn1');
        const btn2 = document.querySelector('#btn2');
        btn1.onclick = function () {

            jsonp({
                url: 'http://localhost:3001/test',
                // 设置参数
                data: {
                    name: 'lisi',
                    age: 20
                },
                success: function (data) {
                    console.log(123)
                    console.log(data)
                }
            })
        }
        btn2.onclick = function () {
            // jsonp({
            //     url: 'http://localhost:3001/test?callback=fn'
            // })
            jsonp({
                url: 'http://localhost:3001/test',
                // 设置参数
                data: {
                    name: 'lisi',
                    age: 20
                },
                success: function (data) {
                    console.log(456)
                    console.log(data)
                }
            })
        }

        function jsonp(options) {
            // 动态创建script标签
            const script = document.createElement('script');
            var params = ""
            for (let attr in options.data) {
                params += '&' + attr + "=" + options.data[attr];
            }
            // 设置函数名,让每次调用这个函数的时候window都能挂载不同的函数名,解决后端处理的数据是异步的问题,这样就不会覆盖第一次调用了。
            const fileName = 'myJson' + Math.random().toString().replace('.', '');
            // 将传递过来的函数变成全局函数
            // window.fn = options.success;
            window[fileName] = options.success
            // 设置非同源地址
            script.src = options.url + '?callback=' + fileName + params;
            document.body.appendChild(script)
            // 为script标签添加onload事件,否则每发送一次请求就会在body里添加一个script,最终会导致body中有很多的script标签
            script.onload = function () {
                document.body.removeChild(script)
            }
        }
    </script>
</body>

</html>

运行结果
在这里插入图片描述

CORS解决跨域
  • 在这里,将webpack-dev-server将前端启动的端口号设置为8080,后端的端口号利用node.js设置成3000。
    首先下载webpack、webpack-cli、webpack-dev-server、html-webpack-plugin。
    package.js文件如下:
{
  "scripts": {
    "dev": "webpack-dev-server"
  },
  "devDependencies": {
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.39.2",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.2"
  }
}

webpack.config.js文件配置如下:

const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    // 入口
    entry: './src/index.js',
    output: {
        filename: 'index.js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: '/' // 资源路径
    },
    
    plugins: [
        new htmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html'
        })
    ]
}
  • 前端必须要有一个index.html和src文件夹下的index.js
    设置index.js内容:
console.log('log')

const xhr = new XMLHttpRequest()
// 设置发送的请求地址时是同源的
xhr.open('get', 'http://localhost:3000/user', true);
xhr.onload = function () {
    console.log(xhr.responseText)
}
xhr.send()

后端代码设置

const express = require('express')
const app = express()
const port = 3000

// CORS:后端解决跨域问题
var allowCrossDomian = function(req,res,next){
    res.header("Access-Control-Allow-Origin", "*")
    res.header("Access-Contro-Allowl-Headers", "*")
    res.header("Access-Control-Allow-Methods", "*")
    // 必须要要有这个,否则不会执行下面的代码
    next()
}
app.use(allowCrossDomian)

app.get('/user', function(req,res){
    res.json({name : 'jack'})
    console.log(123)
})
app.listen(port, () => console.log(`服务端已启动,端口号3000!`))
proxy代理解决跨域
  • 其他不变,只需要在webpack.config.js中添加如下代码即可。
const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    // 入口
    entry: './src/index.js',
    output: {
        filename: 'index.js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: '/' // 资源路径
    },
    // 添加的代码
    devServer: {
        proxy: { // 代理 前端解决跨域问题
            '/api': {
                target: 'http://localhost:3000',
                changeOrigin: true,
                pathRewrite: {
                    '^/api': '' //这里理解成用‘/api’代替target里面的地址,后面组件中我们掉接口时直接用api代替 比如我要调用'http://40.00.100.100:3002/user/add',直接写‘/api/user/add’即可
                }
            }
        }
    },
    plugins: [
        new htmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html'
        })
    ]
}

修改index.js中的请求路径为:

console.log('log')

const xhr = new XMLHttpRequest()
// 设置发送的请求地址时非同源的
// xhr.open('get', 'http://localhost:3000/user', true);
// 设置proxy代理的请求路径
xhr.open('get', '/api/user', true);
xhr.onload = function () {
    console.log(xhr.response)
}
xhr.send()
webpack中间件解决跨域
  • 首先要下载中间件webpack-dev-middleware
    下载的插件如下:
    在这里插入图片描述
    在后端中添加如下代码:
const express = require('express')
const app = express()
const port = 3000

// CORS:后端解决跨域问题
// var allowCrossDomian = function(req,res,next){
//     res.header("Access-Control-Allow-Origin", "*")
//     res.header("Access-Contro-Allowl-Headers", "*")
//     res.header("Access-Control-Allow-Methods", "*")
//     next()
// }
// app.use(allowCrossDomian)

// 中间件,解决跨域问题
const webpack = require('webpack')
const middle = require('webpack-dev-middleware')
const complier = webpack(require('./webpack.config'))
app.use(middle(complier))


app.get('/user', function(req,res){
    res.json({name : 'jack'})
    console.log(123)
})
app.listen(port, () => console.log(`服务端已启动,端口号3000!`))

以上就是四种方法解决跨域问题,可能讲的不是特别清晰。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐