Skip to content
On this page

匕蚀 ​

圚数字时代聊倩已经成䞺我们生掻的䞀郚分而Emoji衚情则是我们衚蟟情感和情绪的重芁方匏之䞀。所以䞺什么䞍把这些可爱的小囟标融入䜠的聊倩宀、项目䞭呢😍🀩

线䞊䜓验 ​

聊倩宀搭建参考即时通讯蜻束实现WebSocket、Vue 3 和 Node.js 猔造的倚人实时亀流平台

䜓验地址✍xioayi
效果劂䞋 emoji.gif

敎䜓实现思路 ​

  • 物料的获取(emoji)
  • 封装䞀䞪emoji组件(最近䜿甚、衚情分类)
  • 细节倄理(劂光标倄插入选择后插入等)
  • 圚聊倩宀具䜓䜿甚(选择衚情、插入蟓入框、页面展瀺)

物料获取 ​

䞋面这䞀䞪眑站郜是可以免莹获取的copy喜欢的衚情 yyds 😀,😄,😁,😆,😅,🀣,😂

  1. 笊号倧党
  2. emojiall

封装䞀䞪emoji组件 ​

倄理emoji衚情 ​

  • 这里需芁封装䞀䞪蟅助凜数来垮我们蜬成数组进行存傚
typescript
/**
 * 
 * @param inputs 参数䞀䞪或倚䞪字笊䞲
 * @returns 返回二绎数组
 */
function splitEmoji(...inputs: string[]): string[][] {
  const emojiRegex: RegExp = /\p{Emoji}/u;
  const emojiArrays: string[][] = [];

  inputs.forEach((input) => {
    const emojiArray: string[] = [];
    for (const char of input) {
      if (emojiRegex.test(char)) {
        emojiArray.push(char);
      }
    }
    emojiArrays.push(emojiArray);
  });

  return emojiArrays;
}

封装emoji组件 ​

  1. 拿到倄理奜的emoji数据**{type:xxx,value:['🍉','🍊','🍋','🍌']}**
  2. 根据props.all 刀断芁展瀺的类别并进行枲染
  3. 倄理亀互点击某䞀衚情就把它䌠给父组件并计入最近䜿甚列衚
vue
<template>
  <div class="emoji">
    <div v-if="emoji.historyList?.length">
      <p>最近䜿甚</p>
      <ul class="history" :class="emoji.historyList?.length ? 'historyShow' : ''">
        <li v-for="(item, index) in [...new Set(emoji.historyList)]" :key="index" @click.stop="chooseEmojiDefault(item)"
          v-html="item"></li>
      </ul>
    </div>
    <div v-for="items in emojiObj" :key="items.name">
      <template v-if="items.name && items.value?.length">
        <p>{{ items.name }}</p>
        <ul class="default">
          <li v-for="(item, index) in items.value" :key="index" @click.stop="chooseEmojiDefault(item)" v-html="item"></li>
        </ul>
      </template>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive } from "vue";
import { getAllTypeEmojis } from './utils'

const emit = defineEmits(["emojiHandle"]);
const props = defineProps({
  all: {
    type: Boolean,
    default: false
  }
})

const res = getAllTypeEmojis()
const emojiObj = ref({})

if (props.all) {
  emojiObj.value = res
} else {
  emojiObj.value = {
    defEmojis: res.defEmojis
  }
}
const emoji = reactive({
  chooseItem: "",
  historyList: [],
  allEmoji: emojiObj.value,
});
const chooseEmojiDefault = (item: string) => {
  emoji.chooseItem = item;
  emoji.historyList.unshift(item);
  emit("emojiHandle", item);
  return item;
};
</script>

<style lang="less" scoped>
</style>

聊倩宀䞭䜿甚衚情 ​

这里有䞀䞪关键点插入䜍眮记圕、插入字笊䞲拌接

  • 插入䜍眮即光标所䜍眮
  • 字笊䞲拌接截取光标前字笊+衚情+光标后字笊

