需求简介

一个搜索页面,上面输入框,下面列表展示搜索到的结果。

重点是:产品要求搜索框默认显示一行,当输入的文字超过一行时,输入框的高度会随着改变,直到输入完毕。

解决思路设想

本想利用textarea实现,但textarea不支持自适应高度,而是定好高度或者是行数之后,超出部分就会显示滚动条。只能另想。

根据需求,首先想到了张鑫旭伪类匹配列表数目实现微信群头像CSS布局的技巧一文提到的文字多字号自动变小的技巧,但仔细一琢磨,不行。这个是根据内容元素的个数,进行处理,而这儿是输入框,没有内容元素。

后面想到可以利用html属性contenteditable="true",加在div上让其可编辑来模拟自适应高度。可是需要在vue中双向绑定实现,这个不是很好处理。

后面想到利用textarea的row属性,根据输入内容的长度控制row的值,为1-n行,但这个似乎不是很智能,因为多少个字体一行不一定,英文、中文、数字的宽度不一致,而且row属性在每个浏览器中的表现不一致。

最后利用textarea,监听change事件,让其高度=其滚动条高度,来达到高度自适应。

没想到最后还是利用了textarea。

实现

参考:textarea如何实现高度自适应?

util.js

  1. /**
  2. * 文本框根据输入内容自适应高度
  3. * @param {HTMLElement} 输入框元素
  4. * @param {Number} 设置光标与输入框保持的距离(默认0)
  5. * @param {Number} 设置最大高度(可选)
  6. * @callback {Function} 设置回调函数(可选)
  7. */
  8. export const autoTextarea = function (elem, extra, maxHeight, callback) {
  9. extra = extra || 0;
  10. var isFirefox = !!document.getBoxObjectFor || 'mozInnerScreenX' in window,
  11. isOpera = !!window.opera && !!window.opera.toString().indexOf('Opera'),
  12. addEvent = function (type, callback) {
  13. elem.addEventListener ?
  14. elem.addEventListener(type, callback, false) :
  15. elem.attachEvent('on' + type, callback);
  16. },
  17. getStyle = elem.currentStyle ? function (name) {
  18. var val = elem.currentStyle[name];
  19. if (name === 'height' && val.search(/px/i) !== 1) {
  20. var rect = elem.getBoundingClientRect();
  21. return rect.bottom - rect.top -
  22. parseFloat(getStyle('paddingTop')) -
  23. parseFloat(getStyle('paddingBottom')) + 'px';
  24. };
  25. return val;
  26. } : function (name) {
  27. return getComputedStyle(elem, null)[name];
  28. },
  29. minHeight = parseFloat(getStyle('height'));
  30. elem.style.resize = 'none';
  31. var change = function () {
  32. var scrollTop, height,
  33. padding = 0,
  34. style = elem.style;
  35. if (elem._length === elem.value.length) return;
  36. elem._length = elem.value.length;
  37. if (!isFirefox && !isOpera) {
  38. padding = parseInt(getStyle('paddingTop')) + parseInt(getStyle('paddingBottom'));
  39. };
  40. scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  41. elem.style.height = minHeight + 'px';
  42. if (elem.scrollHeight > minHeight) {
  43. if (maxHeight && elem.scrollHeight > maxHeight) {
  44. height = maxHeight - padding;
  45. style.overflowY = 'auto';
  46. } else {
  47. height = elem.scrollHeight - padding;
  48. style.overflowY = 'hidden';
  49. };
  50. style.height = height + extra + 'px';
  51. scrollTop += parseInt(style.height) - elem.currHeight;
  52. document.body.scrollTop = scrollTop;
  53. document.documentElement.scrollTop = scrollTop;
  54. elem.currHeight = parseInt(style.height);
  55. callback(parseInt(style.height));
  56. };
  57. };
  58. addEvent('propertychange', change);
  59. addEvent('input', change);
  60. addEvent('focus', change);
  61. change();
  62. };
  63. export const debounce = function (func, delay) {
  64. let timer;
  65. return function (...args) {
  66. if (timer) {
  67. clearTimeout(timer);
  68. }
  69. timer = setTimeout(() => {
  70. func.apply(this, args);
  71. }, delay || 500);
  72. }
  73. }

