当前位置:   article > 正文

uniapp封装一个文章评论输入组件,可发表情、图片评论,Vue3+Ts语法!可随意拓展写法!_vue实现评论实现表情包

vue实现评论实现表情包

前言

最近在开发一款微信小程序,用的Vue3+Ts+uni-app,目前已完成基本的文章发布、文章列表、文章详情、个人中心、首页展示、文章评论点赞等功能,不定期分享开发中的一些东西,希望能帮助到大家!

需求

类似于头条、知乎交流社区类的软件文章页面,可对该进行评论、点赞收藏,可发布表情评论和图片评论。

效果图如下

实现思路

文章最底部固定静态评论框展示以及右侧点赞收藏按钮,静态的评论框点击打开评论输入框,输入框使用textarea,自动聚焦,聚焦式自动弹出键盘,并且键盘自动把输入框顶上去,避免遮挡输入框!

最开始我想用uni-app中的popup组件,但是在popou中嵌入textarea时无法自动聚焦,就很尴尬,索性自己写一个。背景固定一个mask蒙层,评论框固定在页面最底部,层级比蒙层高。表情包按钮和图片按钮放在底部,表情按钮触发时隐藏键盘,并弹出表情选择列表,点击蒙层以及发布评论成功时则关闭评论输入框。

大致是这么一个实现的思路。

代码实现:如下

组件:BottomComment.vue
  1. // 组件:底部固定静态评论显示框,赞藏方法不在这儿展示,根据自己需求修改
  2. <template>
  3. <view class="bottom-comment">
  4. <!-- 左边静态输入框 -->
  5. <view class="disableinput" @click.stop="emit('articleCommentInputFocus', 1)">
  6. 良言一句三冬暖,恶语伤人六月寒。
  7. </view>
  8. <!-- 文章总评论 -->
  9. <view class="bottom-item">
  10. <text class="item-icon icon-a-44tubiao-112"></text>
  11. <text class="item-text">{{ 20 }}</text>
  12. </view>
  13. <!-- 文章总点赞 -->
  14. <view class="bottom-item">
  15. <text class="item-icon"></text>
  16. <text class="item-text">{{ 30 }}</text>
  17. </view>
  18. <!-- 文章总收藏 -->
  19. <view class="bottom-item">
  20. <text class="item-icon"></text>
  21. <text class="item-text">{{ 10 }}</text>
  22. </view>
  23. </view>
  24. </template>
  25. <script setup lang="ts">
  26. const emit = defineEmits([
  27. 'articleCommentInputFocus'
  28. ])
  29. </script>
  30. <style lang="scss">
  31. .bottom-comment {
  32. position: fixed;
  33. left: 0;
  34. bottom: 0;
  35. z-index: 80;
  36. width: 100vw;
  37. min-height: 8vh;
  38. background-color: #fff;
  39. box-shadow: 0 0 8rpx 4rpx #f7f7f7;
  40. display: flex;
  41. align-items: center;
  42. justify-content: space-between;
  43. padding: 0 28rpx;
  44. .disableinput {
  45. width: 54%;
  46. height: 70rpx;
  47. background-color: #f6f6f6;
  48. border-radius: 35rpx;
  49. margin-right: 30rpx;
  50. font-size: 20rpx;
  51. color: #767676;
  52. padding-left: 16rpx;
  53. display: flex;
  54. align-items: center;
  55. }
  56. .bottom-item {
  57. flex: 1;
  58. display: flex;
  59. margin-right: 10rpx;
  60. align-items: center;
  61. .item-icon {
  62. font-size: 38rpx;
  63. padding-right: 10rpx;
  64. }
  65. .isUp {
  66. color: $uni-color-primary;
  67. }
  68. .item-text {
  69. font-size: 30rpx;
  70. }
  71. }
  72. }
  73. </style>
组件:TextareaComment
  1. <template>
  2. <!-- 蒙层 -->
  3. <view clas="c-mask" v-if="showInputPop" class="c-mask" @click.stop="emit('closeInputPop')"
  4. @touchmove.stop.prevent="emit('disableScroll')">
  5. </view>
  6. <view class="popup-comment" v-if="showInputPop">
  7. <view class="comment-input-wrap">
  8. <view class="comment-textarea-box" @touchmove.stop.prevent="emit('disableScroll')">
  9. <textarea v-model="commentParams.content" class="comment-textarea" :maxlength="600" :focus="replyFocus"
  10. :placeholder="customPlaceholder" :show-confirm-bar="false" @focus="commentInputFocus" @blur="commentInputBlur"
  11. :adjust-position="true" :cursor-spacing="400" :cursor="cursorIndex" @input="inputFocusChange" :fixed="true" />
  12. <view class="limit">{{ commentParams.content?.length || 0 }} / 600</view>
  13. </view>
  14. <view class="image-list">
  15. <view class="image-item" v-for="(item, index) in commentImages" :key="index">
  16. <image class="image" :src="item" mode="aspectFill" @click.stop="previewCommentImage(item)"></image>
  17. <uni-icons class="icon-close" @click.stop="deleteOneCommentImage(index)" type="clear" size="20"
  18. color="#red"></uni-icons>
  19. </view>
  20. </view>
  21. <view class="relase-btn">
  22. <!-- 表情 和 图片 -->
  23. <view class="emoji-image">
  24. <!-- 选择上传图片 -->
  25. <view class="as-image icon-a-44tubiao-81" hover-class="checkActive" :hover-stay-time="100"
  26. @click="selectMediaImage"></view>
  27. <!-- 表情 -->
  28. <view class="emoji icon-biaoqing-xue" hover-class="checkActive" :hover-stay-time="100" @click="openEmoji"
  29. v-if="!showEmoji"></view>
  30. <!-- 键盘 -->
  31. <view v-else class="keyboard icon-a-44tubiao-155" hover-class="checkActive" :hover-stay-time="100"
  32. @click="openKeyboard">
  33. </view>
  34. </view>
  35. <!-- 发布 -->
  36. <view class="relase" @click.stop="commentCommit" hover-class="button-hover" :hover-stay-time="100">发布</view>
  37. </view>
  38. <list class="emoji-data" :show-scrollbar="false" v-if="showEmoji">
  39. <view v-for="(item, index) in emojiDataList" :key="index" class="emoji-item" hover-class="checkActive"
  40. :hover-stay-time="100" @click.stop="tuchCurrentEmoji(item)">
  41. <text class="emoj_conn">{{ item }}</text>
  42. </view>
  43. </list>
  44. </view>
  45. </view>
  46. </template>
  47. <script setup lang="ts">
  48. import { ref, nextTick } from 'vue'
  49. import { uploadImages } from '@/utils/public'
  50. const props = defineProps({
  51. showInputPop: {
  52. type: Boolean,
  53. default: false,
  54. },
  55. })
  56. const emit = defineEmits([
  57. 'closeInputPop',
  58. 'disableScroll',
  59. 'update:showInputPop',
  60. ])
  61. // 新增评论入参
  62. const commentParams = ref({ content: '' } as any)
  63. // 评论上传的图片
  64. const commentImages = ref<string[]>([])
  65. // 点击回复控制textarea的聚焦
  66. const replyFocus = ref(false)
  67. // 默认的提示内容
  68. const customPlaceholder = ref<string>('输入评论')
  69. // 是否显示表情包
  70. const showEmoji = ref(false)
  71. // 表情包列表
  72. const emojiDataList = ref([
  73. '
    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/683533
    推荐阅读
    相关标签