input䞭光标䜍眮的获取 ​

  • dom有䞀䞪属性selectionEnd和selectionStart 分别代衚光标起始䜍眮
  • 记圕光标结束䜍眮等䞋选择了奜插入 光标展瀺䜍眮.gif
javascript
/**
 * 获取光标的起始䜍眮
 */
const selectEmoji = () => {
  const Textarea = document.querySelector(".message-input");
  console.log(Textarea?.selectionStart,Textarea?.selectionEnd)
};

选择衚情倄理 ​

  1. 拿到选择衚情
  2. 插入并拌接字笊䞲 截取光标前字笊+衚情+光标后字笊 衚情插入.gif
javascript
/**
 * 选择衚情并把衚情插入蟓入框
 * @param {*} item 选择的衚情
 */
const emojiHandle = (item) => {
  const msg = message.value;
  if (!cursor.value) {
    message.value += item;
  } else {
    message.value = msg.slice(0, cursor.value) + item + msg.slice(cursor.value);
  }
};

完敎代码 ​

仓库地址xiaoyi1255image.png

  • emoji组件䞀共䞉䞪文件 utils.ts、emojis.js、index.vue
  • test.vue 䜿甚瀺䟋
  1. utils.ts
typescript
import {
  defEmojis,
  allEmojis,
  expressionEmojis,
  animalEmojis,
  personEmojis,
  guestrueEmojis,
  publicEmojis,
  twelveEmojis,
} from './emojis'

/**
 * 
 * @param inputs 参数䞀䞪或倚䞪字笊䞲
 * @returns 返回二绎数组
 */
function splitEmoji(...inputs: string[]): string[][] {
  const emojiRegex: RegExp = /\p{Emoji}/u;
  const emojiArrays: string[][] = [];

  inputs.forEach((input) => {
    const emojiArray: string[] = [];
    for (const char of input) {
      if (emojiRegex.test(char)) {
        emojiArray.push(char);
      }
    }
    emojiArrays.push(emojiArray);
  });

  return [...new Set(emojiArrays)];
}

/**
 * 
 * @returns 衚情对象 allEmojis,expressionEmojis,animalEmojis,personEmojis,guestrueEmojis,publicEmojis,twelveEmojis
 */
const getAllTypeEmojis = () => {
  const emojiArr = splitEmoji(allEmojis,expressionEmojis,animalEmojis,personEmojis,guestrueEmojis,publicEmojis,twelveEmojis,defEmojis)
  
  const emojiObj = {
    defEmojis: {name:"默讀衚情", value:emojiArr[7]},
    guestrueEmojis: {name:"手势衚情", value:emojiArr[4]},
    publicEmojis: {name:"公共衚情", value:emojiArr[5]},
    expressionEmojis: {name:"脞郚衚情", value:emojiArr[1]},
    animalEmojis: {name:"劚物衚情", value:emojiArr[2]},
    personEmojis: {name:"人物衚情", value:emojiArr[3]},
    twelveEmojis: {name: "12生肖", value: emojiArr[6]},
    allEmojis: {name:"所有衚情", value:emojiArr[0]},
  }
  return emojiObj

}
const emojiMap = {
  defEmojis: '默讀衚情',
  allEmojis: '所有衚情',
  expressionEmojis: '脞郚衚情',
  animalEmojis: '劚物衚情',
  personEmojis: "人物衚情",
  guestrueEmojis: '手势衚情',
  publicEmojis: '公共衚情',
  twelveEmojis: '12生肖',
}
export {
  getAllTypeEmojis,
  emojiMap
}
  1. emojis.js
javascript
/**
 * 这里存攟所以Emoji物料
 */
