# Notification 通知菜单

# 概述

深度封装的通知菜单,极简单的配置即可完成复杂的通知显示业务,功能丰富。
常用在导航工具栏上,作为整个产品统一的通知中心。

# 代码示例

通知图标
通常用在导航工具栏上。该示例为最简只显示未读提示。
5
<template>
    <Notification :count="5" />
</template>
<script>
    export default {
        
    }
</script>
Expand Copy
通知菜单
通知组件共有 3 部分:
  • Notification:外层,可设置总未读数 (设置 auto-count 可以自动判断未读数) 等内容
  • NotificationTab:页签,主要处理加载逻辑,比如加载更多、清空 (或标记未读)、为空的设置等
  • NotificationItem:单条通知,内置了丰富的配置,零 CSS 即可满足常用业务场景,当然,它本身也是个 slot,内容完全可以自定义
<template>
    <Notification
        auto-count
        @on-load-more="handleLoadMore"
        @on-clear="handleClear"
    >
        <NotificationTab
            title="通知"
            name="message"
            :count="unreadMessage"
            :loaded-all="messageList.length >= 15"
            :loading="messageLoading"
            :scroll-to-load="false"
        >
            <NotificationItem
                v-for="(item, index) in messageList"
                :key="index"
                :title="item.title"
                :icon="item.icon"
                :icon-color="item.iconColor"
                :time="item.time"
                :read="item.read"
            />
        </NotificationTab>
        <NotificationTab
            title="关注"
            name="follow"
            :count="unreadFollow"
            :loaded-all="followList.length >= 15"
            :loading="followLoading"
            :scroll-to-load="false"
        >
            <NotificationItem
                v-for="(item, index) in followList"
                :key="index"
                :avatar="item.avatar"
                :title="item.title"
                :time="item.time"
                :read="item.read"
            />
        </NotificationTab>
        <NotificationTab
            title="待办"
            name="todo"
            :count="unreadTodo"
            :loaded-all="todoList.length >= 15"
            :loading="todoLoading"
            :scroll-to-load="false"
        >
            <NotificationItem
                v-for="(item, index) in todoList"
                :key="index"
                :title="item.title"
                :content="item.content"
                :tag="item.tag"
                :tag-props="item.tagProps"
                :read="item.read"
            />
        </NotificationTab>
    </Notification>
</template>
<script>
    export default {
        data () {
            return {
                messageBaseList: [
                    {
                        icon: 'md-mail',
                        iconColor: '#3391e5',
                        title: '蒂姆·库克回复了你的邮件',
                        read: 1,
                        time: 1557297198
                    },
                    {
                        icon: 'md-home',
                        iconColor: '#87d068',
                        title: '乔纳森·伊夫邀请你参加会议',
                        read: 0,
                        time: 1557297198
                    },
                    {
                        icon: 'md-information',
                        iconColor: '#fe5c57',
                        title: '斯蒂夫·沃兹尼亚克已批准了你的休假申请',
                        read: 1,
                        time: 1557297198
                    },
                    {
                        icon: 'md-star',
                        iconColor: '#ff9900',
                        title: '史蒂夫·乔布斯收藏了你的文章',
                        read: 1,
                        time: 1557297198
                    },
                    {
                        icon: 'md-people',
                        iconColor: '#f06292',
                        title: '比尔·费尔南德斯通过了你的好友申请',
                        read: 1,
                        time: 1557297198
                    }
                ],
                followBaseList: [
                    {
                        avatar: 'https://dev-file.iviewui.com/BbnuuEiM0QXNPHVCvb3E2AFrawIjCkqW/avatar',
                        title: '史蒂夫·乔布斯 关注了你',
                        read: 1,
                        time: 1557299299
                    },
                    {
                        avatar: 'https://dev-file.iviewui.com/zhj85zgAfEjChCNIKT1LQENUIOyOYCaX/avatar',
                        title: '斯蒂夫·沃兹尼亚克 关注了你',
                        read: 1,
                        time: 1557299299
                    },
                    {
                        avatar: 'https://dev-file.iviewui.com/TkH54UozsINlex15TAMI00GElsfsKSiC/avatar',
                        title: '乔纳森·伊夫 关注了你',
                        read: 0,
                        time: 1557299299
                    },
                    {
                        avatar: 'https://dev-file.iviewui.com/xrzbBR99F6tYsDJPLNrvwhllowbuL7Gw/avatar',
                        title: '蒂姆·库克 关注了你',
                        read: 1,
                        time: 1557299299
                    },
                    {
                        avatar: 'https://dev-file.iviewui.com/bgrngoUb9A6UQ2kAwBFtnSNzhrh2qj1O/avatar',
                        title: '比尔·费尔南德斯 关注了你',
                        read: 1,
                        time: 1557299299
                    }
                ],
                todoBaseList: [
                    {
                        title: '2019 下半年 OKR',
                        content: '需要在 2019-06-14 之前完成',
                        tag: '未开始',
                        tagProps: {
                            color: 'default'
                        },
                        read: 1
                    },
                    {
                        title: '公孙离的面试评审',
                        content: '需要在 2019-06-14 之前完成',
                        tag: '即将到期',
                        tagProps: {
                            color: 'red'
                        },
                        read: 0
                    },
                    {
                        title: 'iView 三周年生日会',
                        content: '需要在 2019-07-28 之前完成',
                        tag: '进行中',
                        tagProps: {
                            color: 'blue'
                        },
                        read: 1
                    },
                    {
                        title: 'iView 三周年生日会',
                        content: '需要在 2019-07-28 之前完成',
                        tag: '进行中',
                        tagProps: {
                            color: 'blue'
                        },
                        read: 1
                    }
                ],
                messageList: [],
                followList: [],
                todoList: [],
                messageLoading: false,
                followLoading: false,
                todoLoading: false,
            }
        },
        computed: {
            unreadMessage () {
                let unread = 0;
                this.messageList.forEach(item => {
                    if (!item.read) unread++;
                });
                return unread;
            },
            unreadFollow () {
                let unread = 0;
                this.followList.forEach(item => {
                    if (!item.read) unread++;
                });
                return unread;
            },
            unreadTodo () {
                let unread = 0;
                this.todoList.forEach(item => {
                    if (!item.read) unread++;
                });
                return unread;
            }
        },
        methods: {
            handleLoadMore (tab) {
                this.loadMore(tab.name);
            },
            loadMore (type) {
                if (this[`${type}Loading`]) return;
                this[`${type}Loading`] = true;
                setTimeout(() => {
                    this[`${type}List`] = this[`${type}List`].concat([...this[`${type}BaseList`]]);
                    this[`${type}Loading`] = false;
                }, 1000);
            },
            handleClear (tab) {
                this.clearUnread(tab.name);
            },
            clearUnread (type) {
                this[`${type}List`] = this[`${type}List`].map(item => {
                    item.read = 1;
                    return item;
                });
            }
        },
        mounted () {
            this.messageList = [...this.messageBaseList];
            this.followList = [...this.followBaseList];
            this.todoList = [...this.todoBaseList];
        }
    }
