最近做一个项目,实现类似微信公众号评论回复功能,如图所示:
大概分以下几个组件:
表情包组件:
<template>
<div class="showEmjio" :style="propStyle">
<div class="emjioTitle">
<p>默认表情:</p>
<p @click.prevent="closeEmoji"><i class="iconfont icon-guanbi"></i></p>
</div>
<div class="emjio">
<img
v-show="false"
src="https://im.teams.com/explore/imEmjio/emjioSpritesNew.jpg"
@load="emojiLoad"
/>
<ul>
<li v-for="(emoji, index) in emojiList" :key="index">
<span
class="rong-emoji-item rong-emoji-mac-item"
:title="emoji.name"
@click="selectEmoji(emoji)"
>
<span
class="rong-emoji-content"
:style="{
'background-image': `url(${
emojiRoload
? 'https://im.teams.com/explore/imEmjio/emjioSpritesNew.jpg'
: 'https://im.teams.com/explore/imEmjio/emjioThumbnail.jpg'
})`,
'background-size': '240px 504px',
'background-position': `${-parseInt(index % 10) * 24}px ${
-parseInt(index / 10) * 24
}px`,
}"
></span>
</span>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props: {
emojiList: {
type: Array,
default: () => [],
},
emojiRoload: {
type: Boolean,
default: () => false,
},
propStyle: {
type: Object,
default: () => {},
},
},
data() {
return {};
},
created() {},
mounted() {},
methods: {
closeEmoji() {
this.$emit('closeEmoji');
},
emojiLoad() {
this.$emit('emojiLoad');
},
selectEmoji(emoji) {
this.$emit('selectEmoji', emoji);
},
},
};
</script>
<style scoped lang="scss">
</style>
css:
.showEmjio {
width: 320px;
border-radius: 8px;
background: #fff;
position: absolute;
z-index: 10;
top: 110px;
left: 0px;
box-shadow: 0px 0px 14px 0px rgba(156, 157, 160, 0.76);
box-sizing: border-box;
}
.emjio {
width: 100%;
height: 300px;
overflow: auto;
display: flex;
justify-content: center;
padding: 12px 0 0 12px;
ul {
width: 100%;
display: flex;
flex-wrap: wrap;
}
}
.emjioTitle {
height: 40px;
line-height: 40px;
color: #202124;
font-size: 16px;
border-bottom: 1px solid #eceff0;
padding: 0 16px;
font-weight: bold;
display: flex;
justify-content: space-between;
i {
font-size: 14px;
color: #9a9a9a;
font-weight: normal;
cursor: pointer;
}
}
.emjioBtn {
display: flex;
justify-content: flex-end;
align-items: center;
height: 48px;
padding-right: 10px;
p {
&:nth-child(1) {
width: 60px;
height: 28px;
background: #4273f6;
border-radius: 3px;
line-height: 28px;
text-align: center;
font-size: 14px;
color: #fff;
cursor: pointer;
}
&:nth-child(2) {
width: 60px;
height: 28px;
background: #ffffff;
border: 1px solid #e8ebec;
border-radius: 3px;
line-height: 28px;
text-align: center;
color: #5f6368;
margin-left: 8px;
cursor: pointer;
}
}
}
输入框组件:
<template>
<div class="input_area">
<textarea
class="rong-text-area el-textarea__inner"
ref="textarea"
cols="30"
rows="2"
placeholder="添加评论"
:value="value"
@input="updateInput"
></textarea>
<div class="button">
<iconpark-icon
class="iconfont"
size="24px"
name="biaoqing"
@click.stop="toggleEmoji"
></iconpark-icon>
<button @click="confirmlComment()">留言</button>
</div>
</div>
</template>
<script>
function getCursorOffset(el) {
return el.selectionStart;
}
const MaxLen = 100;
export default {
data() {
return {
value: '',
};
},
created() {},
mounted() {},
methods: {
getValue() {
return {
text: this.value,
};
},
insertText(str) {
const el = this.$refs.textarea;
let cursorOffset = getCursorOffset(el);
let text = el.value;
const beforeCursorStr = text.substring(0, cursorOffset);
const afterCursorStr = text.substring(el.selectionEnd);
text = beforeCursorStr + str + afterCursorStr;
el.value = text;
cursorOffset += str.length;
el.focus();
el.setSelectionRange(cursorOffset, cursorOffset);
this.value = text;
},
focus() {
this.$refs.textarea.focus();
},
textareaVal() {
return this.getValue().text;
},
resetVal() {
this.value = '';
},
toggleEmoji() {
this.$emit('toggleEmoji');
},
confirmlComment() {
this.$emit('confirmlComment', this.value);
},
updateInput(event) {
const _this = this;
this.value = event.target.value;
if (this.value.length > MaxLen) {
this.value = this.value.substr(0, MaxLen);
}
_this.$emit('editBoxChange', _this.getValue().text);
},
},
};
</script>
<style scoped lang="scss">
.input_area {
width: 100%;
background: #ffffff;
border: 1px solid #4273f6;
border-radius: 4px;
.button {
padding: 0 8px 8px 0px;
text-align: right;
display: flex;
align-items: center;
justify-content: flex-end;
.iconfont {
margin-right: 16px;