shu-c-view
Version:
rollup 打包vue@2.7组件库框架
337 lines (335 loc) • 9.1 kB
JavaScript
/**
* @desc 菜单按钮
*/
import _has from 'lodash/has';
import _isEmpty from 'lodash/isEmpty';
import _find from 'lodash/find';
import _isNil from 'lodash/isNil';
import _set from 'lodash/set';
import _omit from 'lodash/omit';
import _isArray from 'lodash/isArray';
import _includes from 'lodash/includes';
import _get from 'lodash/get';
import { devConsole, apply } from '../helper/util.js';
const BaseMenuButton = {
name: 'BaseMenuButton',
inheritAttrs: false,
props: {
props: {
type: Object,
default() {
return {};
}
},
// 一个可选添加的CSS样式类,加入到组件的容器上
ctCls: {
type: String
},
// 标题名称
dropdownLabel: {
type: String,
default: '下拉菜单'
},
// 左边的icon
prefixIcon: {
type: String
},
// 触发下拉的行为 hover, click
trigger: {
type: String,
default: 'click'
},
// 数据
options: {
type: Array
},
// 是否显示所有分割线
isShowDivided: {
type: Boolean,
default: false
},
// 图标的尺寸
svgSize: {
type: String,
default: '16px'
},
// svg 图标集合 [{name: 'studyState', component: studyState}]
svgIcons: {
type: Array,
default() {
return [];
}
},
// 当前激活菜单的 index
defaultActive: {
type: String
},
// 当前激活菜单的文字颜色
activeTextColor: {
type: String,
default: '#409EFF'
}
},
watch: {
dropdownLabel(val) {
if (val !== this.curDropdownLabel) {
this.curDropdownLabel = val;
}
}
},
data() {
this.oData = {};
this.defaultProps = {
children: 'children',
label: 'label',
value: 'value',
icon: 'icon'
};
return {
cascaderValue: [],
curDropdownLabel: this.dropdownLabel
};
},
created() {
if (!_isNil(this.props)) {
apply(this.defaultProps, this.props);
}
},
mounted() {
setTimeout(() => {
if (!_isNil(this.defaultActive)) {
const checkedData = _get(this.oData, this.defaultActive);
if (!_isNil(checkedData)) {
this.$nextTick(() => {
this.curDropdownLabel = _get(checkedData, this.defaultProps.label);
});
}
}
}, 0);
},
methods: {
/**
* @desc 根据菜单的 index 获取对应的路由路径
* @param {String} index - 菜单对应的 index 属性
*/
getRouterPath(index) {
return _get(this.oData, index);
},
/**
* @desc 创建元素自身
* @param {*} self - 元素自身
* @returns VNode
*/
createElSelf(self) {
const h = this.$createElement;
/* return h(
{
render(h) {
return this.$scopedSlots.default();
}
},
{ scopedSlots: { default: props => self } },
[]
); */
return h('base-render-self', { props: { self } });
},
/**
* @desc 创建图表
*/
createIcon(iconUrl) {
const h = this.$createElement;
if (/\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif)$/.test(iconUrl)) {
return h('img', {
style: { marginRight: '5px' },
attrs: { src: iconUrl, width: this.svgSize, height: this.svgSize }
});
}
if (iconUrl.indexOf('symbol-') !== -1) {
return h(
'base-svg-icon',
{
style: { marginRight: '5px' },
props: {
size: this.svgSize,
iconname: iconUrl.replace('symbol-', '')
}
},
[]
);
}
if (_includes(iconUrl, 'svg-')) {
// svg图
const curUrl = iconUrl.replace('svg-', '');
const svgObj = _find(this.svgIcons, o => o.name === curUrl);
if (!_isNil(svgObj)) {
return this.$createElement(_get(svgObj, 'component', 'span'), {
style: {
width: this.svgSize,
height: this.svgSize,
marginRight: '5px'
}
});
}
}
return h('i', { class: iconUrl }, []);
},
/**
* @desc 创建 menu 的内部子元素
* @private
* @method
*/
createMenuElements() {
const h = this.$createElement;
const nodes = [];
for (let i = 0, len = this.options.length; i < len; i++) {
const option = this.options[i];
const index = `1-${i}`;
const disabled = option.disabled;
if (
_has(option, this.defaultProps.children) &&
!_isEmpty(_get(option, this.defaultProps.children, []))
) {
if (!_isNil(option[this.defaultProps.children])) {
nodes.push(this.createElSubMenu(option, index));
}
} else {
const menuItem = h('el-menu-item', { props: { index, disabled } }, [
_has(option, this.defaultProps.icon)
? this.createIcon(option[this.defaultProps.icon])
: h(),
this.createElSelf(option[this.defaultProps.label])
]);
nodes.push(menuItem);
}
_set(
this.oData,
index,
JSON.parse(
JSON.stringify(_omit(option, [this.defaultProps.children]))
)
);
}
return nodes;
},
/**
* @desc 创建 el-submenu
*/
createElSubMenu(option, index) {
const h = this.$createElement;
const nodes = [];
const aOptionData = option[this.defaultProps.children];
for (let i = 0, len = aOptionData.length; i < len; i++) {
const childOption = aOptionData[i];
const innerIndex = `${index}-${i}`;
if (
_has(childOption, this.defaultProps.children) &&
!_isEmpty(_get(childOption, this.defaultProps.children, []))
) {
const sumMenu = this.createElSubMenu(childOption, innerIndex);
nodes.push(sumMenu);
} else {
const menuItem = h(
'el-menu-item',
{ props: { index: innerIndex, disabled: childOption.disabled } },
[
_has(childOption, this.defaultProps.icon)
? this.createIcon(childOption[this.defaultProps.icon])
: h(),
this.createElSelf(childOption[this.defaultProps.label])
]
);
nodes.push(menuItem);
}
_set(
this.oData,
innerIndex,
JSON.parse(
JSON.stringify(_omit(childOption, [this.defaultProps.children]))
)
);
}
return h('el-submenu', { props: { index } }, [
h('template', { slot: 'title' }, [
_has(option, this.defaultProps.icon)
? this.createIcon(option[this.defaultProps.icon])
: h(),
this.createElSelf(option[this.defaultProps.label])
]),
nodes
]);
}
},
render(h) {
return h(
'div',
{
class: {
'base-menu-button': true,
[this.ctCls]: !!this.ctCls
}
},
[
h(
'el-menu',
{
props: {
mode: 'horizontal',
'menu-trigger': this.trigger,
'unique-opened': true,
'default-active': this.defaultActive,
'active-text-color': this.activeTextColor
},
on: {
select: (index, indexPath) => {
const data = JSON.parse(
JSON.stringify(_get(this.oData, index))
);
data.index = index;
data.indexPath = indexPath;
this.$emit('select', data);
}
}
},
[
h(
'el-submenu',
{
props: {
index: '0',
'popper-append-to-body': true,
'popper-class': 'base-menu--horizontal_popup'
}
},
[
h('template', { slot: 'title' }, [
_isNil(this.prefixIcon)
? h()
: h(
'i',
{ class: `${this.prefixIcon} base-drop-down_prefix` },
[]
),
this.createElSelf(this.curDropdownLabel)
]),
this.createMenuElements()
]
)
]
)
]
);
}
};
BaseMenuButton.install = function(Vue, ElComponents) {
// 用于按需加载的时候独立使用
devConsole(`按需加载独立组件:${BaseMenuButton.name}`);
if (_isArray(ElComponents) && !_isEmpty(ElComponents)) {
for (let i = 0; i < ElComponents.length; i++) {
if (ElComponents[i].name !== BaseMenuButton.name) {
Vue.use(ElComponents[i]);
}
}
}
Vue.component(BaseMenuButton.name, BaseMenuButton);
};
export { BaseMenuButton };