// 默讀
const defEmojis = "😀,😄,😁,😆,😅,🀣,😂,🙂,🙃,😉,😊,😇,😕,😟,🙁,☹,😮,😯,😲,😳,🥺,😊,😧,😚,😰,😥,😢,😭,😱,😖,😣,😞,😓,😩,😫,🥱,😀,😡,😠,🀬,😈,👿,💀,☠,💩,🀡,👹,👺,👻,👜,👟,🀖,😺,😞,😹,😻,😌,😜,🙀,😿,😟,🙈,🙉,🙊,💌,💘,💝,💖,💗,💓,💞,💕,💟,❣,💔,❀‍🔥,❀‍🩹,❀,🧡,💚,💊,💫,💋,💯,❀‍🩹,❀‍🔥,🥵,🀧,🀮,🀢,🀕,🀒,😷,😎,🀀,🀯,🀠,🥳,🥞,😎,🀓,🧐,😒,😏,🀭,😘,🀩,😍,🥰,👁‍🗚,💀,💭,🗯,🗚,👁‍🗚,☺,😚,😙,🥲,😋,😛,😜,🀪,😝,🧎‍♀,🧎‍➡,👚🏿‍🊌‍➡,💃🏻,🏇🏻,🀞🏌‍♀,🏋🏟‍♂,🚵🏜‍♂,🛌🏟,🀟,🙎🏌‍♂,🊍,🐎,🐗,🐎,🐺,🐻,🊇,🊃,🐢,🊎,🐍,🐉,🊂,🍉,🍚".replaceAll(',', '')

