webpack源码分析——truncateArgs函数

一、truncateArgs 函数

函数功能

该函数可以用于用户界面中的文本截断,确保长文本在有限的显示空间内能够适当显示,并且用户可以了解到部分文本已被省略。

函数参数

  • args:参数数组。用于输出到界面上
  • maxLength:当前界面上可容纳最大可输出字符长度。根据当前参数对要输出的内容进行转换(具体转换如下)

假设args中只有一个参数

let args = ['sksddsloxcc']
  • 当 0 < maxLength <=3时,输出args[0]中的字符(计算公式:[args[0].slice(-availableLength)])。比如:maxLength = 1,输出 c 。maxLength = 2 输出 cc
  • 当 3 < maxLength < arg[0].length时, 输出args[0]中的字符(计算公式:[“…” + args[0].slice(-availableLength + 3)])。比如:maxLength = 4 时,输出…c。maxLength = 5时,输出…cc
  • 当 maxLength >= arg[0].length 时,直接返回arg[0]完整字符请添加图片描述

假设args中有多个参数

let args = ['sksddsloxcc', 'dfdffrvxgsvchsgcvgcdcdsvcdbcuydcedvc', '2345vgsscgvschghgvghsgc', '35677vsgscysvcvgyvgv']

当多个参数时,truncateArgs 函数总是想着把多个参数内容,最大化输出到界面上,因此呈现如下规律。

  1. args中所有值的长度和6取最小值最后再相加的和(maxLength-参数间空格数)做比较
    maxLength - lengths.length + 1 < arraySum(lengths.map(i => Math.min(i, 6)))
    
  2. 如果界面的空间放不下,则从右向左去掉一个参数,递归(这里args中数量会有变化),再做比较,如果多个最大值6相加小于maxLength - lengths.length + 1,则进入第3步
  3. 获取当前args数组中参数字符串长度总和并和当前maxLength - lengths.length + 1比较。如果当前内容放的下就直接返回。放不下则进入第4步
    let currentLength = arraySum(args.map(a => `${
           a}`.length));
    // Check if all fits into maxLength
    if (currentLength <= maxLength - lengths.length + 1) return args;
    
  4. 因为当前界面放不下当前参数,于是就截断参数(args)中最长的一个。比如:‘dfdffrvxgsvchsgcvgcdcdsvcdbcuydcedvc’,截取一次做一下比较看当前参数的总长度是否小于或等于可用长度。如果时,就进行输出。不是的话就再次进行挑选参数(args)中最长的一个(注意:本次挑选最长的一个和第一次最长的一个不一定是同一个字符,因为第一次已经对它进行了截取),进行截取

最终效果如下
请添加图片描述

源码分析

  1. 对当前args数组计算每一项值的长度,存为lengths,同时获取当前界面可用长度availableLength

    const lengths = args.map(a => `${
           a}`.length);
    const availableLength = maxLength - lengths.length + 1;
    

    maxLength - lengths.length + 1的意思是 空格也占用空间

  2. 对args数组中只有一项并且availableLength大于0

    if (availableLength > 0 && args.length === 1) {
         
    	if (availableLength >= args[0].length) {
          // 当前界面可用长度完全够用
    		return args;
    	} else if (availableLength > 3) {
          // 当前界面可用长度大于3,则需要拦截并伴随'...'
    		return ["..." + args[0].slice(-availableLength + 3)];
    	} else {
          // 当前界面可用长度太短了,只能显示几个字符
    		return [args[0].slice(-availableLength)]; // 这里是负号,注意顺序
    	}
    }
    
  3. 多参数情况。 检查lengths中每一项之和是否超过界面可用长度,超过了进行递归

    if (availableLength < arraySum(lengths.map(i => Math.min(i, 6)))) {
         
    	// remove args
    	if (args.length > 1)
    		return truncateArgs(args.slice(0, args.length - 1), maxLength);
    	return [];
    }
    

    如果lengths中长度超过6时按照6算,是为了实现在不充裕的界面可用长度下该字符最多显示的数量。就是6个字符。即‘…abc’
    请添加图片描述
    当前界面可用长度为16,去掉空格剩余14。因为装不下所以输出内容,通过availableLength < arraySum(lengths.map(i => Math.min(i, 6))),判断发现可以装下args数组中前3项。所以就打印了前3项内容。至于为什么第1和3项内容有’…',下面会有说明

  4. 检查当前lengths中所有项之和是否超过界面可用长度,没有的话就全部返回。有就需要进行截断最长的项

let currentLength = arraySum(lengths);

// Check if all fits into maxLength
if (currentLength <= availableLength) return args;
  1. 截断最长的项,直到总长度符合要求为止。否则进行循环♻️
while (currentLength > availableLength) {
   
	const maxLength = Math.max(...lengths); // 获取当前最长项的长度
	const shorterItems = lengths.filter(l => l !== maxLength); // 过滤得到不长的项
	const nextToMaxLength =
		shorterItems.length > 0 ? Math.max(...shorterItems) : 0; // 在不长项中找到次长项(比着最长项短点)
	const maxReduce = maxLength - nextToMaxLength; // 获取最长项和次长项之间的差距
	let maxItems = lengths.length - shorterItems.length; // 获取最长项个数,因为有可能lengths有多个最长项
	let overrun = currentLength - availableLength; // 获取溢出的长度
	for (let i = 0; i < lengths.length; i++) {
   
		if (lengths[i] === maxLength) {
   
			// 这里需要比较overrun / maxItems和maxReduce的最小值,以免多减
			const reduce = Math.min(Math.floor(overrun / maxItems), maxReduce);
			lengths[i] -= reduce;
			currentLength -= reduce;
			overrun -= reduce;
			maxItems--;
		}
	}
}
  1. 对截取后的项进行输出
return args.map((a, i) => {
   
	const str = `${
     a}`;
	const length = lengths[i];
	if (str.length === length) {
   
		return str;
	} else if (length > 5) {
   
		return "..." + str.slice(-length + 3);
	} else if (length > 0) {
   
		return str.slice(-length);
	} else {
   
		return "";
	}
});

相关推荐

  1. webpack分析——enhanced-resolve库之cdUp函数

    2024-01-31 07:12:04       13 阅读
  2. webpack分析——loader-runner库之runLoaders函数

    2024-01-31 07:12:04       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-31 07:12:04       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-31 07:12:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-31 07:12:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-31 07:12:04       18 阅读

热门阅读

  1. 深入了解Flutter中的Sliver:介绍与使用场景

    2024-01-31 07:12:04       38 阅读
  2. 网站分享(实用)

    2024-01-31 07:12:04       43 阅读
  3. NetCore iText7 根据PDF模板 导出PDF

    2024-01-31 07:12:04       36 阅读
  4. P8655 [蓝桥杯 2017 国 B] 发现环

    2024-01-31 07:12:04       38 阅读
  5. 最大公约数(左右区间问题)

    2024-01-31 07:12:04       33 阅读
  6. 深入理解并测试HttpResponse —— 关键知识和实践

    2024-01-31 07:12:04       29 阅读
  7. STM32——点灯

    2024-01-31 07:12:04       32 阅读
  8. vue中nextTick()

    2024-01-31 07:12:04       34 阅读
  9. Vue2:请求接口的两种方式axios和vue-resource

    2024-01-31 07:12:04       38 阅读
  10. [GN] DP学习笔记板子

    2024-01-31 07:12:04       32 阅读