訊息

訊息元件將協助您在應用程式中視覺化留言和訊息系統。

訊息配置

<div class="page">
  <div class="page-content messages-content">
    <div class="messages">
      <!-- Date stamp -->
      <div class="messages-title"><b>Sunday, Feb 9</b> 12:58</div>

      <!-- Sent message (by default - green and on right side) -->
      <div class="message message-sent">
        <div class="message-content">
          <!-- Bubble with text -->
          <div class="message-bubble">
            <div class="message-text">Hi, Kate</div>
          </div>
        </div>
      </div>

      <!-- Another sent message -->
      <div class="message message-sent">
        <div class="message-content">
          <div class="message-bubble">
            <div class="message-text">How are you?</div>
          </div>
        </div>
      </div>

      <!-- Received message (by default - grey on left side) -->
      <div class="message message-received">
        <!-- Sender avatar -->
        <div class="message-avatar" style="background-image:url(path/to/avatar.jpg)"></div>
        <div class="message-content">
          <!-- Sender name -->
          <div class="message-name">Blue Ninja</div>
          <!-- Bubble with text -->
          <div class="message-bubble">
            <div class="message-text">Hi there, I am also fine, thanks! And how are you?</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

訊息頁面配置

單一訊息配置

以下是完整的單一訊息配置

<div class="message">
  <div class="message-avatar" style="background-image:url(path/to/avatar)"></div>
  <div class="message-content">
    <div class="message-name">John Doe</div>
    <div class="message-header">Message header</div>
    <div class="message-bubble">
      <div class="message-text-header">Text header</div>
      <div class="message-image">
        <img src="path/to/image" />
      </div>
      <div class="message-text">Hello world!</div>
      <div class="message-text-footer">Text footer</div>
    </div>
    <div class="message-footer">Message footer</div>
  </div>
</div>

單一訊息容器的額外類別

訊息應用程式方法

現在,當我們有訊息的 HTML 時,我們需要初始化它。我們需要使用相關應用程式的程式碼

app.messages.create(parameters)使用參數初始化訊息
  • parameters - 物件 - 包含訊息參數的物件
  • 方法傳回已初始化的訊息實例
app.messages.destroy(el)銷毀訊息實例
  • el - HTMLElement字串(使用 CSS 選擇器)或 物件。要銷毀的訊息元素或訊息實例。
app.messages.get(el)透過 HTML 元素取得訊息實例
  • el - HTMLElement字串(使用 CSS 選擇器)。訊息元素。
  • 方法傳回訊息的實例

訊息參數

讓我們看看所有可用參數的清單

參數類型預設值說明
autoLayout布林值true啟用自動版面配置,以根據傳遞的條件自動新增所有必要的附加類別
newMessagesFirst布林值false如果你想要使用頂部的最新訊息,而不是在底部,請啟用
scrollMessages布林值true啟用/停用新增新訊息時訊息自動捲動
scrollMessagesOnEdge布林值true如果啟用,則僅當使用者在訊息檢視的頂部/底部時,訊息才會自動捲動
messages陣列包含初始訊息的陣列。陣列中的每個訊息應表示為具有 單一訊息參數 的物件
on物件

包含事件處理常式的物件。例如