// 党郚
const allEmojis = "🍇🍈🍉🍊🍋🍌🍍🥭🍎🍏🍐🍑🍒🍓🫐🥝🍅🫒🥥🥑🍆🥔🥕🌜🌶🫑🥒🥬🥊🧄🧅🍄🥜🌰🍞🥐🥖🫓🥚🥯🥞🧇🧀🍖🍗🥩🥓🍔🍟🍕🌭🥪🌮🌯🫔🥙🧆🥚🍳🥘🍲🫕🥣🥗🍿🧈🧂🥫🍱🍘🍙🍚🍛🍜🍝🍠🍢🍣🍀🍥🥮🍡🥟🥠🥡🊪🍊🍧🍚🍩🍪🎂🍰🧁🥧🍫🍬🍭🍮🍯🍌🥛☕🫖🍵🍶🍟🍷🍞🍹🍺🍻🥂🥃🥀🧋🧃🧉🧊🥢🍜🍎🥄🚣🗟🏔⛰🌋🗻🏕🏖🏜🏝🏞🏟🏛🏗🛖🏘🏚🏠🏡🏢🏣🏀🏥🏊🏚🏩🏪🏫🏬🏭🏯🏰💒🗌🗜⛪🕌🛕🕍⛩🕋⛲⛺🌁🌃🏙🌄🌅🌆🌇🌉🎠🎡🎢🚂🚃🚄🚅🚆🚇🚈🚉🚊🚝🚞🚋🚌🚍🚎🚐🚑🚒🚓🚔🚕🚖🚗🚘🚙🛻🚚🚛🚜🏎🏍🛵🛺🚲🛎🚏🛣🛀⛜🚚🚥🚊🚧⚓⛵🚀🛳⛎🛥🚢✈🛩🛫🛬🪂💺🚁🚟🚠🚡🛰🚀🛞🪐🌠🌌⛱🎆🎇🎑💎💵💶💷🗿🛂🛃🛄🛅🙈🙉🙊💥💫💊💚🐵🐒🊍🊧🐶🐕🊮🐕‍🊺🐩🐺🊊🊝🐱🐈🐈‍⬛🊁🐯🐅🐆🐎🐎🊄🊓🊌🊬🐮🐂🐃🐄🐷🐖🐗🐜🐏🐑🐐🐪🐫🊙🊒🐘🊣🊏🊛🐭🐁🐀🐹🐰🐇🐿🊫🊔🊇🐻🐻‍❄🐚🐌🊥🊊🊚🊘🊡🐟🊃🐔🐓🐣🐀🐥🐊🐧🕊🊅🊆🊢🊉🊀🪶🊩🊚🊜🐞🐊🐢🊎🐍🐲🐉🊕🊖🐳🐋🐬🊭🐟🐠🐡🊈🐙🐚🐌🊋🐛🐜🐝🪲🐞🊗🪳🕷🕞🊂🊟🪰🪱🊠💐🌞💮🏵🌹🥀🌺🌻🌌🌷🌱🪎🌲🌳🌎🌵🌟🌿☘🍀🍁🍂🍃🍄🌰🊀🊞🊐🊑🌍🌎🌏🌐🪚🌑🌒🌓🌔🌕🌖🌗🌘🌙🌚🌛🌜☀🌝🌞⭐🌟🌠☁⛅⛈🌀🌥🌊🌧🌚🌩🌪🌫🌬🌈☂☔⚡❄☃⛄☄🔥💧🌊🎄✚🎋🎍😀😃😄😁😆😅🀣😂🙂🙃😉😊😇🥰😍🀩😘😗☺😚😙🥲😋😛😜🀪😝🀑🀗🀭🀫🀔🀐🀚😐😑😶😏😒🙄😬🀥😌😔😪🀀😎😷🀒🀕🀢🀮🀧🥵🥶🥎😵🀯🀠🥳🥞😎🀓🧐😕😟🙁☹😮😯😲😳🥺😊😧😚😰😥😢😭😱😖😣😞😓😩😫🥱😀😡😠🀬😈👿💀☠💩🀡👹👺👻👜👟🀖😺😞😹😻😌😜🙀😿😟💋👋🀚🖐✋🖖👌🀌🀏✌🀞🀟🀘🀙👈👉👆🖕👇☝👍👎✊👊🀛🀜👏🙌👐🀲🀝🙏✍💅🀳💪🊟🊿🊵🊶👂🊻👃🧠🫀🫁🊷🊎👀👁👅👄👶🧒👊👧🧑👱👚🧔👚‍🊰👚‍🊱👚‍🊳👚‍🊲👩👩‍🊰🧑‍🊰👩‍🊱🧑‍🊱👩‍🊳🧑‍🊳👩‍🊲🧑‍🊲👱‍♀👱‍♂🧓👎👵🙍🙍‍♂🙍‍♀🙎🙎‍♂🙎‍♀🙅🙅‍♂🙅‍♀🙆🙆‍♂🙆‍♀💁💁‍♂💁‍♀🙋🙋‍♂🙋‍♀🧏🧏‍♂🧏‍♀🙇🙇‍♂🙇‍♀🀊🀊‍♂🀊‍♀🀷🀷‍♂🀷‍♀🧑‍⚕👚‍⚕👩‍⚕🧑‍🎓👚‍🎓👩‍🎓🧑‍🏫👚‍🏫👩‍🏫🧑‍⚖👚‍⚖👩‍⚖🧑‍🌟👚‍🌟👩‍🌟🧑‍🍳👚‍🍳👩‍🍳🧑‍🔧👚‍🔧👩‍🔧🧑‍🏭👚‍🏭👩‍🏭🧑‍💌👚‍💌👩‍💌🧑‍🔬👚‍🔬👩‍🔬🧑‍💻👚‍💻👩‍💻🧑‍🎀👚‍🎀👩‍🎀🧑‍🎚👚‍🎚👩‍🎚🧑‍✈👚‍✈👩‍✈🧑‍🚀👚‍🚀👩‍🚀🧑‍🚒👚‍🚒👩‍🚒👮👮‍♂👮‍♀🕵🕵‍♂🕵‍♀💂💂‍♂💂‍♀🥷👷👷‍♂👷‍♀🀎👞👳👳‍♂👳‍♀👲🧕🀵🀵‍♂🀵‍♀👰👰‍♂👰‍♀🀰🀱👩‍🍌👚‍🍌🧑‍🍌👌🎅🀶🧑‍🎄🊞🊞‍♂🊞‍♀🊹🊹‍♂🊹‍♀🧙🧙‍♂🧙‍♀🧚🧚‍♂🧚‍♀🧛🧛‍♂🧛‍♀🧜🧜‍♂🧜‍♀🧝🧝‍♂🧝‍♀🧞🧞‍♂🧞‍♀🧟🧟‍♂🧟‍♀💆💆‍♂💆‍♀💇💇‍♂💇‍♀🚶🚶‍♂🚶‍♀🧍🧍‍♂🧍‍♀🧎🧎‍♂🧎‍♀🧑‍🊯👚‍🊯👩‍🊯🧑‍🊌👚‍🊌👩‍🊌🧑‍🊜👚‍🊜👩‍🊜🏃🏃‍♂🏃‍♀💃🕺🕎👯👯‍♂👯‍♀🧖🧖‍♂🧖‍♀🧘🧑‍🀝‍🧑👭👫👬💏👩‍❀‍💋‍👚👚‍❀‍💋‍👚👩‍❀‍💋‍👩💑👩‍❀‍👚👚‍❀‍👚👩‍❀‍👩👪👚‍👩‍👊👚‍👩‍👧👚‍👩‍👧‍👊👚‍👩‍👊‍👊👚‍👩‍👧‍👧👚‍👚‍👊👚‍👚‍👧👚‍👚‍👧‍👊👚‍👚‍👊‍👊👚‍👚‍👧‍👧👩‍👩‍👊👩‍👩‍👧👩‍👩‍👧‍👊👩‍👩‍👊‍👊👩‍👩‍👧‍👧👚‍👊👚‍👊‍👊👚‍👧👚‍👧‍👊👚‍👧‍👧👩‍👊👩‍👊‍👊👩‍👧👩‍👧‍👊👩‍👧‍👧🗣👀👥🫂👣🧳🌂☂🎃🧵🧶👓🕶🥜🥌🊺👔👕👖🧣🧀🧥🧊👗👘🥻🩱🩲🩳👙👚👛👜👝🎒🩎👞👟🥟🥿👠👡🩰👢👑👒🎩🎓🧢🪖⛑💄💍💌🩞💌🕳💣🛀🛌🔪🏺🗺🧭🧱💈🊜🊌🛢🛎🧳⌛⏳⌚⏰⏱⏲🕰🌡⛱🧚🎈🎉🎊🎎🎏🎐🧧🎀🎁🀿🪀🪁🔮🪄🧿🕹🧞🪅🪆🖌🧵🪡🧶🪢🛍📿💎📯🎙🎚🎛📻🪕📱📲☎📞📟📠🔋🔌💻🖥🖚⌚🖱🖲💜💟💿📀🧮🎥🎞📜📺📷📞📹📌🔍🔎🕯💡🔊🏮🪔📔📕📖📗📘📙📚📓📒📃📜📄📰🗞📑🔖🏷💰🪙💎💵💶💷💞💳🧟✉📧📚📩📀📥📊📫📪📬📭📮🗳✏✒🖋🖊🖌🖍📝📁📂🗂📅📆🗒🗓📇📈📉📊📋📌📍📎🖇📏📐✂🗃🗄🗑🔒🔓🔏🔐🔑🗝🔚🪓⛏⚒🛠🗡⚔🔫🪃🛡🪚🔧🪛🔩⚙🗜⚖🊯🔗⛓🪝🧰🧲🪜⚗🧪🧫🧬🔬🔭📡💉🩞💊🩹🩺🚪🪞🪟🛏🛋🪑🚜🪠🚿🛁🪀🪒🧎🧷🧹🧺🧻🪣🧌🪥🧜🧯🛒🚬⚰🪊⚱🗿🪧🚰🕎🧗🧗‍♂🧗‍♀🀺🏇⛷🏂🏌🏌‍♂🏌‍♀🏄🏄‍♂🏄‍♀🚣🚣‍♂🚣‍♀🏊🏊‍♂🏊‍♀⛹⛹‍♂⛹‍♀🏋🏋‍♂🏋‍♀🚎🚎‍♂🚎‍♀🚵🚵‍♂🚵‍♀🀞🀞‍♂🀞‍♀🀌🀌‍♂🀌‍♀🀜🀜‍♂🀜‍♀🀟🀟‍♂🀟‍♀🀹🀹‍♂🀹‍♀🧘🧘‍♂🧘‍♀🎪🛹🛌🛶🎗🎟🎫🎖🏆🏅🥇🥈🥉⚜⚟🥎🏀🏐🏈🏉🎟🥏🎳🏏🏑🏒🥍🏓🏞🥊🥋🥅⛳⛞🎣🎜🎿🛷🥌🎯🎱🎮🎰🎲🧩♟🎭🎚🧵🧶🎌🎀🎧🎷🪗🎞🎹🎺🎻🥁🪘🎬🏹💘💝💖💗💓💞💕💟❣💔❀🧡💛💚💙💜🀎🖀🀍💯💢💬👁‍🗚🗚🗯💭💀💮♚💈🛑🕛🕧🕐🕜🕑🕝🕒🕞🕓🕟🕔🕠🕕🕡🕖🕢🕗🕣🕘🕀🕙🕥🕚🕊🌀♠♥♊♣🃏🀄🎎🔇🔈🔉🔊📢📣📯🔔🔕🎵🎶💹🛗🏧🚮🚰♿🚹🚺🚻🚌🚟⚠🚞⛔🚫🚳🚭🚯🚱🚷📵🔞☢☣⬆↗➡↘⬇↙⬅↖↕↔↩↪‎‵🔃🔄🔙🔚🔛🔜🔝🛐⚛🕉✡☞☯✝☊☪☮🕎🔯♈♉♊♋♌♍♎♏♐♑♒♓⛎🔀🔁🔂▶⏩⏭⏯◀⏪⏮🔌⏫🔜⏬⏞⏹⏺⏏🎊🔅🔆📶📳📎♀♂✖➕➖➗♟‌⁉❓❔❕❗〰💱💲⚕♻⚜🔱📛🔰⭕✅☑✔❌❎➰➿ 〜✳✎❇©®™#⃣*⃣0⃣1⃣2⃣3⃣4⃣5⃣6⃣7⃣8⃣9⃣🔟🔠🔡🔢🔣🔀🅰🆎🅱🆑🆒🆓ℹ🆔Ⓜ🆕🆖🅟🆗🅿🆘🆙🆚🈁🈂🈷🈶🈯🉐🈹🈚🈲🉑🈞🈎🈳㊗㊙🈺🈵🔎🟠🟡🟢🔵🟣🟀⚫⚪🟥🟧🟚🟩🟊🟪🟫⬛⬜◌◻◟◜▪▫🔶🔷🔞🔹🔺🔻💠🔘🔳🔲🏁🚩🎌🏎🏳🏳‍🌈🏳‍⚧"

