Web组件中URL参数+号与空格的正确处理
=====================

#### 问题现象

在使用HarmonyOS系统url.URL.parseURL解析包含+号或空格的查询参数时，+被错误解析为空格，导致参数值丢失或出现语义错误。

#### 背景知识

在标准URL编码规范中RFC 3986，+在application/x-www-form-urlencoded格式中被用作“空格”的占位符。但在大多数现代Web组件和系统中，+应作为普通字符处理，不能与空格混淆。

HarmonyOS系统url.URL.parseURL方法遵循标准解析逻辑，对+号自动解码为空格字符。若未对参数进行正确编码，将导致解析偏差，尤其在使用Web组件传递参数时容易引发问题。

#### 解决方案

为确保+号和空格在Web组件中被正确传递与解析，需遵循以下统一编码策略：

**步骤一：所有参数值必须使用encodeURIComponent编码**

*   使用encodeURIComponent对参数值进行编码，确保+被编码为%2B，空格被编码为%20。
*   避免直接拼接原始字符串，防止解析错误。

const queryParam \= 'hello+world';
const encodedValue \= encodeURIComponent(queryParam);

const finalUrl \= \`https://example.com/search?msg1=${encodedValue}\`;
hilog.info(0x0000, 'testTag', 'URL: %{public}s', finalUrl);

**步骤二：使用url.URL.parseURL解析时，参数值将自动保持语义正确**

*   由于+已被编码为%2B，在解析时不会被误认为是“空格”。
*   空格字符（%20）将被正确解码为空格。

const queryParam1 \= 'hello+world';
const queryParam2 \= 'hello world';
const safeUrl \= \`https://example.com/search?msg2=${queryParam1}&msg3=${queryParam2}\`;

try {
  const parsed \= url.URL.parseURL(safeUrl);
  hilog.info(0x0000, 'testTag', \`params: ${parsed.params}\`);
  parsed.params.forEach((value, key) \=\> {
    hilog.info(0x0000, 'testTag', 'value=%{public}s, key=%{public}s', value, key);
  });
} catch (error) {
  hilog.error(0x0000, 'testTag', 'URL解析失败:', error);
}

完整可运行代码如下：

import hilog from '@ohos.hilog';
import url from '@ohos.url';

@Entry
@Component
struct UrlSafety {
  build() {
    Column() {
      Button('encodedValue')
        .onClick(() \=\> {
          const queryParam \= 'hello+world';
          const encodedValue \= encodeURIComponent(queryParam);

          const finalUrl \= \`https://example.com/search?msg1=${encodedValue}\`;
          hilog.info(0x0000, 'testTag', 'URL: %{public}s', finalUrl);
        }).margin({ bottom: 10 });
      Button('parseURL')
        .onClick(() \=\> {
          const queryParam1 \= 'hello+world';
          const queryParam2 \= 'hello world';
          const safeUrl \= \`https://example.com/search?msg2=${queryParam1}&msg3=${queryParam2}\`;

          try {
            const parsed \= url.URL.parseURL(safeUrl);
            hilog.info(0x0000, 'testTag', \`params: ${parsed.params}\`);
            parsed.params.forEach((value, key) \=\> {
              hilog.info(0x0000, 'testTag', 'value=%{public}s, key=%{public}s', value, key);
            });
          } catch (error) {
            hilog.error(0x0000, 'testTag', 'URL解析失败:', error);
          }
        }).margin({ bottom: 10 });
    }.width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center);
  }
}

#### 常见FAQ

Q：为什么+号在URL中会被解析为空格？

A：这是因为在application/x-www-form-urlencoded格式中，+被规定为“空格”占位符。但在非表单场景中，应避免依赖此行为。

Q：能否用+代替空格？

A：不能。在非表单上下文中，+应视为普通字符。若需表示空格，必须使用%20编码。

Q：encodeURI和encodeURIComponent有何区别？

A：encodeURI仅编码URL中非安全字符，但不编码+和空格；而encodeURIComponent会编码所有特殊字符，包括+和空格，适用于参数值编码。