丢弃掉模板语法和‘+‘来拼接url,解决无效代码

        在前端开发中,我们经常需要处理URL,例如在发起HTTP请求时构建API端点,或在页面导航时构建动态链接、拼接动态参数。 过去,我们习惯于使用模板语法和字符串拼接来构建这些URL,现在在代码中依然可以看到新的代码还在使用这种方法。 但这种方法不仅容易出错,而且在维护和阅读代码时也不够直观。本文将介绍更现代和更安全的URL构建方法,并展示如何在实际项目中应用它们。

传统上,我们常使用字符串拼接或模板语法来构建URL。例如:

const baseUrl = "https://api.example.com"; 
const userId = 12345; 
const endpoint = baseUrl + "/users/" + userId + "/details"; 
console.log(endpoint); // "https://api.example.com/users/12345/details"
import { TYPE_EDIT } from '@/constants/type.ts'
const type = TYPE_EDIT
const url = 'https://api.example.com/userInfo'
const newUrl = url + '?type=' + type + '&model=1&share=1&fromModule=wechat'
console.log(urlUrl) // https://api.example.com/userInfo?type=TYPE_EDIT&model=1&share=1&fromModule=wechat

或使用ES6模板字符串:

const baseUrl = "https://api.example.com";
const userId = 12345;
const endpoint = `${baseUrl}/users/${userId}/details`;
console.log(endpoint); // "https://api.example.com/users/12345/details"
import { TYPE_EDIT } from '@/constants/type.ts'
const type = TYPE_EDIT 
const url = 'https://api.example.com/userInfo' 
const newUrl = url + `?type=${type}&model=1&share=1&fromModule=wechat` 
console.log(urlUrl) // https://api.example.com/userInfo?type=TYPE_EDIT&model=1&share=1&fromModule=wechat

虽然模板字符串在一定程度上提高了可读性,但这种方法仍存在几个问题:

  1. 易读性差:当URL变得复杂时,拼接和模板字符串会变得难以阅读和维护(现阶段已经难以阅读和维护了)。
  2. 错误处理麻烦:拼接过程中如果有任何错误(例如漏掉斜杠),可能会导致难以排查的BUG。
  3. 缺乏类型安全:拼接字符串无法提供编译时的类型检查,容易引入错误。

使用URL构造器

为了解决这些问题,现代JavaScript引入了URL构造器,可以更优雅和安全地处理URL。URL构造器提供了一种更结构化和直观的方法来构建和操作URL。

基本用法

const baseUrl = "https://api.example.com";
const userId = 12345;
const url = new URL(`/users/${userId}/details`, baseUrl);
console.log(url.href); // "https://api.example.com/users/12345/details"

添加查询参数

URL构造器还提供了一种简便的方法来添加和操作查询参数:

const baseUrl = "https://api.example.com";
const userId = 12345;

const url = new URL(`/users/${userId}/details`, baseUrl);
url.searchParams.append('type', 'EDIT');
url.searchParams.append('module', 'wechat');
console.log(url.href); // "https://api.example.com/users/12345/details?type=EDIT&module=wechat"

拼接数组参数

假设我们有一个URL,需要将一个数组作为查询参数添加到URL中。

const baseUrl = 'https://example.com';
const url = new URL(baseUrl);

const arrayParam = ['value1', 'value2', 'value3'];
// 将数组转换为逗号分隔的字符串
url.searchParams.set('array', arrayParam.join(','));

console.log(url.toString()); // https://example.com/?array=value1,value2,value3

解析数组参数

当我们获取URL并需要解析其中的数组参数时,可以使用URLSearchParams对象进行解析。

const urlString = 'https://example.com/?array=value1,value2,value3';
const url = new URL(urlString);

const arrayParamString = url.searchParams.get('array');
// 将逗号分隔的字符串转换回数组
const arrayParam = arrayParamString ? arrayParamString.split(',') : [];

console.log(arrayParam); // ['value1', 'value2', 'value3']

以下是一个完整示例,包括拼接和解析数组参数的操作:

// 拼接数组参数到URL
const baseUrl = 'https://example.com';
const url = new URL(baseUrl);

const arrayParam = ['value1', 'value2', 'value3'];
url.searchParams.set('array', arrayParam.join(','));

console.log(url.toString()); // https://example.com/?array=value1,value2,value3

// 解析数组参数从URL
const urlString = url.toString();
const parsedUrl = new URL(urlString);

const arrayParamString = parsedUrl.searchParams.get('array');
const parsedArrayParam = arrayParamString ? arrayParamString.split(',') : [];

console.log(parsedArrayParam); // ['value1', 'value2', 'value3']

处理多个同名参数

有时我们可能会遇到需要处理多个同名参数的情况,例如?array=value1&array=value2&array=value3。可以使用URLSearchParamsgetAll方法:

// 拼接多个同名参数到URL
const url = new URL(baseUrl);

const arrayParam = ['value1', 'value2', 'value3'];
arrayParam.forEach(value => url.searchParams.append('array', value));

console.log(url.toString()); // https://example.com/?array=value1&array=value2&array=value3

// 解析多个同名参数从URL
const urlString = url.toString();
const parsedUrl = new URL(urlString);

const parsedArrayParam = parsedUrl.searchParams.getAll('array');

console.log(parsedArrayParam); // ['value1', 'value2', 'value3']

