url 中 # 号与 ? 号的位置关系

721 阅读2分钟

url 中 ? 号后面一般跟的是请求参数,用来给后台传参,# 号后面跟的是 hash,和标签的 id 配合,用来定位页面,那么当一个 url 既要有 ? 号,又要有 # 号时,它们的位置关系应当如何,是 # 号必须在 ? 号前面,还是 ? 号必须在 # 号前面,还是无所谓。

当 url 存在 ? 和 # 号时,# 号是放在 ? 号后面的,通过下面测试代码说明:

html 代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>url 中 # 号与 ? 号的位置关系</title>
    <style>
      #box1, #box2 {
        width: 100px;
        height: 1000px;
        background: red;
      }
      
      #box2 {
        background: green;
      }
    </style>
  </head>
  <body>
    <div id="box1"></div>
    <div id="box2"></div>
  </body>
</html>

node 代码:

const http = require('http');
const url = require('url');
const fs = require('fs');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  console.log('req.url: ', url.parse(req.url));
  
  fs.readFile('test.html', 'utf8' , (err, data) => {
    if (err) {
      console.error(err);
      res.statusCode = 500;
      res.end('');
      return;
    }
    
    res.statusCode = 200
    res.setHeader('Content-Type', 'text/html')
    res.end(data);
  })
});

server.listen(port, hostname, () => {
  console.log(`服务器运行在 http://${hostname}:${port}/`)
});

当请求路径为:http://127.0.0.1:3000/?a=1#box2 时,页面是能定位到 box2 的,同时 node 那边的打印如下:

可以看出,node 端是可以解析出请求参数的,hash 应该为 #box2,但是打印出来时 null,有点奇怪,后面有空看下。

当请求路径为:http://127.0.0.1:3000/#box2?a=1 时,页面不能定位到 box2,同时 node 那边的打印如下:

可以看出,node 端不能解析出请求参数。

通过以上测试,不管是对于前端还是后台,url 中如果同时出现 # 和 ?,# 应该在 ? 号的后面。

这是为什么呢?

对于请求参数,我们一般会用 encodeURIComponent 函数进行转码,encodeURIComponent 函数也会对 # 号进行转码,也就是 ? 号后面如果出现了 # 号,那么 # 号一定不是请求参数的一部分,而是 hash 定位,浏览器应该是这样认为的。如果 # 号在 ? 号前面,当遇到 ? 号时,怎么判断 ? 号是 hash 的一部分,还是请求参数的开始,是无法判断的,标签的 id 的值,又没说,id 中不能出现 ? 号。

综上,url 中出现 # 和 ? 号时,# 号要在 ? 号后面。