今天在项目上客户有个需要是这样的。
我们做的一个统一待办系统页面,待办的标题如果过长就用“...”代替,但是如果直接用javascript的length来控制会有问题,因为中文汉字会占两个占位符,数字或英文字母占一个占位符,所以就要区分标题中是汉字还是英文。
所以我在javascript中写了一个方法,将中文汉字或者中文的标点符号换成两个字符,最后返回真实的长度,但是单单返回这个还不能满足需求,所以,我返回了一个数组Array,具体代码如下:
function getStrLength(str, idx){ var arr = new Array(); var realLength = 0;//总的字符数 var numLength = 0;//除汉字的个数 var chineseLength = 0;//汉字的个数 var tempIdx = 0; var flag = true; for(var i=0;i<str.length;i++){ var charCode = str.charCodeAt(i); if(charCode >=0 && charCode <= 128){ realLength += 1; numLength ++; }else{ realLength += 2; chineseLength ++; } if(realLength>idx && flag){ tempIdx = i; flag = false; } } if(tempIdx==0){ tempIdx = str.length; } arr[0] = realLength; arr[1] = numLength; arr[2] = chineseLength; arr[3] = tempIdx; return arr; } 方法简单说明:
1.使用javascript语言的charCodeAt()方法,该方法返回 制定索引的Unicode值,通过Unicode值可以判断是数字字母还是中文汉字或者中文符号,这样可以算出真实的占位的长度。
2.返回中文的chineseLength和字母(数字)的numLength是为了更好的测试代码
3.返回一个tempIdx时表示该字符串可以从哪个索引(length获得)截取字符串了
故在代码中获得真正要显示的待办标题就可以这样写:
var orderNameArr = getStrLength(orderName, 37); console.log("displayName前:"+orderName); console.log("orderNameArr:"+"真实长度:"+orderNameArr[0]+", 数字或字母有:"+orderNameArr[1]+", 汉字有:"+orderNameArr[2]+", 到第几个字符时有40长度了:"+orderNameArr[3]); if(orderNameArr[0] > 37){ displayName = orderName.substring(0, orderNameArr[3])+"..."; console.log("截取displayName后:"+displayName); }else{ displayName = orderName; console.log("没有截取displayName后:"+displayName); } 该方法中的37是在实际项目中一点一点试出来的,因为在字号确定的情况下,不能让其换行,最多显示37(真实长度)个占位符
但是使用javascript实现此需求后,切换到环境中,发现整个页面加载速度变得很慢,很影响性能,这里还没有对性能差做其他渗入的研究,故在后台使用java对待办的标题做了处理。用同样的逻辑使用java后加载和整体效果还可以。下面附上写的java代码:
public static Map<String, Integer> getStrLength(String str, int num){ Map<String, Integer> map = new HashMap<String, Integer>(); char[] chff = str.toCharArray(); int realLength = 0; int numLength = 0; int chineseLength = 0; int tempIdx = 0; boolean flag = true; for(int i=0;i<chff.length;i++){ String s = String.valueOf(chff[i]); System.out.println("s:"+s); System.out.println("flag:"+flag); if(s.matches("[^\\x00-\\xff]")){//是汉字,或者占两个字符 realLength += 2; chineseLength ++; }else{ realLength += 1; numLength ++; } if(realLength > num && flag){ tempIdx = i; flag = false; } } if(tempIdx==0){ tempIdx = str.length(); } map.put("realLength", realLength); map.put("numLength", numLength); map.put("chineseLength", chineseLength); map.put("tempIdx", tempIdx); return map; }
因为java中汉字有几个字节是跟字符编码集有关的,假如是utf-8编码的,中文汉字就是三个字节,如果是GBK编码的就是两个字节,我一时没有找到能区分一个汉字(或字母数字)占几个占位符的方法,后来查到char类型中,一个char占两个字节,String有个方法可以转换成char[](char数组),但是char数组不可以使用正则,故还要将char类型在转换成String
1.String 转换成 char数组
char[] chff = str.toCharArray(); 2.char类型转换成 String
String s = String.valueOf(chff[i]); 3.使用正则判断是否为汉字 s.matches("[^\\x00-\\xff]") 4.逻辑和javascript一样,只不过方法不太一样,故在这里做个记录。这样下来,java的性能确实要优于javascript
知识是一点一点积累起来的。
不积跬步,无以至千里。不积小流,无以成江海。