shu-c-view
Version:
rollup 打包vue@2.7组件库框架
402 lines (400 loc) • 11.8 kB
JavaScript
/**
* @desc 菜单水平平铺右侧显示更多下拉菜单-组件
* 获取外层宽度,一行展示不下用>>展示剩余的数据
*/
import jQuery from 'jquery';
import _isEmpty from 'lodash/isEmpty';
import _isArray from 'lodash/isArray';
import _get from 'lodash/get';
import _map from 'lodash/map';
import _toNumber from 'lodash/toNumber';
import _find from 'lodash/find';
import _has from 'lodash/has';
// import _debounce from 'lodash/debounce';
import { devConsole } from '../helper/util.js';
const BaseHorizontalMenu = {
name: 'BaseHorizontalMenu',
inheritAttrs: false,
props: {
// 高度 px
height: {
type: Number,
default: 40
},
// 数据项
listGroup: {
type: Array,
default() {
return [];
}
},
displayField: {
type: String,
default: 'name'
},
valueField: {
type: String,
default: 'id'
},
// 触发方式
viewMoreTrigger: {
type: String,
default: 'click',
validator(value) {
return ['click', 'hover'].indexOf(value) !== -1;
}
},
linkCls: {
type: String
},
viewMoreWrapCls: {
type: String
},
viewMoreDropdownCls: {
type: String
},
// 选中的样式
activeCls: {
type: String,
default: 'selected'
}
},
data() {
this.defaults = {
mainClassName: 'pgwMenu',
viewMoreEnabled: true,
viewMoreLabel: '更多'
};
this.wrapCls = 'base-horizontal-menu';
this.ulLinkCls = 'base-horizontal-menu__links';
this.viewMoreCls = 'base-horizontal-menu__view-more';
this.viewMoreUlCls = 'base-horizontal-menu__view-more-links';
this.horizontalMenuRef = null;
this.defaultActive = 0;
return {
// defaultActive: 0 // 默认选中第一个
};
},
mounted() {
const $ = jQuery;
this.horizontalMenuRef = this.$refs.horizontalMenuRef;
/* this.debouncedGetAnswer = _debounce(() => {
$(this.horizontalMenuRef).css('overflow', 'hidden');
this.checkLink();
}, 500); */
window.addEventListener('resize', this.resizeHandle);
$(document).on('click', this.disableEvent);
if (this.viewMoreTrigger === 'click') {
$(this.horizontalMenuRef)
.find(`.${this.viewMoreCls}`)
.on('click', this.enableViewMoreDropDown);
}
if (this.viewMoreTrigger === 'hover') {
$(this.horizontalMenuRef)
.find(`.${this.viewMoreCls}`)
.hover(this.enableViewMoreDropDown);
}
setTimeout(() => {
const group = _find(this.listGroup, (item, index) => {
return index === this.defaultActive;
});
if (group) {
this.selectHandle(
_get(group, this.displayField),
_get(group, this.valueField),
this.defaultActive
);
}
}, 0);
},
beforeDestroy() {
const $ = jQuery;
// this.debouncedGetAnswer.cancel(); // 组件卸载时清除掉防抖计时器
// window.removeEventListener('resize', this.debouncedGetAnswer);
window.removeEventListener('resize', this.resizeHandle);
$(document).off('click', this.disableEvent);
},
methods: {
resizeHandle() {
const $ = jQuery;
$(this.horizontalMenuRef).css('overflow', 'hidden');
this.disableEvent();
this.checkLink();
},
setActive(index) {
this.defaultActive = index;
const link = this.setSelectedHandle(index);
const { display, value } = link.data();
this.selectHandle(display, value, index);
},
getActive() {
return this.defaultActive;
},
// `更多`展开下拉ul
enableViewMoreDropDown(e) {
const $ = jQuery;
if (
$(this.horizontalMenuRef)
.find(`.${this.viewMoreCls} :first-child`)
.hasClass('active')
) {
this.disableViewMoreDropDown();
return false;
}
$(this.horizontalMenuRef)
.find(`.${this.viewMoreCls} :first-child`)
.addClass('active');
$(this.horizontalMenuRef)
.find(`.${this.viewMoreCls} > ul`)
.show();
e.stopPropagation();
e.preventDefault();
return false;
},
disableViewMoreDropDown() {
const $ = jQuery;
if (
$(this.horizontalMenuRef)
.find(`.${this.viewMoreCls} :first-child`)
.hasClass('active')
) {
$(this.horizontalMenuRef)
.find(`.${this.viewMoreCls} :first-child`)
.removeClass('active');
$(this.horizontalMenuRef)
.find(`.${this.viewMoreCls} > ul`)
.hide();
}
},
disableEvent() {
// 隐藏下拉更多的ul
this.disableViewMoreDropDown();
},
createLinks(h) {
const that = this;
const linkNodes = _map(this.listGroup, (link, index) => {
const displayText = _get(link, this.displayField);
const valueText = _get(link, this.valueField);
const oData = {
'data-display': displayText,
'data-value': valueText,
'data-index': index
};
return h(
'li',
{
attrs: oData,
class: {
selected: index === this.defaultActive,
linkCls: this.linkCls
},
style: { lineHeight: `${this.height}px` },
key: valueText
},
[
_has(that.$scopedSlots, 'default')
? h(
{
render() {
return that.$scopedSlots.default(link);
}
},
{
attrs: oData
}
)
: displayText
]
);
});
setTimeout(() => {
this.$nextTick(this.checkLink);
}, 100);
return linkNodes;
},
checkLink() {
const $ = jQuery;
const hMenuPlugin = $(this.horizontalMenuRef);
const pluginMaxWidth = hMenuPlugin.width();
const viewMoreLinkWidth = hMenuPlugin
.find(`.${this.viewMoreCls}`)
.outerWidth(true);
const contentWidth = this.getContentWidth(hMenuPlugin);
if (contentWidth > pluginMaxWidth) {
this.switchMenu(
'viewMore',
hMenuPlugin,
viewMoreLinkWidth,
pluginMaxWidth
);
} else {
this.switchMenu('normal', hMenuPlugin);
}
hMenuPlugin.css('overflow', '');
},
getContentWidth(plugin) {
const $ = jQuery;
let menuContentWidth = 0;
plugin.find(`.${this.ulLinkCls} > li`).show();
plugin.find(`.${this.ulLinkCls} > li`).each(function() {
menuContentWidth += $(this).outerWidth(true);
});
return menuContentWidth;
},
switchMenu(type, plugin, viewMoreLinkWidth, pluginMaxWidth) {
const $ = jQuery;
const that = this;
if (type === 'viewMore') {
// 更多模式
let viewMoreMenuWidth = viewMoreLinkWidth;
plugin.find(`.${this.viewMoreCls} > ul > li`).remove();
plugin
.find(`.${this.ulLinkCls} > li`)
.show()
.each(function() {
if (viewMoreMenuWidth + $(this).outerWidth(true) < pluginMaxWidth) {
viewMoreMenuWidth += $(this).outerWidth(true);
} else {
if (plugin.find(`.${that.viewMoreCls} > ul > li`).length === 0) {
viewMoreMenuWidth += $(this).outerWidth(true);
}
plugin.find(`.${that.viewMoreUlCls}`).append(
$(this)
.clone()
.show()
);
$(this).hide();
}
});
if (plugin.find(`.${this.viewMoreCls}`).css('display') === 'none') {
plugin.find(`.${this.viewMoreCls}`).show();
}
}
if (type === 'normal') {
// 普通模式没有`更多`
plugin.find(`.${this.ulLinkCls} > li`).show();
plugin.find(`.${this.ulLinkCls}`).show();
plugin.find(`.${this.viewMoreCls}, .${this.viewMoreCls}> ul`).hide();
plugin.find(`.${this.viewMoreCls}> ul > li`).remove();
}
},
setSelectedHandle(index) {
const $ = jQuery;
let linkNode = null;
const selectedLink = $(this.horizontalMenuRef)
.find(`.${this.ulLinkCls} > li`)
.eq(index);
const oldSelectedLink = $(this.horizontalMenuRef)
.find(`.${this.ulLinkCls}`)
.find(`.${this.activeCls}`);
if (oldSelectedLink.length !== 0) {
oldSelectedLink.removeClass(this.activeCls);
}
if (selectedLink.length !== 0) {
if (selectedLink.css('display') !== 'none') {
selectedLink.addClass(this.activeCls);
linkNode = selectedLink;
} else {
const hiddenLinks = $(this.horizontalMenuRef)
.find(`.${this.ulLinkCls} > li`)
.not(':hidden');
const selectedIndex = index - hiddenLinks.length;
const viewMoreSelectedLink = $(this.horizontalMenuRef)
.find(`.${this.viewMoreUlCls} > li`)
.eq(selectedIndex);
if (viewMoreSelectedLink.length !== 0) {
$(this.horizontalMenuRef)
.find(`.${this.viewMoreUlCls}`)
.find(`.${this.activeCls}`)
.removeClass(this.activeCls);
viewMoreSelectedLink.addClass(this.activeCls);
linkNode = viewMoreSelectedLink;
}
}
}
return linkNode;
},
selectHandle(displayText, valueText, index) {
this.defaultActive = index;
this.$emit(
'select',
{
[this.displayField]: displayText,
[this.valueField]: valueText
},
_toNumber(index)
);
}
},
render(h) {
return h(
'div',
{
ref: 'horizontalMenuRef',
class: this.wrapCls,
style: { height: `${this.height}px` },
on: {
click: e => {
const { display, value, index } = e.target.dataset;
this.setSelectedHandle(index);
this.selectHandle(display, value, index);
}
}
},
[
h(
'ul',
{
class: this.ulLinkCls
},
this.createLinks(h)
),
h(
'div',
{
class: [this.viewMoreCls, this.viewMoreWrapCls],
style: { display: 'inline-block' }
},
[
_has(this.$slots, 'moreDesc')
? this.$slots.moreDesc
: h(
'a',
{
attrs: { href: 'javascript:void(0)' },
style: { lineHeight: `${this.height}px` }
},
[
this.defaults.viewMoreLabel,
h('i', { class: 'el-icon-caret-bottom' })
]
),
h('ul', {
class: [this.viewMoreUlCls, this.viewMoreDropdownCls],
on: {
click: e => {
const { display, value, index } = e.target.dataset;
this.setSelectedHandle(index);
this.selectHandle(display, value, index);
}
}
})
]
)
]
);
}
};
BaseHorizontalMenu.install = function(Vue, ElComponents) {
// 用于按需加载的时候独立使用
devConsole(`按需加载独立组件:${BaseHorizontalMenu.name}`);
if (_isArray(ElComponents) && !_isEmpty(ElComponents)) {
for (let i = 0; i < ElComponents.length; i++) {
if (ElComponents[i].name !== BaseHorizontalMenu.name) {
Vue.use(ElComponents[i]);
}
}
}
Vue.component(BaseHorizontalMenu.name, BaseHorizontalMenu);
};
export { BaseHorizontalMenu };