var messages = app.messages.create({
  el: '.messages',
  on: {
    change: function () {
      console.log('Textarea value changed')
    }
  }
})
renderMessagefunction(message)用於呈現單一訊息的函式。必須傳回完整的訊息 HTML 字串
自動版面配置條件
firstMessageRulefunction(message, previousMessage, nextMessage)函式,必須根據先前的訊息和後續訊息的必要條件傳回布林值 truefalse。如果符合條件,則會將 message-first 類別新增至訊息
lastMessageRulefunction(message, previousMessage, nextMessage)函式,必須根據先前的訊息和後續訊息的必要條件傳回布林值 truefalse。如果符合條件,則會將 message-last 類別新增至訊息
tailMessageRulefunction(message, previousMessage, nextMessage)函式,必須根據先前的訊息和後續訊息的必要條件傳回布林值 truefalse。如果符合條件,則會將 message-tail 類別新增至訊息
sameNameMessageRulefunction(message, previousMessage, nextMessage)函式,必須根據先前的訊息和後續訊息的必要條件傳回布林值 truefalse。如果符合條件,則會將 message-same-name 類別新增至訊息
sameHeaderMessageRulefunction(message, previousMessage, nextMessage)必須根據前則和後則訊息的必要條件回傳布林值 truefalse 的函數。若符合條件,則會將 message-same-header 類別新增至訊息
sameFooterMessageRulefunction(message, previousMessage, nextMessage)必須根據前則和後則訊息的必要條件回傳布林值 truefalse 的函數。若符合條件,則會將 message-same-footer 類別新增至訊息
sameAvatarMessageRulefunction(message, previousMessage, nextMessage)必須根據前則和後則訊息的必要條件回傳布林值 truefalse 的函數。若符合條件,則會將 message-same-avatar 類別新增至訊息
customClassMessageRulefunction(message, previousMessage, nextMessage)必須根據前則和後則訊息的必要條件回傳其他訊息類別為字串的函數。

單一訊息參數

當我們傳遞 messages 陣列時,讓我們來看看我們應該使用的單一訊息參數物件

參數類型預設值說明
text字串訊息文字
header字串單一訊息標題
footer字串單一訊息頁尾
name字串寄件者姓名
avatar字串寄件者頭像 URL 字串
type字串sent訊息類型 - sentreceived
textHeader字串訊息文字標題
textFooter字串訊息文字頁尾
image字串訊息圖片 HTML 字串,例如 <img src="path/to/image" />。可用於取代 imageSrc 參數
imageSrc字串訊息圖片 URL 字串。可用於取代 image 參數
isTitle布林值定義是否應呈現為訊息或訊息標題
cssClass字串設定在訊息 HTML 元素上的其他 CSS 類別
attrs物件物件包含要設定在訊息 HTML 元素上的其他 HTML 屬性。例如,若要設定額外的 data 屬性,它應如下所示
var message = {
  text: 'Hello!',
  attrs: {
    'data-id': 1,
    'data-author-id': 150
  }
}

訊息方法和屬性

因此,若要建立訊息,我們必須呼叫

var messages = app.messages.create({ /* parameters */ })

在初始化訊息後,我們在變數中初始化其執行個體(例如上述範例中的 messages 變數),並具有有用的方法和屬性

