<template>
<my-float :class="classes">
<my-float-item ref="left" float="left" class="my-navbar__left">
<!-- 切换按钮 -->
<span v-if="collapsible" @click="handleTrigger" class="my-navbar__trigger">
<my-icon :name="triggerIcon" svg></my-icon>
</span>
<!-- 品牌区 -->
<div v-if="logo || title" class="my-navbar__brand">
<a :href="href">
<slot name="brand" :title="title" :logo="logo">
<img class="my-navbar__logo" v-if="logo" :src="logo" :alt="title">
<h1 class="my-navbar__title" v-if="title">{{title}}</h1>
</slot>
<span v-if="version" class="my-navbar__version">{{version}}</span>
</a>
</div>
</my-float-item>
<!-- 自定义内容区 -->
<my-float-item v-if="$slots.default" ref="content" float="left" class="my-navbar__content">
<slot></slot>
</my-float-item>
<!-- 菜单区 -->
<my-float-item v-if="menus && menus.length" float="left" class="my-navbar__menu" :style="menuStyle">
<my-menu v-bind="menuOptions" :data="menus" @select="handleSelect">
<template v-if="$scopedSlots['menu-item']" v-slot:title="{item}">
<slot name="menu-item" :item="item"></slot>
</template>
</my-menu>
</my-float-item>
<my-float-item ref="right" float="right" class="my-navbar__right">
<!-- 工具按钮放置区 -->
<div class="my-navbar__actions" :class="[`is-${theme}`]">
<slot name="actions"></slot>
</div>
</my-float-item>
</my-float>
</template>
<script>
/**
* 导航条组件
* @module $ui/components/my-navbar
*/
import {MyFloat, MyFloatItem, MyIcon, MyMenu} from '$ui'
import {addResizeListener, removeResizeListener} from 'element-ui/lib/utils/resize-event'
import defaultLogo from '$ui/assets/myweb.png'
import '$ui/icons/indent'
import '$ui/icons/outdent'
/**
* 插槽
* @member slots
* @property {string} brand 作用域插槽,定义品牌区的logo 和 标题, 参数:logo、title
* @property {string} default 默认插槽,定义额外内容
* @property {string} menu-item 作用域插槽,定义菜单项,参数:item 菜单项对象
* @property {string} actions 定义操作区内容
*/
export default {
name: 'MyNavbar',
components: {
MyFloat,
MyFloatItem,
MyIcon,
MyMenu
},
/**
* 属性参数
* @member props
* @property {string} [logo] logo图片地址
* @property {string} [title] 标题名称,如系统名称
* @property {string} [version] 版本号
* @property {string} [href] 品牌区链接地址,通常设置系统首页
* @property {boolean} [collapsible=false] 显示触发切换折叠按钮
* @property {boolean} [collapsed=false] 折叠,collapsible 为true时有效,支持sync修饰符
* @property {array} [menus] 菜单数据, 项字段参考 my-menu 组件
* @property {object} [menuProps] 菜单组件实例化参数,字段参考 my-menu 组件
* @property {string} [theme=light] 主题,可选值:'light', 'dark', 'primary', 'gradual'
* @property {boolean} [shadow] 显示阴影
*/
props: {
// logo 图片
logo: {
type: String,
default: defaultLogo
},
// 系统名称
title: String,
// 系统版本号
version: String,
// 品牌链接地址
href: {
type: String
},
// 显示触发折叠按钮
collapsible: Boolean,
// 折叠,collapsible 为true时有效
collapsed: Boolean,
// 菜单数据
menus: Array,
// 菜单参数
menuProps: Object,
// 主题
theme: {
type: String,
default: 'light',
validator(val) {
return ['light', 'dark', 'primary', 'gradual', 'black'].includes(val)
}
},
// 显示阴影
shadow: Boolean,
// 是否弹性布局
isFlex: Boolean
},
data() {
return {
leftWidth: 0,
rightWidth: 0,
contentWidth: 0
}
},
computed: {
classes() {
return {
'my-navbar': true,
[`is-${this.theme}`]: !!this.theme,
'is-shadow': this.shadow,
'is-flex': this.isFlex
}
},
triggerIcon() {
return this.collapsed
? 'icon-indent'
: 'icon-outdent'
},
menuOptions() {
return {
...(this.menuProps || {}),
mode: 'horizontal',
theme: this.theme
}
},
menuStyle() {
return {
width: `calc(100% - ${this.leftWidth + this.rightWidth + this.contentWidth}px)`
}
}
},
methods: {
handleTrigger() {
if (!this.collapsible) return
this.$emit('update:collapsed', !this.collapsed)
},
handleSelect(item) {
/**
* 菜单项选中时触发
* @event select
* @param {Object} item 菜单项对象
*/
this.$emit('select', item)
},
updateWidth() {
if (this.$refs.left) {
const rect = this.$refs.left.$el.getBoundingClientRect()
this.leftWidth = rect.width
}
if (this.$refs.right) {
const rect = this.$refs.right.$el.getBoundingClientRect()
this.rightWidth = rect.width
}
if (this.$refs.content) {
const rect = this.$refs.content.$el.getBoundingClientRect()
this.contentWidth = rect.width
}
},
bindEvents() {
if (this.$refs.left) {
addResizeListener(this.$refs.left.$el, this.updateWidth)
}
if (this.$refs.right) {
addResizeListener(this.$refs.right.$el, this.updateWidth)
}
if (this.$refs.content) {
addResizeListener(this.$refs.content.$el, this.updateWidth)
}
}
},
mounted() {
setTimeout(() => {
this.updateWidth()
}, 0)
this.bindEvents()
},
beforeDestroy() {
if (this.$refs.left) {
removeResizeListener(this.$refs.left.$el, this.updateWidth)
}
if (this.$refs.right) {
removeResizeListener(this.$refs.right.$el, this.updateWidth)
}
if (this.$refs.content) {
removeResizeListener(this.$refs.content.$el, this.updateWidth)
}
}
}
</script>