样式大致模仿的网页版抖音的评论输入框

表情包的引用可以看gitee地址:vue 表情输入组件

效果图:

在这里插入图片描述

废话不多说,直接上代码

src/components/emotion.vue

<template>
  <div class="ly-emotion" >
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'emotion',
  mounted () {
    const name = this.$el.innerHTML
    const list = ['微笑', '撇嘴', '色', '发呆', '得意', '流泪', '害羞', '闭嘴', '睡', '大哭', '尴尬', '发怒', '调皮', '呲牙', '惊讶', '难过', '酷', '冷汗', '抓狂', '吐', '偷笑', '可爱', '白眼', '傲慢', '饥饿', '困', '惊恐', '流汗', '憨笑', '大兵', '奋斗', '咒骂', '疑问', '嘘', '晕', '折磨', '衰', '骷髅', '敲打', '再见', '擦汗', '抠鼻', '鼓掌', '糗大了', '坏笑', '左哼哼', '右哼哼', '哈欠', '鄙视', '委屈', '快哭了', '阴险', '亲亲', '吓', '可怜', '菜刀', '西瓜', '啤酒', '篮球', '乒乓', '咖啡', '饭', '猪头', '玫瑰', '凋谢', '示爱', '爱心', '心碎', '蛋糕', '闪电', '炸弹', '刀', '足球', '瓢虫', '便便', '月亮', '太阳', '礼物', '拥抱', '强', '弱', '握手', '胜利', '抱拳', '勾引', '拳头', '差劲', '爱你', 'NO', 'OK', '爱情', '飞吻', '跳跳', '发抖', '怄火', '转圈', '磕头', '回头', '跳绳', '挥手', '激动', '街舞', '献吻', '左太极', '右太极']
    let index = list.indexOf(name)
    let imgHTML = `<img src="https://res.wx.qq.com/mpres/htmledition/images/icon/emotion/${index}.gif">`
    this.$nextTick(() => {
      this.$el.innerHTML = imgHTML
    })
  },
}
</script>
<style scoped>
.ly-emotion {
  display: inline-block
}
.ly-static-emotion {
  width: 24px;
  height: 24px;
  display: inline-block;
}
</style>

src/components/index.vue

<template>
  <div>
    <div class="emotion-box" :style="{height: height + 'px' }" >
      <div class="emotion-box-line" v-for="(line, i) in list" :key="i" >
        <Emotion class="emotion-item" v-for="(item, i) in line" :key="i" @click.native="clickHandler(item)" >{{item}}</Emotion>
      </div>
    </div>
  </div>
</template>

<script>
import { reactive, toRefs } from '@vue/reactivity'
import Emotion from './emotion'
export default {
  props: ['height'],
  components: {
    Emotion
  },

  setup(props,content){
    let data = reactive({
      list: [
        ['微笑', '撇嘴', '色', '发呆', '得意', '流泪', '害羞', '闭嘴'],
        ['睡', '大哭', '尴尬', '发怒', '调皮', '呲牙', '惊讶', '难过']
        ['酷', '冷汗', '抓狂', '吐', '偷笑', '可爱', '白眼', '傲慢'],
        ['饥饿', '困', '惊恐', '流汗', '憨笑', '大兵', '奋斗', '咒骂'],
        ['疑问', '嘘', '晕', '折磨', '衰', '骷髅', '敲打', '再见'],
        ['擦汗', '抠鼻', '鼓掌', '糗大了', '坏笑', '左哼哼', '右哼哼', '哈欠'],
        ['鄙视', '委屈', '快哭了', '阴险', '亲亲', '吓', '可怜', '菜刀'],
        ['西瓜', '啤酒', '篮球', '乒乓', '咖啡', '饭', '猪头', '玫瑰',],
        ['凋谢', '示爱', '爱心', '心碎', '蛋糕', '闪电', '炸弹', '刀'],
        ['足球', '瓢虫', '便便', '月亮', '太阳', '礼物', '拥抱', '强'],
        ['弱', '握手', '胜利', '抱拳', '勾引', '拳头', '差劲', '爱你'],
        ['NO', 'OK', '爱情', '飞吻', '跳跳', '发抖', '怄火', '转圈'],
        ['磕头', '回头', '跳绳', '挥手', '激动', '街舞', '左太极', '右太极'],
      ],
      height:props.height || 200
    })


    const clickHandler = (i)=>{
      let emotion = `#${i};`
      content.emit('emotion', emotion)
    }

    return {
      ...toRefs(data),
      clickHandler
    }
  }
}
</script>
<style scoped>
  .emotion-box {
    margin: 0 auto;
    width: 100%;
    box-sizing: border-box;
    padding: 5px;
    overflow: hidden;
    overflow-y: auto;
  }
  .emotion-box::-webkit-scrollbar{
    width: 5px;
    height: 3px !important;
    background-color: #F5F5F5;
  }
  
  /*定义滑块 内阴影+圆角*/
  .emotion-box::-webkit-scrollbar-thumb
  {
    background-color: rgba(0,0,0,.15);
  }
  .emotion-box-line {
    display: flex;
  }
  .emotion-item {
    flex: 1;
    text-align: center;
    cursor: pointer;
    margin: 5px;
  }
