/** * 替换字符串中的占位符 * 支持多种插值语法: * 1. 数字索引:{0}, {1}, {2}... * 2. 命名参数:{name}, {age}... * 3. 对象属性:{user.name}, {user.age}... * * @param template 模板字符串,如 "Hello {0}, welcome to {1}" 或 "Hello {name}, welcome to {place}" * @param values 要替换的值,可以是数组、对象或混合 * @returns 替换后的字符串 */ export function interpolateTemplate(template, values) { if (!template || typeof template !== 'string') { return template; } // 如果没有提供值,直接返回模板 if (values === undefined || values === null) { return template; } // 处理数组形式的参数 if (Array.isArray(values)) { return template.replace(/{(\d+)}/g, (match, index) => { const numIndex = parseInt(index, 10); return values[numIndex] !== undefined ? String(values[numIndex]) : match; }); } // 处理对象形式的参数 if (typeof values === 'object') { return template.replace(/{([^}]+)}/g, (match, key) => { // 处理嵌套对象属性,如 {user.name} const keys = key.trim().split('.'); let value = values; for (const k of keys) { if (value && typeof value === 'object' && k in value) { value = value[k]; } else { return match; // 如果找不到对应的值,保持原样 } } return value !== undefined ? String(value) : match; }); } // 如果values不是数组也不是对象,直接返回模板 return template; } /** * 增强的插值函数,支持更复杂的插值语法 * @param template 模板字符串 * @param values 插值参数 * @param options 配置选项 * @returns 替换后的字符串 */ export function advancedInterpolate(template, values, options = {}) { if (!template || typeof template !== 'string') { return template; } const { fallback = '', // 当找不到对应值时的默认值 prefix = '{', // 插值前缀 suffix = '}', // 插值后缀 escape = false // 是否转义HTML } = options; // 构建正则表达式 const regex = new RegExp(`${escapeRegExp(prefix)}([^${escapeRegExp(suffix)}]+)${escapeRegExp(suffix)}`, 'g'); return template.replace(regex, (match, key) => { const trimmedKey = key.trim(); let value = getNestedValue(values, trimmedKey); if (value === undefined) { return fallback || match; } // 转换为字符串 let result = String(value); // HTML转义 if (escape) { result = result .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } return result; }); } /** * 获取嵌套对象的值 * @param obj 对象 * @param path 路径,如 'user.name' 或 '0.name' * @returns 值 */ function getNestedValue(obj, path) { if (!obj || typeof obj !== 'object') { return undefined; } const keys = path.split('.'); let value = obj; for (const key of keys) { if (value && typeof value === 'object') { // 如果是数字索引,尝试作为数组访问 if (/^\d+$/.test(key)) { const index = parseInt(key, 10); value = Array.isArray(value) ? value[index] : value[key]; } else { value = value[key]; } } else { return undefined; } } return value; } /** * 转义正则表达式特殊字符 * @param string 字符串 * @returns 转义后的字符串 */ function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }