消息栏 Vue 组件

消息栏 Vue 组件代表 Framework7 的消息栏组件。

消息栏组件

包含以下组件:

消息栏属性

属性类型默认描述
<f7-messagebar> 属性
init布尔值true初始化消息栏
name字符串文本区域 "name" 属性
textarea-id字符串
数字
文本区域 "id" 属性
占位符字符串消息文本区域占位符文本
字符串
数字
文本区域值
只读布尔值false设置 "readonly" 文本区域属性
禁用布尔值false设置 "disabled" 文本区域属性
send-link字符串启用发送链接并指定其文本。如果使用send-link插槽相同
max-height数字定义可调整大小的文本区域最大高度
resizable布尔值true启用可调整大小的文本区域
sheet-visible布尔值false使消息栏表单可见/激活
attachments-visible布尔值false使消息栏附件可见/激活
resize-page布尔值true当启用时,它会在消息栏文本区域大小变化时调整消息页面
<f7-messagebar-sheet-image> 属性
图片字符串表单图片 URL
已选中布尔值false指示此表单图片项是否被选中
<f7-messagebar-attachment> 属性
图片字符串附件图片 URL
deletable布尔值true定义附件是否可删除。如果是可删除的,将渲染额外的删除按钮

消息栏事件

事件参数描述
<f7-messagebar> 事件
change(event)当在消息栏文本区域元素上发生 "change" 事件时,将触发此事件
input(event)当在消息栏文本区域元素上发生 "input" 事件时,将触发此事件
focus(event)当在消息栏文本区域元素上发生 "focus" 事件时,将触发此事件
blur(event)当在消息栏文本区域元素上发生 "blur" 事件时,将触发此事件
submit
send
(value, clear)当用户点击消息栏 "发送链接" 时,将触发此事件
<f7-messagebar-sheet-image> 事件
change(event)当表单项复选框更改时,将触发此事件
<f7-messagebar-attachment> 事件
attachment:click(event)当附件被点击时,将触发此事件
attachment:delete(event)当附件删除按钮被点击时,将触发此事件

消息栏插槽

消息栏 Vue 组件有额外的插槽用于自定义元素:

<f7-messagebar placeholder="Message" @submit="onSubmit">
  <div slot="before-inner">Before inner</div>
  <div slot="after-inner">After inner</div>
  <div slot="before-area">Before textarea</div>
  <div slot="after-area">After textarea</div>
  <f7-icon ios="f7:arrow_up_fill" md="material:send" slot="send-link"></f7-icon>
  <div>Default slot</div>
</f7-messagebar>

渲染到:

<div class="toolbar messagebar">
  <div>Before inner</div>
  <div class="toolbar-inner">
    <div class="messagebar-area">
      <div>Before textarea</div>
      <textarea placeholder="Message"></textarea>
      <div>After textarea</div>
    </div>
    <a href="#" class="link"><i class="icon f7-icons">arrow_up_fill</i></a>
    <div>Default slot</div>
  </div>
  <div>After inner</div>
</div>

消息栏 v-model

f7-messagebar组件支持v-modelonvalueprop:

<template>
  ...
  <f7-messagebar
    v-model:value="messageText"
  />
  ...
</template>
<script>
  export default {
    data() {
      messageText: '',
    },
    ...
  };
</script>

示例

这里是完整的消息页面示例,它可以在消息:

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>
无噪 Logo
无噪文档
中文文档 · 复刻官网
查看所有 ↗