通过这些方法,可以更加优雅和简便地处理URL中的数组参数,提升代码的可读性和可维护性。

但实际情况往往比上面的示例更复杂,比如参数是一个对象、根据实际情况来设置参数的值、要处理undefined'undefined'0'0'Boolean'true'NaN等不同类型和异常的值,每次使用时都去处理显然是不合理的,这时候就可以将拼接和移除参数的函数封装成方法来使用。

/**
 * 获取URL查询参数并返回一个对象,支持数组
 * @param {string} urlString - 需要解析的URL字符串
 * @returns {Object} - 包含查询参数的对象
 */
function getURLParams(urlString) {
    const url = new URL(urlString);
    const params = new URLSearchParams(url.search);
    const result = {};

    for (const [key, value] of params.entries()) {
        if (result[key]) {
            if (Array.isArray(result[key])) {
                result[key].push(value);
            } else {
                result[key] = [result[key], value];
            }
        } else {
            result[key] = value;
        }
    }

    return result;
}

/**
 * 设置URL的查询参数,支持对象和数组
 * @param {string} urlString - 基础URL字符串
 * @param {Object} params - 需要设置的查询参数对象
 * @returns {string} - 带有查询参数的URL字符串
 */
function setURLParams(urlString, params) {
    const url = new URL(urlString);
    const searchParams = new URLSearchParams();

    for (const key in params) {
        if (params.hasOwnProperty(key)) {
            const value = params[key];
            if (Array.isArray(value)) {
                value.forEach(val => {
                    if (val !== undefined && !Number.isNaN(val)) {
                        searchParams.append(key, val);
                    } else {
                        console.warn(`Warning: The value of "${key}" is ${val}, which is invalid and will be ignored.`);
                    }
                });
            } else if (value !== undefined && !Number.isNaN(value)) {
                searchParams.append(key, value);
            } else {
                console.warn(`Warning: The value of "${key}" is ${value}, which is invalid and will be ignored.`);
            }
        }
    }

    url.search = searchParams.toString();
    return url.toString();
}

// 测试用例
const baseUrl = 'https://example.com';

// 测试 getURLParams 方法
const testUrl = 'https://example.com/?param1=value1&param2=value2&param2=value3';
const parsedParams = getURLParams(testUrl);
console.log(parsedParams); // { param1: 'value1', param2: ['value2', 'value3'] }

// 测试 setURLParams 方法
const params = {
    param1: 'value1',
    param2: ['value2', 'value3'],
    param3: undefined,
    param4: NaN,
    param5: 'value5',
    param6: 0,
};

const newUrl = setURLParams(baseUrl, params);
console.log(newUrl); // 'https://example.com/?param1=value1&param2=value2&param2=value3&param5=value5'
以上代码是根据掌握的知识编写的基本使用示例,像这种工作完全不用自己来写,现在已经有非常成熟的库可以直接使用。
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个基本的Unity游戏背包丢弃物品,物品落在地上的代码系统。请注意,这是一个非常基本的示例,你可能需要进行修改和优化以适应你的具体游戏需求。 ``` using UnityEngine; using System.Collections.Generic; public class Inventory : MonoBehaviour { public List<GameObject> items = new List<GameObject>(); // 存储物品的列表 public GameObject itemPrefab; // 物品的预制体 public void DropItem(int index) { // 检查物品索引是否有效 if (index < 0 || index >= items.Count) { Debug.LogError("Invalid item index"); return; } // 从列表中删除物品 GameObject item = items[index]; items.RemoveAt(index); // 创建一个新的物品实例,并将其放置在玩家位置上方一定高度处 Vector3 playerPos = transform.position; Vector3 dropPos = new Vector3(playerPos.x, playerPos.y + 1.0f, playerPos.z); GameObject dropItem = Instantiate(itemPrefab, dropPos, Quaternion.identity); // 将物品的模型设置为刚被删除的物品的模型,并添加一个附加物体以存储物品数据 dropItem.GetComponentInChildren<MeshFilter>().mesh = item.GetComponentInChildren<MeshFilter>().mesh; dropItem.GetComponentInChildren<MeshRenderer>().material = item.GetComponentInChildren<MeshRenderer>().material; dropItem.AddComponent<ItemData>().item = item.GetComponent<ItemData>().item; } } public class ItemData : MonoBehaviour { public Item item; // 物品数据 } public class Item : MonoBehaviour { public string itemName; // 物品名称 public int itemID; // 物品ID // 其他物品数据... } ``` 在这个代码示例中,`Inventory`类存储了一个包含物品的列表`items`,并提供了一个方法`DropItem()`来丢弃列表中的物品。当调用该方法时,它将从列表中删除指定索引处的物品,然后将其实例化为一个新的物体,将其放置在玩家位置上方一定高度处,并将物品模型和数据添加到新的物体上。 `ItemData`类是一个用于存储物品数据的附加物体。它包含一个名为`item`的公共变量,该变量存储了一个指向`Item`类的引用,`Item`类包含了有关物品的所有数据。 请注意,这个代码示例是非常基础的,你可能需要在其基础上进行扩展和优化以满足你的具体游戏需求。例如,你可能需要在物品上添加其他组件以实现交互或特殊效果,或者你可能需要在物品丢弃时产生不同的动画或声音效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值