说明:由于下面是列表,需要计算高度,为了避免重新再去获取高度,所以加了个回调方法,把高度回调出去。

vue-search.vue

  1. <template>
  2. <div class="search-list">
  3. <div>
  4. <textarea ref="textarea" v-model="keywords" :maxlength="keywordsMax" @change="searchChange"></textarea>
  5. <span class="clear" @click="clearKeywords">x</span>
  6. </div>
  7. <div class="list" ref="list">
  8. <ul>
  9. <li v-for="item in list" :key="item.id">
  10. <span class="icon"></span>
  11. <dl>
  12. <dt>{{item.title}}</dt>
  13. <dd>{{item.desc}}</dd>
  14. </dl>
  15. </li>
  16. </ul>
  17. </div>
  18. </div>
  19. </template>
  20. <script>
  21. import { debounce, autoTextarea } from '@/util.js';
  22. let rootFontSize = parseFloat(document.documentElement.style.fontSize);
  23. export default {
  24. data () {
  25. return {
  26. keywordsMax: 128,
  27. keywords: '',
  28. list: []
  29. }
  30. },
  31. mounted () {
  32. this.$nextTick(() => {
  33. let textarea = this.$refs.textarea;
  34. textarea.focus();
  35. let prevHeight = 65;
  36. textarea && autoTextarea(textarea, 5, 0, (height) => {
  37. height += 20;
  38. if (height !== prevHeight) {
  39. prevHeight = height;
  40. let rem = height / rootFontSize;
  41. this.$refs.list.style.height = `calc(100% - ${rem}rem)`;
  42. }
  43. });
  44. })
  45. },
  46. methods: {
  47. clearKeywords () {
  48. this.keywords = '';
  49. this.list = [];
  50. let textarea = this.$refs.textarea;
  51. let height = 40;
  52. let rem = height / rootFontSize;
  53. textarea.style.height = `${rem}rem`;
  54. rem = (height + 20) / rootFontSize;
  55. this.$refs.list.style.height = `calc(100% - ${rem}rem)`;
  56. textarea.focus();
  57. },
  58. searchChange: debounce(function () {
  59. let trim = this.keywords.trim();
  60. if (!trim) {
  61. this.list = [];
  62. return;
  63. }
  64. const params = {
  65. keywords: this.keywords
  66. }
  67. // 调api ...
  68. })
  69. }
  70. }
  71. </script>

补充div模拟textarea自适应

  1. <style>
  2. .textarea{
  3. width: 400px;
  4. min-height: 20px;
  5. max-height: 300px;
  6. _height: 120px;
  7. margin-left: auto;
  8. margin-right: auto;
  9. padding: 3px;
  10. outline: 0;
  11. border: 1px solid #a0b3d6;
  12. font-size: 12px;
  13. line-height: 24px;
  14. padding: 2px;
  15. word-wrap: break-word;
  16. overflow-x: hidden;
  17. overflow-y: auto;
  18. border-color: rgba(82, 168, 236, 0.8);
  19. box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
  20. }
  21. </style>
  22. <div class="textarea" contenteditable="true"></div>