</script>
Expand Copy
自动加载更多
给 NotificationTab 设置属性 scroll-to-load 可以在滚动至底部时自动加载更多通知。
<template>
    <Notification
        auto-count
        @on-load-more="handleLoadMore"
        @on-clear="handleClear"
    >
        <NotificationTab
            title="通知"
            name="message"
            :count="unreadMessage"
            :loading="messageLoading"
        >
            <NotificationItem
                v-for="(item, index) in messageList"
                :key="index"
                :title="item.title"
                :icon="item.icon"
                :icon-color="item.iconColor"
                :time="item.time"
                :read="item.read"
            />
        </NotificationTab>
    </Notification>
</template>
<script>
    export default {
        data () {
            return {
                messageBaseList: [
                    {
                        icon: 'md-mail',
                        iconColor: '#3391e5',
                        title: '蒂姆·库克回复了你的邮件',
                        read: 1,
                        time: 1557297198
                    },
                    {
                        icon: 'md-home',
                        iconColor: '#87d068',
                        title: '乔纳森·伊夫邀请你参加会议',
                        read: 0,
                        time: 1557297198
                    },
                    {
                        icon: 'md-information',
                        iconColor: '#fe5c57',
                        title: '斯蒂夫·沃兹尼亚克已批准了你的休假申请',
                        read: 1,
                        time: 1557297198
                    },
                    {
                        icon: 'md-star',
                        iconColor: '#ff9900',
                        title: '史蒂夫·乔布斯收藏了你的文章',
                        read: 1,
                        time: 1557297198
                    },
                    {
                        icon: 'md-people',
                        iconColor: '#f06292',
                        title: '比尔·费尔南德斯通过了你的好友申请',
                        read: 1,
                        time: 1557297198
                    }
                ],
                messageList: [],
                messageLoading: false,
            }
        },
        computed: {
            unreadMessage () {
                let unread = 0;
                this.messageList.forEach(item => {
                    if (!item.read) unread++;
                });
                return unread;
            }
        },
        methods: {
            handleLoadMore (tab) {
                this.loadMore(tab.name);
            },
            loadMore (type) {
                if (this[`${type}Loading`]) return;
                this[`${type}Loading`] = true;
                setTimeout(() => {
                    this[`${type}List`] = this[`${type}List`].concat([...this[`${type}BaseList`]]);
                    this[`${type}Loading`] = false;
                }, 1000);
            },
            handleClear (tab) {
                this.clearUnread(tab.name);
            },
            clearUnread (type) {
                this[`${type}List`] = this[`${type}List`].map(item => {
                    item.read = 1;
                    return item;
                });
            }
        },
        mounted () {
            this.messageList = [...this.messageBaseList];
        }
    }
