UNPKG

shu-c-view

Version:

rollup 打包vue@2.7组件库框架

402 lines (400 loc) 11.8 kB
/** * @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 };