vue-textarea 自适应高度的更多相关文章

  1. textarea自适应高度,div模仿textarea可编辑实现自适应高度,placeholder使用图标

    1.textarea自适应高度,placeholder使用图标 自适应高度,有很多种办法: 1)jq: $("textarea").on("input",fun ...

  2. div模拟textarea自适应高度

    之前在公司做项目的时候,有这么一个需求,要我写一个评论框,可以随着评论的行数增加而自动扩大,最开始我想用textarea实现,但是后来尝试后发现textarea并不适合,textarea的高度不会随着 ...

  3. textarea自适应高度

    最近做项目遇见了这个自适应高度的问题,也在网上找了些资料,大多选择用DIV模拟textarea,但是这样就有安全性的问题,因为你是可以直接将HTML代码输入进去的. 接下来介绍的这种办法是采用两个te ...

  4. 简单实现一个textarea自适应高度

    textarea自适应的实现方法很多,原理其实比较简单:监听textarea的input或者键盘事件,获取元素的scrollHeight,重置textarea元素的高度. 预览地址:textarea ...

  5. js实现textarea自适应高度

    html结构: <div class="container" id="container"> <div class="text-wr ...

  6. jquery文本框textarea自适应高度

    浏览器中默认的文本框是不能根据内容的增多变高,只能固定高度有滚动条,体验不是很好,找了很多方法兼容都不行,总算找到个兼容良好的方法: <body> <textarea id=&quo ...

  7. Textarea自适应高度 JS实现,兼容IE6\7\8\9\10\11

    <!DOCTYPE html> <html> <head> <title>autoresizing textarea</title> < ...

  8. textarea 自适应高度

    试了好多方法,包括百度了好多.一旦接口获取的内容,就不好用了.有时候就是脑袋转不过来,想了好久的方法居然那么简单,然后,脑洞大开,忽然想到还可以这样弄, 很简单,两句话 var textareaHei ...

  9. 将textarea实现自适应高度及IE下滚动条不出现的bug

    1.<el-table-column label="备注" width="180"> <template scope="scope& ...

  10. div实现自适应高度的textarea,实现angular双向绑定

    相信不少同学模拟过腾讯的QQ做一个聊天应用,至少我是其中一个. 过程中我遇到的一个问题就是QQ输入框,自适应高度,最高高度为3row. 如果你也像我一样打算使用textarea,那么很抱歉,你一开始就 ...

随机推荐

  1. [原创]Zynq AXI-CDMA的使用

    Xilinx 提供了3种DMA AXI-DMA AXI-CDMA AXI-VDMA 使用CDMA能够满足项目需求(MM-MM),DS文档介绍如下: The Xilinx LogiCORE™ IP AX ...

  2. mysql8.0 定时创建分区表记录 每天定时创建下一天的分区表

    因单表数据太大, 需要表按时间分区 分区字段 pay_out_date 按天分 要求自动创建 1. 创建分区表 MYSQL的分区字段,必须包含在主键字段内 常见错误提示 错误提示:#1503 A PR ...

  3. js属性对象的propertyIsEnumerable方法

    定义 每个对象都有一个propertyIsEnumerable()方法.此方法返回一个布尔值,表明指定的属性是否是可枚举. This method can determine whether the ...

  4. oracle数据库学习

    trunc(number[,decimals])--number 待做截取处理的数值:decimals 指明需保留小数点后面的位数     CREATE PUBLIC DATABASE LINK Co ...

  5. 运营-赵本山最近有点烦:二人转产业链滑铁卢 关联公司IPO预披露

    http://news.cecb2b.com/info/20141117/2868962.shtml

  6. 浅析Kubernetes的工作原理

    先放一张Kubernetes的架构图: 整体来看,是一个老大,多个干活的这种结构,基本上所有的分布式系统都是这样,但是里面的组件名称就纷繁复杂,下面将一一解析. 1.元数据存储与集群维护 作为一个集群 ...

  7. input里面的submit鼠标按钮属性cursor

    属性cursor 属性值: pointer  小手 move  移动 help 帮助 wait 等待

  8. 随机生成UserAgent包之fake-useragent

    一.安装 pip install fake-usragent 二.使用 .导包 from fake-useragent import UserAgent .实例化 ua = UserAgent() . ...

  9. C++日志打印

    C++日志打印: %d              十进制有符号整数 %u              十进制无符号整数 %f              浮点数 %s              字符串 % ...

  10. sql基本语法

    sql基本语法 sql server 查询 多表查询 直接多表查询 select * from st_profiles,st_score_report 上面的语句将会产生两个表的笛卡尔乘积,其中大部分 ...