如何限制textarea域中的字符的个数

本文介绍了一种使用 jQuery 实现 textarea 标签输入长度限制的方法,包括如何编写自定义函数来设置最大字符数,并在输入过程中实时验证和调整。

我们都知道textarea标签没有maxlength属性,那么就需要我们用代码来进行控制,下面是针对texarea写的一个限制输入长度的

jQuery.fn.maxLength = function(max){  
            this.each(function(){  
               var type = this.tagName.toLowerCase(); 
                var inputType = this.type? this.type.toLowerCase() : null;  
                if(type == "input" && inputType == "text" || inputType == "password"){  
                    //Apply the standard maxLength  
                    this.maxLength = max;  
                }  
                else if(type == "textarea"){  
                 this.onkeypress = function(e){  
                     var ob = e || event;  
                     var keyCode = ob.keyCode;  
                     var hasSelection = document.selection? document.selection.createRange().text.length > 0 : this.selectionStart != this.selectionEnd;  
                     return !(this.value.length >= max && (keyCode > 50 || keyCode == 32 || keyCode == 0 || keyCode == 13) && !ob.ctrlKey && !ob.altKey && !hasSelection);  
                 };  
                 this.onkeyup = function(){  
                     if(this.value.length > max){  
                        this.value = this.value.substring(0,max);  
                     }  
                 };  
             }  
         });  
     };  

用法如下:

$('#mytextarea').maxLength(500); 

 

 

 

 