</style>

src/components/MyInput.vue

<template>
    <div>
        <div class="_video-comment-input" >
            <input type="text" placeholder="留下你的精彩评论吧!" v-model="content" @keyup.enter="handlePublish" @focus="isShowEmotion = false">
            <img src="@/assets/emotion.png" alt="表情" @click="isShowEmotion = !isShowEmotion">
            <img src="@/assets/publish.png" alt="发布" @click="handlePublish">
        </div>
        <emotion v-show="isShowEmotion" class="emotion" @emotion="(i) => content+=i" :height="200" ></emotion>
    </div>
</template>

<script>
import { reactive, toRefs } from '@vue/reactivity';
import Emotion from '@/components/index.vue'



export default {
    name: 'Input',
    components:{
        Emotion
    },
    setup(props,content){


        let data = reactive({
            content:'',
            isShowEmotion:false
        })
        const  handlePublish = () => {
            content.emit('ok',data.content)
            data.content = ''
            data.isShowEmotion = false
        }
        return {
            ...toRefs(data),
            handlePublish
        }
    }
};
</script>

<style lang="scss" scoped>
@mixin flx($jc,$ai,$fd:row){
      display: flex;
      flex-direction: $fd;
      justify-content: $jc;
      align-items: $ai;
  }
    div{
        width: 100%;
        position: relative;
        ._video-comment-input{
            width: 100%;
            height: 45px;
            border-radius: 10px;
            // line-height: 55px;
            box-shadow: 0 0 8px rgba($color: #000000, $alpha: .2);
            background: var(--searchbgcolor);
            overflow: hidden;
            padding: 0 5px;
            @include flx(space-evenly,center);
            >input{
                outline: none;
                border: 0;
                width:88%;
                font-size: 16px;
                background: inherit;
                color: var(--maincolor);
                margin-left: 13px;
            }
            >img{
                width: 25px;
                height: 25px;
                margin: auto;
                cursor: pointer;
            }
        }
        >.emotion{
            position: absolute;
            top: 48px;
            right: -10px;
            width: 400px;
            border-radius: 6px;
            overflow: hidden;
            box-shadow: 0px 0px 24px rgba(0,0,0,.2);
        }
    }
</style>

在需要使用表情输入框的地方引入 MyInput.vue 文件

<template>
    <div class="inp"> <MyInput @ok="handlePublish"/> </div>
    <div class="content" v-html="data.content.replace(/\#[\u4E00-\u9FA5]{1,3}\;/gi, emotion)"> </div>
</template>

<script>
import { reactive } from '@vue/reactivity';

import MyInput from './components/MyInput.vue'
export default {
  name: 'App',
  components:{
    MyInput
  },

  setup() {
    let data = reactive({
      content:''
    })

    let handlePublish = (e)=> data.content = e

    // 将匹配结果替换表情图片
    function  emotion (res) {
          let word = res.replace(/\#|\;/gi,'')
          const list = ['微笑', '撇嘴', '色', '发呆', '得意', '流泪', '害羞', '闭嘴', '睡', '大哭', '尴尬', '发怒', '调皮', '呲牙', '惊讶', '难过', '酷', '冷汗', '抓狂', '吐', '偷笑', '可爱', '白眼', '傲慢', '饥饿', '困', '惊恐', '流汗', '憨笑', '大兵', '奋斗', '咒骂', '疑问', '嘘', '晕', '折磨', '衰', '骷髅', '敲打', '再见', '擦汗', '抠鼻', '鼓掌', '糗大了', '坏笑', '左哼哼', '右哼哼', '哈欠', '鄙视', '委屈', '快哭了', '阴险', '亲亲', '吓', '可怜', '菜刀', '西瓜', '啤酒', '篮球', '乒乓', '咖啡', '饭', '猪头', '玫瑰', '凋谢', '示爱', '爱心', '心碎', '蛋糕', '闪电', '炸弹', '刀', '足球', '瓢虫', '便便', '月亮', '太阳', '礼物', '拥抱', '强', '弱', '握手', '胜利', '抱拳', '勾引', '拳头', '差劲', '爱你', 'NO', 'OK', '爱情', '飞吻', '跳跳', '发抖', '怄火', '转圈', '磕头', '回头', '跳绳', '挥手', '激动', '街舞', '献吻', '左太极', '右太极']
          let index = list.indexOf(word)
          return `<img src="https://res.wx.qq.com/mpres/htmledition/images/icon/emotion/${index}.gif" style="vertical-align: sub;" align="middle">`   
      }

    return {
      data,
      handlePublish,
      emotion
    };
  },


};
</script>

<style lang="scss" scoped>
  .inp{
    width: 800px;
    margin: 100px auto 0;
  }
  .content{
    width: 800px;
    margin: 50px auto;
  }
</style>

两个所用的图标资源:
在这里插入图片描述
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