屬性
messages.params包含已傳遞初始化參數的物件
messages.el訊息容器 HTML 元素(<div class="messages">
messages.$el包含訊息 HTML 元素的 Dom7 元素
messages.messages包含訊息的陣列
方法
messages.showTyping(message)顯示輸入訊息指標
messages.hideTyping()隱藏輸入訊息指標
messages.addMessage(message, method, animate);

根據 method 參數,將新訊息新增至尾端或開頭

  • message - object - 要新增的 訊息參數。必要。
  • method - string - (appendprepend) 指示將新訊息新增至訊息容器的尾端或開頭。選擇性,如果未指定,則會根據 newMessagesFirst 參數新增訊息
  • animate - boolean - (預設為 true) 您可以在此處傳遞 false,訊息將立即新增,而不會有任何過渡或捲動動畫。選擇性。
  • 方法傳回訊息實例
messages.addMessages(messages, method, animate);一次新增多則訊息。
  • messages - 要新增的訊息 陣列。陣列中的每則訊息應以包含 訊息參數 的物件呈現。必要。
  • 方法傳回訊息實例
messages.removeMessage(message);移除訊息
  • message - 要移除的訊息的 HTMLElement字串 (使用 CSS 選擇器) 或 數字 (使用 messages 陣列中訊息的索引編號)
  • 方法傳回訊息實例
messages.removeMessages(messages);移除多則訊息
  • messages - 要移除的訊息 陣列
  • 方法傳回訊息實例
messages.scroll(duration, position);根據 newMessagesFirst 參數將訊息捲動至頂端/底部
  • duration - 數字 捲動持續時間 (毫秒)
  • position - 數字 捲動位置 (像素)
messages.renderMessages()根據 messages 陣列呈現訊息 HTML
messages.layout();強制訊息自動佈局
messages.clear();清除/移除所有訊息
messages.destroy();銷毀訊息實例

訊息事件

訊息將在訊息元素上觸發以下 DOM 事件,以及在應用程式和訊息實例上觸發事件

DOM 事件

事件目標說明
messages:beforedestroy訊息元素<div class="messages">事件將在訊息實例被銷毀之前觸發

應用程式和訊息實例事件

訊息實例會在自身實例和應用程式實例上發出事件。應用程式實例事件具有相同的名稱,但前綴為 messages

事件目標參數說明
beforeDestroymessages(messages)事件將在訊息實例被銷毀之前觸發
messagesBeforeDestroyapp

訊息自動初始化

如果您不需要使用訊息 API,而且您的訊息在頁面內部,並在頁面初始化時顯示在 DOM 中,則只需將額外的 messages-init 類別新增到訊息元素即可自動初始化,並且可以使用 data- 屬性傳遞所有必需的參數

<div class="messages messages-init" data-new-messages-first="true">
  ...
</div>

在 camelCase 中使用的參數,例如 newMessagesFirst,在 data- 屬性中應使用 kebab-case,例如 data-new-messages-first

CSS 變數

以下是相關 CSS 變數 (CSS 自訂屬性) 的清單。

請注意,註解的變數預設未指定,它們的值是它們在此情況下的後備值。

:root {
  --f7-message-text-header-opacity: 0.65;
  --f7-message-text-header-font-size: 12px;
  --f7-message-text-footer-opacity: 0.65;
  --f7-message-text-footer-font-size: 12px;
  --f7-message-bubble-line-height: 1.2;
  --f7-message-header-font-size: 12px;
  --f7-message-footer-font-size: 11px;
  --f7-message-name-font-size: 12px;
  --f7-message-name-font-weight: inherit;
  --f7-message-avatar-border-radius: 50%;
  --f7-messages-title-font-weight: inherit;
  --f7-message-typing-indicator-bg-color: #000;
}
:root .dark,
:root.dark {
  --f7-message-typing-indicator-bg-color: #fff;
}
.ios {
  --f7-message-text-header-text-color: inherit;
  --f7-message-text-footer-text-color: inherit;
  --f7-messages-title-font-size: 11px;
  --f7-message-avatar-size: 29px;
  --f7-message-margin: 10px;
  --f7-message-bubble-min-height: 32px;
  --f7-message-bubble-font-size: 17px;
  --f7-message-bubble-border-radius: 16px;
  --f7-message-bubble-padding-vertical: 6px;
  --f7-message-bubble-padding-horizontal: 16px;
  --f7-message-typing-indicator-opacity: 0.35;
  /*
  --f7-message-sent-bg-color: var(--f7-theme-color);
  */
  --f7-message-sent-text-color: #fff;
  --f7-messages-content-bg-color: #fff;
  --f7-message-received-text-color: #000;
  --f7-message-received-bg-color: #e5e5ea;
  --f7-messages-title-text-color: rgba(0, 0, 0, 0.45);
  --f7-message-header-text-color: rgba(0, 0, 0, 0.45);
  --f7-message-footer-text-color: rgba(0, 0, 0, 0.45);
  --f7-message-name-text-color: rgba(0, 0, 0, 0.45);
}
.ios .dark,
.ios.dark {
  --f7-message-received-bg-color: #252525;
  --f7-message-received-text-color: #fff;
  --f7-messages-content-bg-color: transparent;
  --f7-messages-title-text-color: rgba(255, 255, 255, 0.54);
  --f7-message-header-text-color: rgba(255, 255, 255, 0.54);
  --f7-message-name-text-color: rgba(255, 255, 255, 0.54);
  --f7-message-footer-text-color: rgba(255, 255, 255, 0.54);
}
.md {
  --f7-messages-content-bg-color: transparent;
  --f7-messages-title-font-size: 12px;
  --f7-message-avatar-size: 32px;
  --f7-message-margin: 16px;
  --f7-message-bubble-min-height: 40px;
  --f7-message-bubble-font-size: 16px;
  --f7-message-bubble-border-radius: 20px;
  --f7-message-bubble-padding-vertical: 10px;
  --f7-message-bubble-padding-horizontal: 16px;
  --f7-message-typing-indicator-opacity: 0.6;
}
.md,
.md .dark,
.md [class*='color-'] {
  --f7-message-sent-bg-color: var(--f7-md-primary);
  --f7-message-sent-text-color: var(--f7-md-on-primary);
  --f7-message-received-bg-color: var(--f7-md-surface-variant);
  --f7-message-received-text-color: var(--f7-md-on-surface);
  --f7-message-text-header-text-color: var(--f7-md-on-surface-variant);
  --f7-message-text-footer-text-color: var(--f7-md-on-surface-variant);
  --f7-messages-title-text-color: var(--f7-md-on-surface-variant);
  --f7-message-header-text-color: var(--f7-md-on-surface-variant);
  --f7-message-footer-text-color: var(--f7-md-on-surface-variant);
  --f7-message-name-text-color: var(--f7-md-on-surface-variant);
}

範例

messages.html
<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="title">Messages</div>
      </div>
    </div>
    <div class="toolbar messagebar" @messagebar:attachmentdelete=${deleteAttachment}>
      <div class="toolbar-inner">
        <a class="link icon-only" @click=${sheetToggle}>
          <i class="icon f7-icons if-not-md">camera_fill</i>
          <i class="icon material-icons md-only">camera_alt</i>
        </a>
        <div class="messagebar-area">
          <textarea class="resizable" placeholder="Message"></textarea>
        </div>
        <a class="link icon-only demo-send-message-link" @click=${sendMessage}>
          <i class="icon f7-icons if-not-md">arrow_up_circle_fill</i>
          <i class="icon material-icons md-only">send</i>
        </a>
      </div>
      <div class="messagebar-sheet">
        ${images.map((image) => $h`
        <label class="checkbox messagebar-sheet-image" @change=${handleAttachment}>
          <input type="checkbox" />
          <i class="icon icon-checkbox"></i>
          <img src=${image} />
        </label>
        `)}
      </div>
    </div>
    <div class="page-content messages-content">
      <div class="messages">
        <div class="messages-title"><b>Sunday, Feb 9,</b> 12:58</div>
        <div class="message message-sent">
          <div class="message-content">
            <div class="message-bubble">
              <div class="message-text">Hi, Kate</div>
            </div>
          </div>
        </div>
        <div class="message message-sent">
          <div class="message-content">
            <div class="message-bubble">
              <div class="message-text">How are you?</div>
            </div>
          </div>
        </div>
        <div class="message message-received">
          <div class="message-avatar"
            style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-9.jpg)"></div>
          <div class="message-content">
            <div class="message-name">Kate</div>
            <div class="message-bubble">
              <div class="message-text">Hi, I am good!</div>
            </div>
          </div>
        </div>
        <div class="message message-received">
          <div class="message-avatar"
            style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-7.jpg)"></div>
          <div class="message-content">
            <div class="message-name">Blue Ninja</div>
            <div class="message-bubble">
              <div class="message-text">Hi there, I am also fine, thanks! And how are you?</div>
            </div>
          </div>
        </div>
        <div class="message message-sent">
          <div class="message-content">
            <div class="message-bubble">
              <div class="message-text">Hey, Blue Ninja! Glad to see you ;)</div>
            </div>
          </div>
        </div>
        <div class="message message-sent">
          <div class="message-content">
            <div class="message-bubble">
              <div class="message-text">Hey, look, cutest kitten ever!</div>
            </div>
          </div>
        </div>
        <div class="message message-sent">
          <div class="message-content">
            <div class="message-bubble">
              <div class="message-image">
                <img src="https://cdn.framework7.io/placeholder/cats-200x260-4.jpg"
                  style="width:200px; height: 260px" />
              </div>
            </div>
          </div>
        </div>
        <div class="message message-received">
          <div class="message-avatar"
            style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-9.jpg)"></div>
          <div class="message-content">
            <div class="message-name">Kate</div>
            <div class="message-bubble">
              <div class="message-text">Nice!</div>
            </div>
          </div>
        </div>
        <div class="message message-received">
          <div class="message-avatar"
            style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-9.jpg)"></div>
          <div class="message-content">
            <div class="message-name">Kate</div>
            <div class="message-bubble">
              <div class="message-text">Like it very much!</div>
            </div>
          </div>
        </div>
        <div class="message message-received">
          <div class="message-avatar"
            style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-7.jpg)"></div>
          <div class="message-content">
            <div class="message-name">Blue Ninja</div>
            <div class="message-bubble">
              <div class="message-text">Awesome!</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  export default (props, { $f7, $el, $on, $ }) => {
    const 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'
    ];
    const 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'
      },
    ];
    const 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!!!',
    ];

    let responseInProgress = false;
    let messagebar;
    let messages;

    const sheetToggle = () => {
      messagebar.sheetToggle();
    }
    const deleteAttachment = (e, index) => {
      var image = messagebar.attachments.splice(index, 1)[0];
      messagebar.renderAttachments();
      checkAttachments();
      // Uncheck in sheet
      var imageIndex = images.indexOf(image);
      $el.value.find('.messagebar-sheet .checkbox').eq(imageIndex).find('input').prop('checked', false);
    }
    const handleAttachment = (e) => {
      var index = $(e.target).parents('label.checkbox').index();
      var image = images[index];
      if (e.target.checked) {
        // Add to attachments
        messagebar.attachments.unshift(image)
      } else {
        // Remove from attachments
        messagebar.attachments.splice(messagebar.attachments.indexOf(image), 1);
      }
      messagebar.renderAttachments();
      checkAttachments();
    }
    const checkAttachments = () => {
      if (messagebar.attachments.length > 0) {
        messagebar.attachmentsShow();
        messagebar.setPlaceholder('Add comment or Send');
      } else {
        messagebar.attachmentsHide();
        messagebar.setPlaceholder('Message');
      }
    }
    const sendMessage = () => {
      var text = messagebar.getValue().replace(/\n/g, '<br />').trim();
      var messagesToSend = [];
      messagebar.attachments.forEach(function (attachment) {
        var size = attachment.split('placeholder/cats-')[1].split('-')[0].split('x');
        messagesToSend.push({
          image: '<img src="' + attachment + '" style="width: ' + (size[0] / 2) + 'px; height: ' + (size[1] / 2) + 'px">'
        });
      });
      if (text.trim().length) {
        messagesToSend.push({
          text: text
        });
      }
      // Reset attachments
      messagebar.attachments = [];
      checkAttachments();
      // Hide sheet
      messagebar.sheetHide();
      // Uncheck selected images in sheet
      messagebar.$sheetEl.find('input').prop('checked', false);
      // Clear area
      messagebar.clear();
      // Focus area
      if (text.length) messagebar.focus();
      // Exit when nothing to send
      if (!messagesToSend.length) return;
      // Send message
      messages.addMessages(messagesToSend);

      // Mock response
      if (responseInProgress) return;
      responseInProgress = true;
      setTimeout(function () {
        var answer = answers[Math.floor(Math.random() * answers.length)];
        var person = people[Math.floor(Math.random() * people.length)];
        messages.showTyping({
          header: person.name + ' is typing',
          avatar: person.avatar
        });
        setTimeout(function () {
          messages.addMessage({
            text: answer,
            type: 'received',
            name: person.name,
            avatar: person.avatar
          });
          messages.hideTyping();
          responseInProgress = false;
        }, 4000);
      }, 1000);
    }

    $on('pageInit', () => {
      messagebar = $f7.messagebar.create({
        el: $el.value.find('.messagebar'),
        attachments: []
      });
      messages = $f7.messages.create({
        el: $el.value.find('.messages'),
        firstMessageRule: function (message, previousMessage, nextMessage) {
          if (message.isTitle) return false;
          if (!previousMessage || previousMessage.type !== message.type || previousMessage.name !== message.name) return true;
          return false;
        },
        lastMessageRule: function (message, previousMessage, nextMessage) {
          if (message.isTitle) return false;
          if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
          return false;
        },
        tailMessageRule: function (message, previousMessage, nextMessage) {
          if (message.isTitle) return false;
          if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
          return false;
        }
      });
    })
    $on('pageBeforeRemove', () => {
      messagebar.destroy()
      messages.destroy()
    })



    return $render;
  };

</script>