Vue評論留言的表情功能實現
介紹:使用的微信提供的表情包地址,生成img標簽,然后用v-html渲染.然后點擊標簽返回#表情名字;
帶有#表情名字;
的內容用正則表達式處理替換成img標簽,其他文字不變,然后用v-html渲染出來
大概就是點擊標簽,然后input/areatext框里面出現#表情名字
,然后content里的#表情名字
會變成
第一步 擁有一個表情名字的數組
為了共用,這個數組可以放到一個js文件里並導出
例:https://res.wx.qq.com/mpres/htmledition/images/icon/emotion/0.gif 這表情就是微笑 ,然后數組中微笑的下標就是0
// 這里是放在 src\assets\js\emotionList.js
export default{emotionList:["微笑","撇嘴","色","發呆","得意","流淚","害羞","閉嘴","睡","大哭","尷尬","發怒","調皮","呲牙","驚訝","難過","酷","冷汗","抓狂","吐","偷笑","可愛","白眼","傲慢","飢餓","困","驚恐","流汗","憨笑","大兵","奮斗","咒罵","疑問","噓","暈","折磨","衰","骷髏","敲打","再見","擦汗","摳鼻","鼓掌","糗大了","壞笑","左哼哼","右哼哼","哈欠","鄙視","委屈","快哭了","陰險","親親","嚇","可憐","菜刀","西瓜","啤酒","籃球","乒乓","咖啡","飯","豬頭","玫瑰","凋謝","示愛","愛心","心碎","蛋糕","閃電","炸彈","刀","足球","瓢蟲","便便","月亮","太陽","禮物","擁抱","強","弱","握手","勝利","抱拳","勾引","拳頭","差勁","愛你","不","好","愛情","飛吻","跳跳","發抖","慪火","轉圈","磕頭","回頭","跳繩","揮手","激動","街舞","獻吻","左太極","右太極"]}
第二步 編寫表情展示組件(一個按鈕和一個表情盒子)
- 這個組件(display:inline-block)默認就只展示一個emotion然后點擊展示它會展示出一個表情盒子
- 這三部分是同一個文件的,復制到一起直接就可以用了
<template>
<div @click="handleShowClick" class="emotion-box">
<slot>
<span class="emotion">emotion</span>
</slot>
<div v-if="load" v-show="show" class="box">
<span
class="emo"
v-for="(line, i) in emotionArr"
:key="'emojo'+i"
@click.stop="emoClick(line.name)"
v-html="line.url"
></span>
</div>
</div>
</template>
-
點擊emotion(可以視為按鈕)觸發
handleShowClick()
,如果沒有加載過表情盒子則去調用loadEmotion()
加載表情盒子(懶加載) -
loadEmotion()
遍歷第一步里的數組並生成一個對象數組(對象的名字,img表情完全體) -
在
<template>
中用v-for和emotionArr生成一堆<img ... />
在盒子里 -
然后給每個
設置事件監聽,點擊時觸發
emoClick
並向父組件發送這個表情的名字(子向父傳值)
<script>
// emo: 單個span標簽標簽簡寫
// TODO 鼠標點擊其他地方關閉
// 位置 src\components\common\emotion-box.vue
import emotions from '@/assets/js/emotionList.js'
export default {
name: 'emotion-box',
data() {
return {
show: false, // 是否展示表情框(表情盒子)
load: false, // 是否加載了表情框
emotionArr: null, //表情數組
}
},
methods: {
// 監聽span點擊來選擇展示表情box
handleShowClick() {
// 當第一次點擊展開在渲染表情盒子 懶加載
if (this.load == false) this.loadEmotion()
this.show = !this.show //切換表情盒子的展示狀況
},
// 表情點擊把名字發給父組件(調用者)
emoClick(arg) {
this.show = false // 關閉表情盒子
this.$emit('emotionClick', arg)
},
// 加載表情
loadEmotion() {
const list = emotions.emotionList
let emotionArr = []
list.map((item, index) => {
emotionArr.push({
name: `#${item};`,
url: `<img title="${item}" src="https://res.wx.qq.com/mpres/htmledition/images/icon/emotion/${index}.gif">`,
})
})
this.emotionArr = emotionArr
this.load = true
console.log('表情盒子加載完成')
},
},
}
</script>
- 然后就是隨便加點樣式,別看代碼多主要是設置相對定位和絕對定位,還可以設置下z-index防止被覆蓋
<style lang="scss" scoped>
.emotion-box {
// 重要的就是加個相對定位
display: inline-block;
position: relative;
> .emotion {
cursor: pointer;
height: 30px;
user-select: none;
line-height: 30px;
padding: 2px 4px;
border: 1px solid #9c9a9a;
border-radius: 7px;
margin-right: 5px;
&:hover {
background-color: aquamarine;
}
}
// 重要的就是加個絕對定位 其他就是好看的
> .box {
z-index: 10;
position: absolute;
background-color: #fff;
width: 285px;
max-height: 150px;
overflow: scroll;
top: 30px;
border: 1px solid aqua;
// 每個span表情標簽樣式
.emo {
cursor: pointer;
}
}
}
</style>
然后別的組件導入,注冊下這個組件,然后寫個函數處理監聽到的表情點擊事件就可以了
第三步 寫個函數利用正則表達式處理帶有特殊格式的內容
當有xxx#色;
的文字就會變轉成成xxx😍 (就是img標簽)
把內容用這個函數處理,然后交給v-html
import emotions from '../assets/js/emotionList.js';
export function processEmotion(str) {
return str.replace(/\#[\u4E00-\u9FA5]{1,3}\;/gi, (words) => {
let word = words.replace(/\#|\;/gi, '')
let index = emotions.emotionList.indexOf(word)
if (index !== -1) {
return `<img src="https://res.wx.qq.com/mpres/htmledition/images/icon/emotion/${index}.gif" align="middle">`
} else {
return words
}
})
}