AngularJS textarea高度自增directive

textarea元素的高度自增实现起来非常的不方便, 网络上的一些实现方法甚至要使用到额外的pre元素, 这使得textarea实现高度自增的成本远大于设置了contenteditable=”true”属性的div元素.

不过这也不表示纯粹的textarea不能实现高度自增, 本文介绍2种不添加额外元素的textarea高度自增实现方法, 具体的代码编写成了AngularJS的directive.

第一种方法是判断换行符的数量并调节textarea的rows属性, directive如下:

App.directive 'autoHeight',($parse)->  
    (scope, element, attrs)->
        min = if not isNaN attrs['autoHeight'] then attrs['autoHeight'] else element[0].rows
        element.attr 'rows',min
        element.on 'input', (event)->
            rows = element.val().split('\n').length
            element.attr 'rows', Math.max(rows, min)

这种方法虽然简单, 但是缺陷也很明显, 当内容的单行长度超过了textarea的宽度时将不会被认为增加了一行, 导致无法自适应高度. 网络上还有一种计算文字宽度的做法, 我没有尝试过.

另一种方法是通过scrollHeight得到文本的实际高度, 实现比较恶心, 并且可能存在浏览器兼容问题.

App.directive 'autoHeight',($parse)->  
    (scope, element, attrs)->
        min = if attrs['autoHeight'] and not isNaN attrs['autoHeight'] then attrs['autoHeight'] else element[0].scrollHeight
        borderWidth = element.outerHeight() - element.innerHeight()
        element.on 'input', (event)->
            element.height(0)
            element.height borderWidth + Math.max(element[0].scrollHeight, min)

事实上, 如果firefox浏览器中设置了box-sizing为border-box, 计算出的高度就会不正常, 需要判断浏览器的CSS后在borderWidth加上元素的padding值. 在一些浏览器中可能会出现元素向上跳动.