// 衚情
const expressionEmojis = '😀😃😄😁😆😅🀣😂🙂🙃😉😊😇🥰😍🀩😘😗☺😚😙🥲😋😛😜🀪😝🀑🀗🀭🀫🀔🀐🀚😐😑😶😏😒🙄😬🀥😌😔😪🀀😎😷🀒🀕🀢🀮🀧🥵🥶🥎😵🀯🀠🥳🥞😎🀓🧐😕😟🙁☹😮😯😲😳🥺😊😧😚😰😥😢😭😱😖😣😞😓😩😫🥱😀😡😠🀬😈👿💀☠💩🀡👹👺👻'

// 小劚物
const animalEmojis = "🙊💥💫💊💚🐵🐒🊍🊧🐶🐕🊮🐕‍🊺🐩🐺🊊🊝🐱🐈🐈‍⬛🊁🐯🐅🐆🐎🐎🊄🊓🊌🊬🐮🐂🐃🐄🐷🐖🐗🐜🐏🐑🐐🐪🐫🊙🊒🐘🊣🊏🊛🐭🐁🐀🐹🐰🐇🐿🊫🊔🊇🐻🐻‍❄🐚🐌🊥🊊🊚🊘🊡🐟🊃🐔🐓🐣🐀🐥🐊🐧🕊🊅🊆🊢🊉🊀🪶🊩🊚🊜🐞🐊🐢🊎🐍🐲🐉🊕🊖🐳🐋🐬🊭🐟🐠🐡🊈🐙🐚🐌🊋🐛🐜🐝🪲🐞🊗🪳🕷🕞🊂🊟🪰🪱🊠💐🌞💮🏵🌹🥀🌺🌻🌌🌷🌱🪎🌲🌳🌎🌵🌟🌿☘🍀🍁🍂🍃🍄🌰🊀🊞🊐🊑"

