消息组件
Messages Vue 组件代表 消息 组件。
消息组件
包括以下组件
f7-messages
- 主要消息容器f7-message
- 单个消息元素f7-messages-title
- 单个消息标题元素
消息属性
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
<f7-messages> 属性 | |||
init | 布尔值 | 真 | 初始化消息组件 |
new-messages-first | 布尔值 | 布尔值 | 假 |
如果您希望在顶部使用新消息(而不是在底部),请启用此选项 | 布尔值 | 真 | 启用/禁用在添加新消息时自动滚动消息 |
scroll-messages-on-edge | 布尔值 | 真 | 如果启用,则仅当用户位于消息视图的顶部/底部时,才会自动滚动消息 |
输入 | 布尔值 | 布尔值 | 允许显示/切换输入消息指示符 |
<f7-message> 属性 | |||
类型 | 字符串 | 发送 | 消息类型:发送 (默认)或已接收 |
文本 | 字符串 | 消息文本 | |
头像 | 字符串 | 消息用户头像网址 | |
名称 | 字符串 | 消息用户姓名 | |
图像 | 字符串 | 消息图像网址 | |
页眉 | 字符串 | 消息页眉 | |
页脚 | 字符串 | 消息页脚 | |
文本页眉 | 字符串 | 消息文本页眉 | |
文本页脚 | 字符串 | 消息文本页脚 | |
第一个 | 布尔值 | 布尔值 | 定义该消息在对话中第一个 |
最后一个 | 布尔值 | 布尔值 | 定义该消息在对话中最后一个 |
尾部 | 布尔值 | 布尔值 | 定义该消息具有视觉“尾部”。通常是对话中的最后一则消息 |
同名 | 布尔值 | 布尔值 | 定义此消息发送者名称与上条消息中的发送者名称相同 |
同页眉 | 布尔值 | 布尔值 | 定义此消息页眉文本与上一条消息中的内容相同 |
同页脚 | 布尔值 | 布尔值 | 定义此消息页脚文本与上一条消息中的内容相同 |
同头像 | 布尔值 | 布尔值 | 定义此消息用户头像网址与上一条消息中的内容相同 |
消息事件
事件 | 描述 |
---|---|
<f7-message> 事件 | |
单击 | 当用户单击消息气泡时触发该事件 |
单击:名称 | 当用户单击消息用户姓名时触发该事件 |
单击:文本 | 当用户单击消息文本时触发该事件 |
单击:头像 | 当用户单击消息用户头像时触发该事件 |
单击:页眉 | 当用户单击消息页眉时触发该事件 |
单击:页脚 | 当用户单击消息页脚时触发该事件 |
单击:气泡 | 当用户单击消息气泡时触发该事件 |
消息槽
单个消息 Vue 组件(<f7-message>
)具有其他自定义元素槽
默认
- 元素将作为<div class="message-bubble">
元素的子元素插入末尾开始
- 元素将插入到开头并作为主消息元素<div class="message">
的直接子元素结尾
- 元素将插入到结尾并作为主消息元素<div class="message">
的直接子元素内容开始
- 元素将插入到开头并作为<div class="message-content">
元素的直接子元素内容结束
- 元素将插入到结尾并作为<div class="message-content">
元素的直接子元素气泡开始
- 元素将插入到开头并作为<div class="message-bubble">
元素的直接子元素气泡结束
- 元素将插入到结尾并作为<div class="message-bubble">
元素的直接子元素。与默认
槽相同
需要传入更多复杂布局时,在单个消息内部可使用以下插槽,而不是使用相同道具
header
- 元素将插入到消息标题中footer
- 元素将插入到消息页脚中text
- 元素将插入到消息文本中name
- 元素将插入到消息名称中image
- 元素将插入到消息图片中(假定为<img>
元素)text-header
- 元素将插入到消息文本头中text-footer
- 元素将插入到消息文本页脚中
<f7-message
type="sent"
text="Hello World"
name="John Doe"
avatar="path/to/image.jpg"
>
<div slot="start">Start</div>
<div slot="end">End</div>
<div slot="content-start">Content Start</div>
<div slot="content-end">Content End</div>
<div slot="bubble-start">Bubble Start</div>
<div slot="bubble-end">Bubble End</div>
</f7-message>
<!-- Renders to: -->
<div class="message message-sent">
<div>Start</div>
<div class="message-avatar" style="background-image: url(path/to/image.jpg);"></div>
<div class="message-content">
<div>Content Start</div>
<div class="message-name">John Doe</div>
<div class="message-bubble">
<div>Bubble Start</div>
<div class="message-text">Hello World</div>
<div>Bubble End</div>
</div>
<div>Content End</div>
</div>
<div>End</div>
</div>
示例
以下是 Messages 页面的完整示例,其中可与 Messagebar 一起使用
messages.vue
<template>
<f7-page>
<f7-navbar title="Messages"></f7-navbar>
<f7-messagebar
ref="messagebar"
v-model:value="messageText"
:placeholder="placeholder"
:attachments-visible="attachmentsVisible"
:sheet-visible="sheetVisible"
>
<template #inner-start>
<f7-link
icon-ios="f7:camera_fill"
icon-md="material:camera_alt"
@click="sheetVisible = !sheetVisible"
/>
</template>
<template #inner-end>
<f7-link icon-ios="f7:arrow_up_circle_fill" icon-md="material:send" @click="sendMessage" />
</template>
<f7-messagebar-attachments>
<f7-messagebar-attachment
v-for="(image, index) in attachments"
:key="index"
:image="image"
@attachment:delete="deleteAttachment(image)"
></f7-messagebar-attachment>
</f7-messagebar-attachments>
<f7-messagebar-sheet>
<f7-messagebar-sheet-image
v-for="(image, index) in images"
:key="index"
:image="image"
:checked="attachments.indexOf(image) >= 0"
@change="handleAttachment"
></f7-messagebar-sheet-image>
</f7-messagebar-sheet>
</f7-messagebar>
<f7-messages>
<f7-messages-title><b>Sunday, Feb 9,</b> 12:58</f7-messages-title>
<f7-message
v-for="(message, index) in messagesData"
:key="index"
:type="message.type"
:image="message.image"
:name="message.name"
:avatar="message.avatar"
:first="isFirstMessage(message, index)"
:last="isLastMessage(message, index)"
:tail="isTailMessage(message, index)"
>
<template v-if="message.text" #text>
<!-- eslint-disable-next-line -->
<span v-html="message.text"></span>
</template>
</f7-message>
<f7-message
v-if="typingMessage"
type="received"
:typing="true"
:first="true"
:last="true"
:tail="true"
:header="`${typingMessage.name} is typing`"
:avatar="typingMessage.avatar"
></f7-message>
</f7-messages>
</f7-page>
</template>
<script>
import {
f7Navbar,
f7Page,
f7Messages,
f7MessagesTitle,
f7Message,
f7Messagebar,
f7Link,
f7MessagebarAttachments,
f7MessagebarAttachment,
f7MessagebarSheet,
f7MessagebarSheetImage,
f7ready,
f7,
} from 'framework7-vue';
import $ from 'dom7';
export default {
components: {
f7Navbar,
f7Page,
f7Messages,
f7MessagesTitle,
f7Message,
f7Messagebar,
f7MessagebarAttachments,
f7MessagebarAttachment,
f7MessagebarSheet,
f7MessagebarSheetImage,
f7Link,
},
data() {
return {
attachments: [],
sheetVisible: false,
typingMessage: null,
messageText: '',
messagesData: [
{
type: 'sent',
text: 'Hi, Kate',
},
{
type: 'sent',
text: 'How are you?',
},
{
name: 'Kate',
type: 'received',
text: 'Hi, I am good!',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
},
{
name: 'Blue Ninja',
type: 'received',
text: 'Hi there, I am also fine, thanks! And how are you?',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
},
{
type: 'sent',
text: 'Hey, Blue Ninja! Glad to see you ;)',
},
{
type: 'sent',
text: 'Hey, look, cutest kitten ever!',
},
{
type: 'sent',
image: 'https://cdn.framework7.io/placeholder/cats-200x260-4.jpg',
},
{
name: 'Kate',
type: 'received',
text: 'Nice!',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
},
{
name: 'Kate',
type: 'received',
text: 'Like it very much!',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
},
{
name: 'Blue Ninja',
type: 'received',
text: 'Awesome!',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
},
],
images: [
'https://cdn.framework7.io/placeholder/cats-300x300-1.jpg',
'https://cdn.framework7.io/placeholder/cats-200x300-2.jpg',
'https://cdn.framework7.io/placeholder/cats-400x300-3.jpg',
'https://cdn.framework7.io/placeholder/cats-300x150-4.jpg',
'https://cdn.framework7.io/placeholder/cats-150x300-5.jpg',
'https://cdn.framework7.io/placeholder/cats-300x300-6.jpg',
'https://cdn.framework7.io/placeholder/cats-300x300-7.jpg',
'https://cdn.framework7.io/placeholder/cats-200x300-8.jpg',
'https://cdn.framework7.io/placeholder/cats-400x300-9.jpg',
'https://cdn.framework7.io/placeholder/cats-300x150-10.jpg',
],
people: [
{
name: 'Kate Johnson',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg',
},
{
name: 'Blue Ninja',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg',
},
],
answers: [
'Yes!',
'No',
'Hm...',
'I am not sure',
'And what about you?',
'May be ;)',
'Lorem ipsum dolor sit amet, consectetur',
'What?',
'Are you sure?',
'Of course',
'Need to think about it',
'Amazing!!!',
],
responseInProgress: false,
};
},
computed: {
attachmentsVisible() {
const self = this;
return self.attachments.length > 0;
},
placeholder() {
const self = this;
return self.attachments.length > 0 ? 'Add comment or Send' : 'Message';
},
},
mounted() {
const self = this;
f7ready(() => {
self.messagebar = f7.messagebar.get(self.$refs.messagebar.$el);
});
},
methods: {
isFirstMessage(message, index) {
const self = this;
const previousMessage = self.messagesData[index - 1];
if (message.isTitle) return false;
if (
!previousMessage ||
previousMessage.type !== message.type ||
previousMessage.name !== message.name
)
return true;
return false;
},
isLastMessage(message, index) {
const self = this;
const nextMessage = self.messagesData[index + 1];
if (message.isTitle) return false;
if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name)
return true;
return false;
},
isTailMessage(message, index) {
const self = this;
const nextMessage = self.messagesData[index + 1];
if (message.isTitle) return false;
if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name)
return true;
return false;
},
deleteAttachment(image) {
const self = this;
const index = self.attachments.indexOf(image);
self.attachments.splice(index, 1)[0]; // eslint-disable-line
},
handleAttachment(e) {
const self = this;
const index = $(e.target).parents('label.checkbox').index();
const image = self.images[index];
if (e.target.checked) {
// Add to attachments
self.attachments.unshift(image);
} else {
// Remove from attachments
self.attachments.splice(self.attachments.indexOf(image), 1);
}
},
sendMessage() {
const self = this;
const text = self.messageText.replace(/\n/g, '<br>').trim();
const messagesToSend = [];
self.attachments.forEach((attachment) => {
messagesToSend.push({
image: attachment,
});
});
if (text.length) {
messagesToSend.push({
text,
});
}
if (messagesToSend.length === 0) {
return;
}
// Reset attachments
self.attachments = [];
// Hide sheet
self.sheetVisible = false;
// Clear area
self.messageText = '';
// Focus area
if (text.length) self.messagebar.focus();
// Send message
self.messagesData.push(...messagesToSend);
// Mock response
if (self.responseInProgress) return;
self.responseInProgress = true;
setTimeout(() => {
const answer = self.answers[Math.floor(Math.random() * self.answers.length)];
const person = self.people[Math.floor(Math.random() * self.people.length)];
self.typingMessage = {
name: person.name,
avatar: person.avatar,
};
setTimeout(() => {
self.messagesData.push({
text: answer,
type: 'received',
name: person.name,
avatar: person.avatar,
});
self.typingMessage = null;
self.responseInProgress = false;
}, 4000);
}, 1000);
},
},
};
</script>