# 评论页
# 技术点
自定义输入框
contenteditable
操作光标位置
resize事件监听
# 目录结构
└─ src
└─ views
└─ comment # 评论页
├─ components # 评论组件
│ ├─ CommentBar.vue # 评论底部 bar
│ ├─ CommentEditor.vue # 评论输入框
│ ├─ CommentItem.vue # 评论内容
│ ├─ CommentSkeleton.vue # 评论加载骨架
│ └─ CommentTool.vue # 评论举报等操作 action-sheet
└─ index.vue # 评论入口页
# 功能介绍
因为多种资源存在评论功能,如文章、影评、视频等,所以将该页面单独抽离出来作为一个公共页面。
注意,该评论页面为弹窗的子页面,以实现用户返回操作时,只关闭评论的弹窗。
comment-bar
组件中,输入框为 div
元素,不是真实输入框。用户点击后,路由插入 hash
值 #edit
,以使用户点击返回按钮时只关闭评论框。
在 comment-editor
组件中,使用 div
的 contenteditable
属性模拟输入框,为何未使用 input
或者 textarea
呢? input
只能一行,textarea
编辑时光标位置无法移动到最后,不支持表情等。
# 主要代码
CommentEditor
组件
<!-- 评论输入框 -->
<div
@input="inputChange"
contenteditable
ref="input"
class="comment-edit"
:style="style"
autosize
placeholder="爱笑的人运气不会太差~"
></div>
mounted() {
// 注册页面 `resize` 事件,当软键盘收起时,则关闭输入框页面
const _this = this;
let originalHeight = document.documentElement.clientHeight || document.body.clientHeight;
window.onresize = function () {
//键盘弹起与隐藏都会引起窗口的高度发生变化
let resizeHeight =
document.documentElement.clientHeight || document.body.clientHeight;
if (resizeHeight - 0 < originalHeight - 0) {
//软键盘弹起
} else {
//软键盘收起
_this.$router.back();
}
};
// 如果输入框有内容时关闭输入框,再次打开时,还原之前输入内容
// 还原后光标会在最前方,需要移动至最后
this.$nextTick(() => {
this.$refs.input.focus();
let range = window.getSelection();
range.selectAllChildren(this.$refs.input);
range.collapseToEnd(); //光标移至最后
setTimeout(() => {
this.inputFocus();
}, 300);
});
},
methods: {
// 该方法是为了计算去掉软键盘与边距等高度后,可输入内容区域剩余高度
inputFocus() {
const height = window.innerHeight - 112;
this.style = `max-height: ${height}px`;
}
}