// 人物
const personEmojis = "👶🧒👊👧🧑👱👚🧔👚‍🊰👚‍🊱👚‍🊳👚‍🊲👩👩‍🊰🧑‍🊰👩‍🊱🧑‍🊱👩‍🊳🧑‍🊳👩‍🊲🧑‍🊲👱‍♀👱‍♂🧓👎👵🙍🙍‍♂🙍‍♀🙎🙎‍♂🙎‍♀🙅🙅‍♂🙅‍♀🙆🙆‍♂🙆‍♀💁💁‍♂💁‍♀🙋🙋‍♂🙋‍♀🧏🧏‍♂🧏‍♀🙇🙇‍♂🙇‍♀🀊🀊‍♂🀊‍♀🀷🀷‍♂🀷‍♀🧑‍⚕👚‍⚕👩‍⚕🧑‍🎓👚‍🎓👩‍🎓🧑‍🏫👚‍🏫👩‍🏫🧑‍⚖👚‍⚖👩‍⚖🧑‍🌟👚‍🌟👩‍🌟🧑‍🍳👚‍🍳👩‍🍳🧑‍🔧👚‍🔧👩‍🔧🧑‍🏭👚‍🏭👩‍🏭🧑‍💌👚‍💌👩‍💌🧑‍🔬👚‍🔬👩‍🔬🧑‍💻👚‍💻👩‍💻🧑‍🎀👚‍🎀👩‍🎀🧑‍🎚👚‍🎚👩‍🎚🧑‍✈👚‍✈👩‍✈🧑‍🚀👚‍🚀👩‍🚀🧑‍🚒👚‍🚒👩‍🚒👮👮‍♂👮‍♀🕵🕵‍♂🕵‍♀💂💂‍♂💂‍♀🥷👷👷‍♂👷‍♀🀎👞👳👳‍♂👳‍♀👲🧕🀵🀵‍♂🀵‍♀👰👰‍♂👰‍♀🀰🀱👩‍🍌👚‍🍌🧑‍🍌👌🎅🀶🧑‍🎄🊞🊞‍♂🊞‍♀🊹🊹‍♂🊹‍♀🧙🧙‍♂🧙‍♀🧚🧚‍♂🧚‍♀🧛🧛‍♂🧛‍♀🧜🧜‍♂🧜‍♀🧝🧝‍♂🧝‍♀🧞🧞‍♂🧞‍♀🧟🧟‍♂🧟‍♀💆💆‍♂💆‍♀💇💇‍♂💇‍♀🚶🚶‍♂🚶‍♀🧍🧍‍♂🧍‍♀🧎🧎‍♂🧎‍♀🧑‍🊯👚‍🊯👩‍🊯👚‍🊌🧑‍🊜👚‍🊜👩‍🊜🏃🏃‍♂🏃‍♀💃🕺🕎👯👯‍♂👯‍♀🧖🧖‍♂🧖‍♀🧘🧑‍🀝‍🧑👭👫👬"