</script>
Expand Copy
通知为空
当没有通知内容时,会显示默认的占位图和文案,当然,这些都可以自定义。
<template>
    <Notification>
        <NotificationTab title="通知" name="message" :count="0">
            <NotificationItem v-for="(item, index) in messageList" :key="index" />
        </NotificationTab>
        <NotificationTab title="关注" name="follow" :count="0">
            <div slot="empty">
                通知为空,是可以自定义的
            </div>
            <NotificationItem v-for="(item, index) in messageList" :key="index" />
        </NotificationTab>
    </Notification>
</template>
<script>
    export default {
        data () {
            return {
                messageList: []
            }
        }
    }
</script>
Expand Copy

# API

# Notification props

属性 说明 类型 默认值
count 图标上的消息总数 Number -
auto-count 是否根基 Tab 的 count 自动计算 count,开启,则 count 无效 Boolean false
count-type Tab 的 count 是纯文本显示,还是 Badge 显示,可选值为 text 或 badge String text
icon 图标 (铃铛),也有同名 slot String md-notifications-outline
transfer 是否将弹层放置于 body 内 Boolean false
placement 弹窗的展开方向,支持 12 个方向 String bottom
badge-props 额外的 Badge 配置 Object {}
clear-close 点击清空按钮后关闭通知菜单 Boolean false
tab 当前显示哪一个面板,基于 Tab 的 name String -
wide 开启后,宽度是100%而不是默认的300px,在移动端等环境下使用较好 Boolean false
locale 默认文案 Object {
loadedAll: '加载完毕',
loading: '加载中...',
loadMore: '加载更多',
clear: '清空'
}

# Notification Events

事件名 说明 返回值
on-clear 点击清空时触发,返回 tab 内容,包含 name 和 title tab
on-load-more 点击加载更多时触发,返回 tab 内容 tab
on-tab-change 切换页签时触发,返回 tab 内容 tab
on-item-click 点击 item 项时触发,返回 tab 和 item(其中 item 返回的是 attrs 而不是 props) tab, item
on-visible-change 菜单显示状态改变时调用 state

# Notification Slots

名称 说明
icon 自定义铃铛
extra 底部附加信息,常见有设置、查看全部等功能

# NotificationTab props

属性 说明 类型 默认值
count 当前 tab 的消息总数 Number -
title 消息分类的页签标题,必填 String -
name 当前 tab 标识 String -
empty-text 没有通知的文案 String 目前没有通知
empty-image 没有通知的图标 String https://file.iviewui.com/iview-pro/icon-no-message.svg
loaded-all 已加载完所有消息 Boolean true
show-loaded-all 是否显示已加载完所有消息 Boolean true
loading 当前 Tab 的加载状态 Boolean false
scroll-to-load 是否允许滚动到底部自动加载 Boolean true
show-clear 是否显示清空按钮 Boolean true
show-clear-icon 是否显示清空按钮前的图标 Boolean true

# NotificationTab Slots

名称 说明
top 顶部,比如:这些人最近关注了你
empty 自定义通知为空时的内容
loading 自定义加载中的内容
load-more 自定义加载更多的内容
loaded-all 自定义已完成加载的内容
clear 自定义清空全部的内容

# NotificationItem props

属性 说明 类型 默认值
row-props Row 的配置,默认垂直居中 Object {
type: 'flex',
justify: 'center',
align: 'middle'
}
read 是否已读,1 和 true 是已读,0 和 false 是未读 Boolean, Number false
icon 小图标 String -
custom-icon 自定义小图标 String -
icon-color 小图标的颜色 String -
icon-size 小图标尺寸,可选值为 small、default、large String default
avatar 头像地址 String -
avatar-shape 头像形状,可选值为 circle 或 square String circle
title 标题 String -
content 内容 String -
time 时间,会转为相对时间 Number, Date, String -
time-props 相对时间配置 Object {}
tag 标签 String -
tag-props 标签配置 Object {}
click-close 点击列表项关闭通知菜单 Boolean false

# NotificationItem Events

事件名 说明 返回值
on-item-click 点击 item 项时触发,返回 item(item 返回的是 attrs 而不是 props) item

# NotificationItem Slots

名称 说明
default 如果想完全自定义 NotificationItem 内容,可以使用默认的 slot,否则不建议覆盖此 slot 内容
title 自定义标题
content 自定义内容
time 自定义时间