先一起重新学习有关URL的基础知识,
关注H5与原生app通信部分的同学可以直接划到第五章!
一、URL
URL 是Uniform Resource Locator 的简称,也叫“统一资源定位符”。是用于定位互联网上资源的字符串。
一个标准的URL格式的包含了以下的基础元素:
1、Protocol - 协议:指定了访问资源所使用的协议类型,比如http、https、ftp等。
2、User:Password - 用户名和密码(可选):某些资源可能需要身份验证,这部分用于提供用户名和密码。在现代Web应用中,这种方式已经较少使用,更多是通过其他方式(如OAuth、API密钥等)进行身份验证。
3、Hostname - 主机名:资源的服务器地址,比如www.example.com。
4、Port - 端口号(可选):服务器监听的端口,如果省略,则使用协议的默认端口(如HTTP的默认端口是80,HTTPS的默认端口是443)。
5、Path - 路径:资源在服务器上的位置,比如/path/to/resource。
6、Query String - 查询参数(可选):向服务器传递的额外信息,通常用于过滤或定制响应,以?开头,后面跟着一个或多个键值对,键值对之间用&分隔,比如?key1=value1&key2=value2。
7、Fragment Identifier - 片段标识符(可选):用于指定资源的某一部分,通常用于HTML页面中的导航,以#开头,比如#section1。
一个完整的URL示例可能如下所示:
https: //username:password@w ww.example.com:8080/path/to/resource?key1=value1&key2=value2#section1
当然了,大多数情况,URL可能看起来像这样,这就是更常见的形式了:
https: //w ww.example.com/path/to/page?search=query#results
在这个例子中: https 是协议。 w ww.example.com 是主机名。 /path/to/page 是路径。 ?search=query 是查询参数。 #results 是片段标识符。
二、URL()
在使用URL时,有一个很好用的构造函数——new URL(),用于创建一个表示 URL 的 URL 对象。这个对象提供了一系列属性和方法来解析、构造、规范化和编码 URLs。
如何使用
当你使用 new URL(url, base) 创建一个新的 URL 对象时,你可以传入两个参数:
1、url:要解析的 URL 字符串。这可以是一个完整的 URL,也可以是一个相对 URL(在这种情况下,它会根据第二个参数 base 来解析)。
2、base(可选):一个表示基本 URL 的字符串或 URL 对象。如果提供了这个参数,并且第一个参数 url 是一个相对 URL,那么 url 会相对于 base 来解析。如果没有提供 base,那么 url 会被解析为相对于当前文档的 URL(在浏览器环境中)。
URL 对象提供了很多有用的属性和方法
比如:
-
href:获取或设置整个 URL。
-
protocol:获取 URL 的协议部分(例如 https:)。
-
host:获取 URL 的主机部分(例如 www.example.com)。
-
hostname:类似于 host,但不包括端口号。
-
port:获取 URL 的端口号(如果有的话)。
-
pathname:获取 URL 的路径部分(例如 /path/to/resource)。
-
search:获取 URL 的查询字符串部分(例如 ?name=value&name2=value2)。
-
hash:获取 URL 的哈希部分(例如 #section1)。
此外,URL 对象还提供了 toString() 方法来返回序列化后的 URL 字符串,以及 searchParams 属性来访问和操作查询字符串的参数。
下面是一个使用 new URL() 的例子:
const urlString = "https://www.example.com:8080/path/name?search=test#hash";`
const myURL = new URL(urlString);
console.log(myURL.href); // 输出完整的 URL 字符串
console.log(myURL.protocol); // 输出 "https:"
console.log(myURL.host); // 输出 "www.example.com:8080"
console.log(myURL.hostname); // 输出 "www.example.com"
console.log(myURL.port); // 输出 "8080"
console.log(myURL.pathname); // 输出 "/path/name"
console.log(myURL.search); // 输出 "?search=test"
console.log(myURL.hash); // 输出 "#hash"
// 使用 searchParams 访问和操作查询字符串参数
const params = myURL.searchParams;
console.log(params.get("search")); // 输出 "test"
params.append("newParam", "newValue");
console.log(myURL.search); // 输出 "?search=test&newParam=newValue"
URL 对象在处理和分析网页中的 URL 时非常有用,特别是在需要构建、修改或解析 URL 的情况下。
三、百分号编码(百分数编码)
这是一种编码机制,用于将非ASCII字符或URL中的特殊字符转换为可以在互联网上安全传输的格式。这种编码方式通过在需要编码的字符前加上一个%符号,并紧接着该字符的ASCII码(或对于非ASCII字符,其UTF-8编码的字节的)十六进制值来实现。
在URL中,某些字符具有特殊的含义或作用,例如:、/、?、#、[、]、@、!、$、&、'、(、)、*、+、,、;、=和空格等。这些字符被称为保留字符,因为它们被URL的语法保留用于特定的目的。当这些字符需要作为URL的一部分进行传输时,它们必须进行URL编码。
我们经常可以看到一些url中包含 %7B、 %20、 %22,这就是“百分号编码”。
常见的有:
-
空格:在URL中,空格字符是一个特殊字符,它不能直接在URL中出现。因此,空格通常被编码为%20。例如,字符串"Hello World"在URL编码后会变成"Hello%20World"。
-
加号:虽然加号(+)在URL中有特定的用途(作为空格的替代字符,在某些上下文中),但在需要进行百分号编码时,加号本身也会被编码为%2B。
-
斜杠:斜杠(/)在URL中用作路径分隔符,因此它也是一个特殊字符。然而,在某些情况下(如编码查询字符串中的斜杠),斜杠也可能被编码为%2F。
-
问号(?)在URL中用作查询字符串的开始标志,因此它也是一个特殊字符。在需要对问号进行编码时,它会被编码为%3F。
-
井号(#)在URL中通常用于表示片段标识符(即URL中#后面的部分),因此它也是一个特殊字符。在需要对井号进行编码时,它会被编码为%23。
-
和号(&)在URL中用作参数分隔符,在查询字符串中分隔不同的键值对。因此,它也是一个特殊字符,在编码时会被转换为%26。
-
等号(=)在URL中用作键值对的分隔符,在编码时会被转换为%3D。
-
百分号(%)本身在URL编码中用作引入十六进制值的标志,因此当需要对百分号进行编码时,它会被编码为%25。
四、URL的编码和解码
在JavaScript中,处理URL的编码和解码主要依赖于两个内置函数:encodeURIComponent 和 decodeURIComponent,以及它们的“非组件”版本 encodeURI 和 decodeURI。
以下是这些函数的使用方法和区别:
编码URL组件
encodeURIComponent 函数用于对URL的某个组件(如查询字符串中的参数值)进行编码。它会将字符串中的特殊字符(如空格、&、=、%等)转换为对应的百分号编码形式。
let plainString = "Hello World! & Special % Characters";
let encodedString = encodeURIComponent(plainString);
console.log(encodedString); // 输出:"Hello%20World%21%20%26%20Special%20%25%20Characters"
解码URL组件
decodeURIComponent 函数用于解码使用 encodeURIComponent 编码的URL组件。它会将百分号编码的字符串还原为原始字符串。
let encodedString = "Hello%20World%21%20%26%20Special%20%25%20Characters";
let decodedString = decodeURIComponent(encodedString);
console.log(decodedString); // 输出: "Hello World! & Special % Characters"
编码整个URL
encodeURI 函数用于对整个URL进行编码,但它主要编码URL中的非ASCII字符和一些特殊字符(如空格),而不会对URL中的保留字符(如:、/、?、#、@等)进行编码。
let plainURL = "https://example.com/path?name=Hello World! & age=25";
let encodedURL = encodeURI(plainURL);
console.log(encodedURL); // 输出:"https://example.com/path?name=Hello%20World%20%26%20age=25"
// 注意:这里的空格被编码为%20,但&没有被编码为%26,因为&是URL的保留字符。
然而,在实际应用中,通常只需要对URL的查询字符串部分或特定组件使用 encodeURIComponent 进行编码,而不是对整个URL进行编码。
解码整个URL(通常不需要)
decodeURI 函数用于解码使用 encodeURI 编码的整个URL。但是,在大多数情况下,你不需要对整个URL进行解码,因为浏览器会自动处理URL的解码。
// 假设你有一个之前编码过的URL
let encodedURL = "https://example.com/path?name=Hello%20World%20%26%20age=25";
// 注意:这里使用decodeURI并不会改变URL的结构,因为URL中的保留字符不会被解码
let decodedURL = decodeURI(encodedURL);
console.log(decodedURL); // 输出: "https://example.com/path?name=Hello World & age=25"
// 但是,请注意,这里的空格和&仍然是URL的一部分,没有被进一步处理为普通字符。
注意事项
当你需要对URL的某个组件(如查询字符串的值)进行编码时,应使用 encodeURIComponent。
当你需要解码之前使用 encodeURIComponent 编码的URL组件时,应使用 decodeURIComponent。
在大多数情况下,你不需要对整个URL进行编码或解码。如果需要,请确保你了解编码和解码的影响,因为对整个URL进行编码可能会导致URL的结构被破坏。
编码和解码时,应确保输入的字符串是有效的URL组件或URL,以避免出现意外的结果或错误。
五、与原生APP交互的回调URL
以下是一个H5与原生app 通信的回调URL:
https: //w ww.xxx.com/...path.../index.html?scheme=jsbridge://w ww.yyy.com/app/operation/openMainPageTab¶ms=%7B%22tab%22%3A%22main%22%7D
这个URL的最后部分携带了重要的参数:
-
scheme:其值为jsbridge://w ww.yyy.com/app/operation/openMainPageTab。这个参数用于指示某种特定的协议或操作,jsbridge是一个用于在Web页面和原生应用之间通信的桥梁。(有关jsbridge的补充内容在文章结尾 ↓) -
params:其值为%7B%22tab%22%3A%22main%22%7D,这是一个经过URL编码的JSON字符串,解码后为{"tab":"main"}。这个参数包含了要传递给原生应用的具体信息。
这个URL就会告诉app:“我要跳转到你的main页面~”
想要实现这种交互,只需要使用 window.location.replace(URL) 就可以跳转到app中的对应页面啦。
app端如何实现
-
场景描述:在Web页面中,可能需要调用原生应用的一些特定功能,如打开原生应用的某个页面、执行某个操作等。这时,可以通过构造一个特殊的URL,并在其中嵌入原生应用能够识别的scheme和参数,来实现从Web页面到原生应用的通信。
-
实现方式:在Web页面中,通过JavaScript代码(如
window.location.href或window.location.replace)跳转到这个特殊的URL。原生应用会监听这些URL的访问请求,并解析其中的scheme和参数,然后根据这些信息执行相应的操作。
补充知识点:jsbridge 是什么
JSBridge,即JavaScript Bridge的简写,是一座连接Web端(JavaScript代码)和Native端(原生应用代码)的桥梁。它允许前端JavaScript代码调用原生应用的功能,并接收来自原生应用的回调,同时原生应用也能够通过JSBridge向JavaScript发送消息。这种双向通信通道为混合开发(Hybrid Development)中的前端部分提供了方便,使其能够充分利用原生应用的功能,如摄像头、定位服务等。
具体来说,JSBridge的作用包括但不限于:
-
实现功能调用:通过JSBridge,Web页面可以调用原生应用中的功能,如打开摄像头、访问文件系统、使用定位服务等。这些功能在纯Web应用中可能难以实现或性能不佳,但在原生应用中则可以轻松实现。
-
数据传递与同步:JSBridge还允许Web页面与原生应用之间传递数据,实现数据的同步和共享。这对于需要在Web页面和原生应用之间共享状态或数据的场景非常有用。
-
提高应用性能和用户体验:通过利用原生应用的功能和性能优势,JSBridge可以帮助提高混合应用的性能和用户体验。例如,使用原生UI组件可以比纯Web组件更流畅地呈现用户界面。
在实际应用中,JSBridge的实现方式可能因平台和框架的不同而有所差异。在移动应用开发中,常见的原生平台包括iOS和Android,而常用的混合开发框架如React Native、Flutter等也提供了与原生代码交互的接口。在这些平台上,开发者可以使用特定的API或库来创建和管理JSBridge的实例,从而实现Web页面与原生应用之间的通信。
总之,JSBridge是混合开发中不可或缺的一部分,它使得Web页面能够充分利用原生应用的功能和性能优势,为用户提供更加丰富和流畅的体验。