// 手势
const guestrueEmojis = "💪👈👉☝👆👇✌✋👌👍👎✊👊👋👏👐✍"

// 公共
const publicEmojis = "♻🏧🚮🚰♿🚹🚺🚻🚌🚟⚠🚞⛔🚫🚳🚭🚯🚱🚷🔞💈"

// 生肖
const twelveEmojis = "🐁🐂🐅🐇🐉🐍🐎🐐🐒🐓🐕🐖"

export {
  defEmojis,
  allEmojis,
  expressionEmojis,
  animalEmojis,
  personEmojis,
  guestrueEmojis,
  publicEmojis,
  twelveEmojis,
}

  1. index.vue
vue
<template>
  <div class="emoji">
    <div v-if="emoji.historyList?.length">
      <p>最近䜿甚</p>
      <ul class="history" :class="emoji.historyList?.length ? 'historyShow' : ''">
        <li v-for="(item, index) in [...new Set(emoji.historyList)]" :key="index" @click.stop="chooseEmojiDefault(item)"
          v-html="item"></li>
      </ul>
    </div>
    <div v-for="items in emojiObj" :key="items.name">
      <template v-if="items.name && items.value?.length">
        <p>{{ items.name }}</p>
        <ul class="default">
          <li v-for="(item, index) in items.value" :key="index" @click.stop="chooseEmojiDefault(item)" v-html="item"></li>
        </ul>
      </template>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ref, reactive } from "vue";
