先看一下效果
微信聊天输入框的特点
- 随着文字输入的增加,输入框的行数增加
- 输入框最大5行
- 超过5行则开始滚动
实现方式
使用textarea标签,通过设置rows属性来更改输入行数
难点分析
- 如何检测文字到达边界,改变textarea的rows属性
如何解决
使用相同宽度的textarea,将该textarea设置为不可见,rows属性为1,readonly。
通过textarea的clientHeight和ScrollHeight来判断行数。
其它注意点
- 去除文字首尾的空白字符
- 去除空白字符后无其它字符,则不允许发送
代码实现
// InputArea.js
import React, { useState, useMemo, useRef, useEffect } from 'react'
import './InputArea.scss'
export default function InputArea(props) {
const [content, setContent] = useState('')
// 默认textarea的最高行数
const [defaultMaxRows] = useState(5)
const [rows, setRows] = useState(1)
const hiddenTextarea = useRef(null)
const maxRows = useMemo(() => props.maxRows || defaultMaxRows, [props.maxRows])
useEffect(() => {
return () => {
let r = hiddenTextarea.current.scrollHeight / hiddenTextarea.current.clientHeight
if (r > maxRows) r = maxRows
setRows(r)
}
}, [maxRows, content])
// 用户输入内容是否可以发送
// 去除输入内容的收尾两端空格
const disable = useMemo(() => content.replace(/(^\s+)|(\s+$)/g, '') === '', [content])
// 发送消息
function sendMessage() {
// 调用接口发送消息
props.sendMessage && props.sendMessage()
// 发送成功后
setContent('')
}
function onChange(e) {
// console.log('onchange', e.target.value)
setContent(e.target.value)
}
function onBlur(e) {
// 键盘收起
setTimeout(() => {
// safari on ios9 一下不支持window.scrollTo 好在这个兼容性问题出现在ios12的微信里
window.scrollTo && window.scrollTo(0, 99999999)
}, 100)
}
function onFocus(e) {
// 键盘弹出
setTimeout(() => {
// safari on ios9 一下不支持window.scrollTo 好在这个兼容性问题出现在ios12的微信里
window.scrollTo && window.scrollTo(0, 99999999)
}, 100)
}
return (
<div className="m-input-area__wrapper">
<div className="m-input-area__content">
<textarea
spellCheck={false}
placeholder="输入聊天内容..."
rows={rows}
value={content}
onChange={onChange}
onBlur={onBlur}
onFocus={onFocus}
/>
{/* 不可见的输入框 */}
<textarea readOnly rows={1} value={content} ref={hiddenTextarea} />
</div>
<input
className={`m-input-area__btn ${disable ? 'disable' : ''}`}
type="button"
value="发送"
disabled={disable}
onClick={sendMessage}
/>
</div>
)
}
.m-input-area__wrapper {
display: flex;
justify-content: space-between;
background: #F6F6F6;
padding: 3px 6px 4px 6px;
// border-top: solid 1px #f1f1f1;
box-shadow: 0 -1px 4px #ddd;
}
.m-input-area__content {
flex-grow: 1;
position: relative;
// height: fit-content;
border-radius: 2px;
margin-right: 6px;
padding: 4px 6px;
background: #fff;
// font-size: 0; // 解决textarea后面会添加空白字符 导致的高度无端撑开3px 其它解决方式看笔记
textarea {
display: block; // 解决textarea后面会添加空白字符 导致的高度无端撑开3px 其它解决方式看笔记
font-size: 14px;
padding: 0;
border: 0;
line-height: 22px;
color: #71777c;
resize: none; // 不允许调整元素大小
width: 100%;
outline: none;
&::placeholder {
color: #CECECE;
}
&:nth-child(2) {
visibility: hidden;
position: absolute;
left: 0;
top: 0;
padding: 0 6px;
box-sizing: border-box;
}
}
}
.m-input-area__btn {
width: 60px;
height: 30px;
font-size: 14px;
// text-align: center;
color: #fff;
background: #007fff;
// border: solid 1px #007fff;
border: none;
border-radius: 2px;
font-weight: 600;
cursor: pointer;
letter-spacing: 4px;
text-indent: 4px;
&.disable {
// border-color: #CECECE;
background: #cecece;
color: #fff;
}
}