<think>我们之前已经讨论过如何在el-inputtextarea的maxlength计数中去除特殊字符(如换行符)。现在,用户提出了新的需求:希望参考站内引用中的一些方法来实现同样的目标。根据引用[1]和引用[2],我们可以总结出以下几点:1.引用[1]提供了一个方法:在@input事件中,使用正则表达式去除换行符等特殊字符,然后计算有效长度,并截取字符串。2.引用[2]则指出在iOS上换行符会被计算为两个字符(\r\n),所以需要特殊处理。根据用户的需求,我们需要实现一个函数,在输入时动态处理:-去除特殊字符(换行符等)后,检查有效长度是否超过maxlength。-如果超过,则截取字符串,并保留原始字符中的换行符(因为用户可能需要换行,只是不计入总长度)。但是,我们也要注意iOS兼容性问题:在iOS中,换行符实际上是两个字符(\r\n),所以我们在计算原始字符串长度时要考虑这一点。不过,我们去除特殊字符后计算长度时,已经将换行符去除了,所以不需要特别处理。但是,当我们截取字符串时,如果原始字符串中包含换行符,我们需要考虑这些换行符所占的字符数(在非iOS设备上,换行符可能只算一个字符,而在iOS上可能是两个)。然而,在JavaScript中,我们通常获取的换行符是`\n`(一个字符),除非是从某些特定输入(比如iOS的textarea)中获取的可能包含`\r\n`。为了统一,我们可以将换行符都替换为`\n`(一个字符),这样计算长度时就不会有差异。或者,我们在去除换行符时,同时去除`\r`和`\n`,这样无论平台,换行符都被去除,然后我们只计算非换行字符的长度。但是,用户的需求是在计数时不统计换行符,所以我们在计算长度时,应该只考虑非换行符的字符。至于截取字符串,我们需要保证用户输入的换行符仍然保留,只是总有效字符数不超过maxlength。因此,我们可以这样设计:1.在@input事件中,获取当前值。2.去除所有的`\r`和`\n`(即特殊字符),得到纯文本字符串。3.检查纯文本字符串的长度,如果超过maxlength,那么我们需要截取原始字符串(注意:是原始字符串,因为我们要保留换行符),截取的位置需要考虑原始字符串中换行符所占的字符数。但是,如果我们直接按原始字符串截取,那么可能截断的地方正好是一个换行符中间(比如在iOS中,换行符是`\r\n`,如果我们截在中间,会导致乱码吗?)。实际上,在JavaScript中,我们处理的是字符串,换行符在字符串中都是`\n`(一个字符)或者`\r`(一个字符),所以我们可以按字符截取。然而,用户要求保留换行符,只是不计入长度。因此,我们在截取的时候,需要按原始字符串逐个字符遍历,同时维护一个计数器(只统计非换行符的字符),当计数器达到maxlength时,就截取到当前位置。这种方法比较精确,但是相对复杂。另一种简单的方法是:我们允许用户输入任意字符,包括换行,但是当有效字符数(去除换行符后)超过maxlength时,我们通过去除换行符后的字符串截取到maxlength,然后重新构建一个字符串,保留原始字符串中在有效字符位置内的换行符。但是,重新构建字符串会比较复杂。我们可以这样:-遍历原始字符串,同时记录非换行符的个数,当非换行符个数达到maxlength时,我们就结束,并且截取原始字符串的前i个字符(包括中间的换行符)。因此,我们可以写一个函数来实现:```javascripthandleSpecialChars(val){letcleanCount=0;//记录非换行符的字符数letindex=0;//当前遍历到的位置//遍历字符串,直到非换行符数量达到maxlength或者遍历完字符串for(;index< val.length&&cleanCount< this.maxLength;index++){//如果当前字符不是换行符(这里换行符包括\r和\n),那么cleanCount加1if(val[index]!=='\n'&&val[index]!=='\r'){cleanCount++;}}//如果cleanCount达到maxLength,那么我们就截取到当前位置(index)if(cleanCount>=this.maxLength){//如果当前index位置超过0,说明需要截断this.form.text=val.substring(0,index);}else{//否则,直接使用原始值this.form.text=val;}}```但是,这种方法在每次输入时都会遍历整个字符串(直到达到maxlength或结束),如果maxlength很大,而字符串很长,可能会有性能问题。不过,一般maxlength不会太大,所以可以接受。另外,我们还要注意,如果我们截取了字符串,那么输入框的值会改变,从而触发新的@input事件,但由于我们设置的值比原来的短,所以不会再次超过,所以不会死循环。另外,我们可以结合引用[1]中的方法,先去除特殊字符,如果去除后的长度超过maxlength,我们再按照上述方法找到截断位置。这样可以避免每次都遍历,但实际上去除特殊字符也需要遍历字符串,所以性能差不多。这里采用直接遍历的方法,实现如下:```vue<template><el-inputtype="textarea"v-model="form.text":rows="3":maxlength="maxLength":show-word-limit="true"@input="handleSpecialChars"placeholder="请输入内容"></el-input></template><script>exportdefault{data(){return{form:{text:'',//绑定输入值},maxLength:33,//允许的最大有效字符数(不包括换行符)};},methods:{handleSpecialChars(val){letcleanCount=0;//记录非换行符的数量leti=0;//索引//遍历字符串,直到达到最大长度或者字符串结束for(i=0;i< val.length;i++){//如果当前字符不是换行符,则计数if(val[i]!=='\n'&&val[i]!=='\r'){cleanCount++;}//如果非换行符数量达到最大值,则跳出if(cleanCount>=this.maxLength){break;}}//因为我们遍历到了i位置,但有效字符数已经达到maxLength,所以我们要截取到i+1位置吗?//注意:我们遍历到第i个字符时,如果cleanCount>=maxLength,那么我们要包括第i个字符吗?//实际上,当cleanCount超过时,我们就应该停在当前位置(因为我们是在这个字符上达到或超过了),所以应该包括当前位置(因为当前字符是非换行符,才会导致超过,所以我们要截取到当前位置,不包括这个导致超过的字符?)//但我们的逻辑是,当我们处理第i个字符时,如果加上这个字符会导致超过,那么我们就不能包含这个字符。所以应该截取到i(不包含i)。//但是,我们在循环中,当检查到cleanCount已经达到maxLength时,我们break,此时i指向的是导致超过的那个字符的下一个位置?不对,我们在break时,i指向的是当前字符(就是那个让cleanCount达到maxLength的字符)。所以我们应该截取到i+1,这样这个字符就被包括进去了?这样就会导致有效字符超过maxLength一个。//正确的方式:当我们发现当前字符会导致有效字符数超过maxLength,那么这个字符就不能要,所以我们截取到i(不包括位置i的字符)。即0到i-1的字符串。//但是,我们也可以这样理解:我们希望在达到maxLength时就停止,所以当非换行符数量等于maxLength时,我们继续添加一个非换行符就会超过,所以当发现当前字符是非换行符并且cleanCount==maxLength,然后cleanCount++变成了maxLength+1,这时候我们已经超过了,所以不能要这个字符。所以我们截取的位置应该是i-1?这不对,因为i已经指向了当前字符(这个字符导致超过了),所以我们不应该包括它,因此截取的位置是i(即从0到i,不包括i位置,就是0到i-1位置)。//然而,实际上,我们在循环中,当处理第i个字符后,如果cleanCount达到maxLength,我们可以继续,但是当cleanCount即将超过时,我们就要停止。所以,我们在处理每个字符时,检查处理后的cleanCount是否大于maxLength,如果是,则截取到当前位置(不包括当前字符),然后退出循环。//修改逻辑:我们在增加cleanCount之前进行判断,如果增加后大于maxLength,则不能要这个字符,直接跳出循环。//因此,我们将循环内部修改为:letnewVal='';letcleanCount=0;letvalidChars=0;//记录我们保留的字符数(包括换行符),用于最后截取for(leti=0;i< val.length;i++){constchar=val[i];if(char==='\n'||char==='\r'){//如果是换行符,直接保留,且不需要增加cleanCountvalidChars++;}else{//如果还没有超过,则增加,否则跳过if(cleanCount< this.maxLength){cleanCount++;validChars++;}else{//已经超过,所以跳出break;}}}//这样,validChars就是我们要保留的字符数newVal=val.substring(0,validChars);if(newVal!==val){//为了避免死循环,我们只在不相等时才更新this.form.text=newVal;}}}};</script>```但是,这种方法还是有点复杂,而且可能存在性能问题(虽然maxlength不大)。我们也可以使用另一种思路:1.先移除所有换行符,计算有效字符长度。2.如果有效字符长度没有超过maxlength,则保留原字符串。3.如果超过了,我们就需要从原字符串中去除超出部分的字符(但保留换行符)。但是,如何去除呢?我们可以逐个字符遍历,跳过换行符,移除超过的非换行符字符。这里我们可以采用一个更简洁的方法:```javascripthandleSpecialChars(val){//先计算去除换行符后的长度constcleanVal=val.replace(/[\r\n]/g,'');if(cleanVal.length<=this.maxLength){//有效字符数在限制内,直接使用原值this.form.text=val;return;}//如果超过了,我们需要从原字符串中截取,确保有效字符数不超过maxLength,同时保留换行符letcleanCount=0;letnewVal='';for(leti=0;i< val.length;i++){constchar=val[i];if(char==='\n'||char==='\r'){newVal+=char;}else{if(cleanCount< this.maxLength){newVal+=char;cleanCount++;}else{//已经超过,后面的非换行符字符都不加入//但是换行符还要加吗?不加,因为我们要保留换行符,但非换行符已经超了,所以整个字符串到此结束(因为非换行符已经达到最大值,后续即使有换行符也不能加入,因为有效字符数已达到,加入换行符会让位置后面还能输入非换行符?)//注意:我们在这里遇到了一个非换行符,而且已经超过了,所以我们不应该再加任何字符,包括换行符。因为换行符本身不计入总数,但是我们在前面已经有了足够多的非换行符,后续的换行符如果允许,那么用户还可以在换行后输入非换行符,这就不合理了(因为非换行符数量已经被限制)。//所以,我们直接跳出循环。break;}}}this.form.text=newVal;}```这个函数的意思是:我们只保留前面的非换行符字符(数量不超过maxLength)和在这些字符之间(或前后)的换行符。当我们已经加入了maxLength个非换行符后,后面的字符(即使是换行符)也不保留。因为如果后面还有换行符,那么用户就可以在换行后继续输入(虽然我们限制非换行符,但换行符本身会占用一行,而用户输入可能换行后继续输入,但我们已经限制了非换行符的数量,所以后面的换行符就不必要了)。这样,我们确保了总的非换行符数量不超过maxLength。另外,我们也可以在截取后继续添加换行符?这不太符合需求,因为要求是有效字符不超过maxLength。而且我们的截取策略是只保留在达到maxLength之前的换行符,达到maxLength之后的所有字符(包括换行符)都不保留。所以,我们按照上面的代码实现:```vue<template><el-inputtype="textarea"v-model="form.text":rows="3":maxlength="maxLength":show-word-limit="true"@input="handleSpecialChars"placeholder="请输入内容"></el-input></template><script>exportdefault{data(){return{form:{text:'',//绑定输入值},maxLength:33,//允许输入的最大有效字符数(不包括换行符)};},methods:{handleSpecialChars(val){//首先,去除所有换行符和回车符,计算当前有效字符数constcleanVal=val.replace(/[\r\n]/g,'');//如果有效字符数小于等于最大长度,则直接使用原值if(cleanVal.length<=this.maxLength){this.form.text=val;return;}//如果有效字符数超过最大长度,那么我们需要截取字符串letcleanCount=0;letnewVal='';//遍历原始字符串for(leti=0;i< val.length;i++){constchar=val[i];if(char==='\n'||char==='\r'){//如果是换行符,直接保留newVal+=char;}else{//如果是非换行符,检查是否已经达到最大长度if(cleanCount< this.maxLength){newVal+=char;cleanCount++;}else{//已经达到最大长度,终止循环break;}}}this.form.text=newVal;}}};</script>```这种方法会保留在达到有效字符数maxLength之前的所有换行符和非换行符,之后的全部截断。注意:我们在@input事件中修改了form.text的值,这会触发下一次的@input事件,但下一次输入的值(即newVal)经过计算,有效字符数一定不超过maxLength,所以不会进入截取分支,从而避免了死循环。最后,我们还需要考虑用户可能从中间删除字符,导致字符串变短的情况,这个逻辑也兼容。##关于显示字数限制我们使用了`:show-word-limit="true"`,这个属性会显示当前输入的字符总数(包括换行符)和maxlength(我们传入的maxLength)的对比。但是,我们的需求是不统计换行符,所以这里显示的字数限制并不正确(因为它统计了换行符)。要解决这个问题,我们需要自定义字数显示。我们可以不用`:show-word-limit`,而是自己写一个div来显示有效字符数(去除换行符后的字符数)和最大限制。例如:```vue<template><div><el-inputtype="textarea"v-model="form.text":rows="3"@input="handleSpecialChars"placeholder="请输入内容"></el-input><divclass="word-limit">有效字符数:{{effectiveCharCount}}/{{maxLength}}</div></div></template><script>exportdefault{data(){return{form:{text:'',//绑定输入值},maxLength:33,//允许输入的最大有效字符数(不包括换行符)effectiveCharCount:0};},methods:{handleSpecialChars(val){//...按照上面的逻辑处理//在每次处理完,计算有效字符数this.effectiveCharCount=this.form.text.replace(/[\r\n]/g,'').length;}},watch:{'form.text'(val){this.effectiveCharCount=val.replace(/[\r\n]/g,'').length;}}};</script>```这样,我们就能显示正确的不包括换行符的字符计数了。##总结1.通过@input事件处理输入,去除换行符后计算有效字符长度。2.如果有效字符长度超过最大限制,则遍历原始字符串,只保留在达到最大有效字符数前的非换行符和此位置前的换行符,后面的全部截断。3.自定义显示有效字符数,不使用ElementUI自带的字数统计。##相关问题1.如何在el-inputtextarea中同时限制每行字符数和总行数?2.如何处理textarea换行符在移动端(特别是iOS)的兼容性问题?3.如何通过CSS使textarea中的换行符(连续空格和换行)正确显示?</think> ### 实现 el-input textarea 的 maxlength 计数忽略特殊字符(如换行符) 以下是实现方案(基于 Vue.js + Element UI): ```vue <template> <div> <el-input type="textarea" v-model="textValue" :rows="4" placeholder="输入内容(换行符不计入字数)" @input="handleTextInput" ></el-input> <div class="custom-counter"> 有效字数:{{ effectiveCharCount }}/{{ maxLength }} </div> </div> </template> <script> export default { data() { return { textValue: '', maxLength: 100, // 最大有效字符数(忽略换行符) }; }, computed: { // 计算不包含换行符的实际字符数 effectiveCharCount() { return this.textValue.replace(/[\r\n]/g, '').length; } }, methods: { handleTextInput(value) { // 计算忽略换行符后的实际字符数 const cleanVal = value.replace(/[\r\n]/g, ''); if (cleanVal.length > this.maxLength) { // 超出限制时进行截断 let validLength = 0; let finalValue = ''; // 逐个字符处理(保留换行符但统计有效字符) for (let char of value) { if (char === '\n' || char === '\r') { finalValue += char; // 保留换行符 } else { if (validLength < this.maxLength) { finalValue += char; validLength++; } } } this.textValue = finalValue; } else { this.textValue = value; } } } }; </script> <style> .custom-counter { color: #909399; font-size: 12px; text-align: right; padding: 0 12px; } </style> ``` ### 关键实现解析 1. **特殊字符处理** 使用正则表达式 `replace(/[\r\n]/g, '')` 去除换行符后计算实际字符数 2. **输入时动态处理** `@input` 事件中检测有效字符数,超过限制时: - 保留已有换行符 - 截断多余的非换行字符 3. **iOS 兼容性** 同时处理 `\r`(回车) 和 `\n`(换行) 字符,兼容不同系统的换行符差异[^2] 4. **自定义计数器** 通过计算属性 `effectiveCharCount` 显示真实的字符统计(不包含换行符) 5. **视觉显示优化** 添加 `white-space: pre-wrap` 确保换行显示正确:[^3] ```css .el-textarea__inner { white-space: pre-wrap; word-break: break-all; } ``` ### 特性说明 1. **换行符完全保留** - 用户可以正常换行 2. **实时精确计数** - 计数器忽略所有换行字符 3. **输入保护机制** - 阻止输入超出限制的有效字符 4. **跨平台兼容** - 同时处理 Windows(\r\n) 和 Unix(\n) 换行格式 如果需要保留其他特殊字符(如制表符),只需修改正则表达式: ```js // 同时忽略换行符和制表符 const cleanVal = value.replace(/[\r\n\t]/g, ''); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值