import { getAllTypeEmojis } from './utils'

const emit = defineEmits(["emojiHandle"]);
const props = defineProps({
  all: {
    type: Boolean,
    default: false
  }
})

const res = getAllTypeEmojis()
console.log(res)
const emojiObj = ref({})

if (props.all) {
  emojiObj.value = res
} else {
  emojiObj.value = {
    defEmojis: res.defEmojis
  }
}
const emoji = reactive({
  chooseItem: "",
  historyList: [],
  allEmoji: emojiObj.value,
});
const chooseEmojiDefault = (item: string) => {
  emoji.chooseItem = item;
  emoji.historyList.unshift(item);
  emit("emojiHandle", item);
  return item;
};
</script>

<style lang="less" scoped>
.history::-webkit-scrollbar,
.default::-webkit-scrollbar {
  display: none;
}

.emoji {
  text-align: left;
  width: 70vw;
  max-height: 20vh;
  background: #fff;
  overflow-y: auto;


  p {
    font-size: 14px;
    padding: 1vh;
  }

  .history,
  .default {
    width: 100%;
    height: 20vh;
    overflow-y: auto;

    li {
      display: inline-block;
      padding: 1vh;
      font-size: 26px;
      width: 32px;
      height: 32px;
      line-height: 1;
      overflow: hidden;
      cursor: pointer;
    }

    li:hover {
      background-color: #ececec;
    }
  }

  .history {
    height: 0;
    width: 100%;
    position: relative;
    transition: all 2.5s;
  }

  .historyShow {
    height: 40px;
  }
}

@media screen and (max-width: 800px) {
  .emoji {
    width: 80vw;
  }
}
</style>


  1. test.vue 䜿甚瀺䟋
vue
<template>
  <smile-outlined
    style="font-size: 22px; margin: 0 2vh"
    @click="selectEmoji"
  />
  <Popover v-model:open="visible" title="" placement="top">
    <template #content>
      <div>
        <Emoji @emojiHandle="emojiHandle" :all="false" />
      </div>
    </template>
  </Popover>
  <Textarea
    :maxlength="100"
    @pressEnter="sendMessage"
    class="message-input"
    v-model:value.trim="message"
    placeholder="回蜊发送消息..."
  />
</template>

<script setup>
import Emoji from "@/components/emoji/index.vue";
import { SmileOutlined } from "@ant-design/icons-vue";
import {  Textarea, Popover } from "ant-design-vue";

const cursor = ref(0);
const message = ref('')
const visible = ref(false)
// 发送消息
const sendMessage = () => {}

/**
 * 点击展瀺衚情
 */
const selectEmoji = () => {
  const Textarea = document.querySelector(".message-input");
  cursor.value = Textarea?.selectionEnd;
  visible.value = !visible.value;
};
/**
 * 选择衚情并把衚情插入蟓入框
 * @param {*} item 选择的衚情
 */
const emojiHandle = (item) => {
  const msg = message.value;
  if (!cursor.value) {
    message.value += item;
  } else {
    message.value = msg.slice(0, cursor.value) + item + msg.slice(cursor.value);
  }
};
</script>

总结 ​

  • 敎䜓实现起来挺简单的没有螩什么坑
  • 最近䜿甚目前是存圚变量的刷新就没了后期考虑匕入角色存入数据库
  • 衚情包组件简易版已经封装了奜了需芁的小䌙䌎自取~

结语 ​

劂果本文对䜠有收获麻烊劚劚发莢的小手点点关泚、点点赞🙊🙊🙊

劂果有䞍对、可以䌘化的地方欢迎圚评论区指出谢谢😂😂