Grid API: grid
<grid clickable>
<grid-item icon="el-icon-phone-outline" text="文字" to="/system/menuManagement" />
<grid-item icon="el-icon-eleme" text="文字" />
<grid-item icon="el-icon-upload" text="文字" />
<grid-item><div>文字</div></grid-item>
</grid>
<!--
* Copyright ©
* #
* @author: zw
* @date: 2022-07-05
-->
<template>
<div :class="[bem(), { 'hairline--top': border && !gutter } ]">
<slot />
</div>
</template>
<script>
import { ParentMixin } from "./mixins";
const isDef = (val) => val !== undefined && val !== null
const isNumeric = (val) => /^\d+(\.\d+)?$/.test(val)
function addUnit(value) {
if (!isDef(value)) return undefined;
value = String(value);
return isNumeric(value) ? value + "px" : value;
}
export default {
name: 'grid',
mixins: [ParentMixin('grid')],
props: {
square: Boolean,
gutter: [Number, String],
iconSize: [Number, String],
direction: { type: String, default: 'vertical' },
clickable: Boolean,
columnNum: { type: [Number, String], default: 4 },
center: { type: Boolean, default: true },
border: { type: Boolean, default: true }
},
methods: {
createBem(name) {
/**
* bem helper
* b() // 'button'
* b('text') // 'button__text'
* b({ disabled }) // 'button button--disabled'
* b('text', { disabled }) // 'button__text button__text--disabled'
* b(['disabled', 'primary']) // 'button button--disabled button--primary'
*/
return function (el, mods) {
function gen(name, mods) {
if (!mods) return '';
if (typeof mods === 'string') return " " + name + "--" + mods;
if (Array.isArray(mods)) return mods.reduce((ret, item) => ret + gen(name, item), '');
return Object.keys(mods).reduce((ret, key) => ret + (mods[key] ? gen(name, key) : ''), '');
}
if (el && typeof el !== 'string') {
mods = el; el = '';
}
el = el ? name + "__" + el : name;
return "" + el + gen(el, mods);
};
}
},
computed: {
style() {
const { gutter } = this;
if (!gutter) return;
return { paddingLeft: addUnit(gutter) };
},
bem() {
return (...cls) => this.createBem(this.$options.name)(...cls);
},
},
// End
}
</script>
<style lang='css' scoped>
.hairline--top {
position: relative;
}
.grid {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
</style>
<!--
* Copyright ©
* #
* @author: zw
* @date: 2022-07-05
-->
<template>
<div :class="bem({square: parent.square})" :style="style">
<div :class="[bem('content', [parent.direction, {center: parent.center, square: parent.square, clickable: parent.clickable, curround: parent.border && parent.gutter}]), { 'hairline': parent.border && !parent.gutter }]" :style="contentStyle" :role="parent.clickable ? 0 : null"
:tabindex="parent.clickable ? 0 : null" @click="onClick">
<slot>
<i :class="[bem('icon'), icon]" />
<span :class="bem('text')">{{text}}</span>
</slot>
</div>
</div>
</template>
<script>
import { ChildrenMixin } from "./mixins";
const isDef = (val) => val !== undefined && val !== null
const isNumeric = (val) => /^\d+(\.\d+)?$/.test(val)
function addUnit(value) {
if (!isDef(value)) return undefined;
value = String(value);
return isNumeric(value) ? value + "px" : value;
}
function isRedundantNavigation(err) {
return err.name === 'NavigationDuplicated' || // compatible with [email protected]
err.message && err.message.indexOf('redundant navigation') !== -1;
}
function route(router, config) {
var to = config.to,
url = config.url,
replace = config.replace;
if (to && router) {
var promise = router[replace ? 'replace' : 'push'](to);
/* istanbul ignore else */
if (promise && promise.catch) {
promise.catch(err => {
if (err && !isRedundantNavigation(err)) {
throw err;
}
});
}
} else if (url) {
replace ? location.replace(url) : location.href = url;
}
}
export default {
name: 'grid-item',
mixins: [ChildrenMixin('grid')],
props: {
url: String,
replace: Boolean,
to: [String, Object],
dot: Boolean,
text: String,
icon: String,
iconPrefix: String,
badge: [Number, String],
// @deprecated
info: [Number, String]
},
mounted() {
},
methods: {
onClick: function onClick(event) {
this.$emit('click', event);
route(this.$router, this);
},
createBem(name) {
/**
* bem helper
* b() // 'button'
* b('text') // 'button__text'
* b({ disabled }) // 'button button--disabled'
* b('text', { disabled }) // 'button__text button__text--disabled'
* b(['disabled', 'primary']) // 'button button--disabled button--primary'
*/
return function (el, mods) {
function gen(name, mods) {
if (!mods) return '';
if (typeof mods === 'string') return " " + name + "--" + mods;
if (Array.isArray(mods)) return mods.reduce((ret, item) => ret + gen(name, item), '');
return Object.keys(mods).reduce((ret, key) => ret + (mods[key] ? gen(name, key) : ''), '');
}
if (el && typeof el !== 'string') {
mods = el; el = '';
}
el = el ? name + "__" + el : name;
return "" + el + gen(el, mods);
};
}
},
computed: {
bem() {
return (...cls) => this.createBem(this.$options.name)(...cls);
},
style() {
var _this$parent = this.parent;
var square = _this$parent.square;
var gutter = _this$parent.gutter;
var columnNum = _this$parent.columnNum;
var percent = 100 / columnNum + "%";
var style = { flexBasis: percent };
if (square) {
style.paddingTop = percent;
} else if (gutter) {
var gutterValue = addUnit(gutter);
style.paddingRight = gutterValue;
if (this.index >= columnNum) {
style.marginTop = gutterValue;
}
}
return style;
},
contentStyle() {
var _this$parent2 = this.parent,
square = _this$parent2.square,
gutter = _this$parent2.gutter;
if (square && gutter) {
var gutterValue = addUnit(gutter);
return { right: gutterValue, bottom: gutterValue, height: 'auto' };
}
return {};
}
},
// End
}
</script>
<style lang='css' scoped>
.grid-item {
position: relative;
box-sizing: border-box;
}
.grid-item--square {
height: 0;
}
.grid-item__icon {
font-size: 28px;
}
.grid-item__icon-wrapper {
position: relative;
}
.grid-item__text {
color: #646566;
font-size: 12px;
line-height: 1.5;
word-break: break-all;
}
.grid-item__icon + .grid-item__text {
margin-top: 8px;
}
.grid-item__content {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
box-sizing: border-box;
height: 100%;
padding: 16px 8px;
background-color: #fff;
}
.grid-item__content::after {
z-index: 1;
border-width: 0 1px 1px 0;
}
.grid-item__content--square {
position: absolute;
top: 0;
right: 0;
left: 0;
}
.grid-item__content--center {
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
.grid-item__content--horizontal {
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row;
}
.grid-item__content--horizontal .grid-item__icon + .grid-item__text {
margin-top: 0;
margin-left: 8px;
}
.grid-item__content--surround::after {
border-width: 1px;
}
.grid-item__content--clickable {
cursor: pointer;
}
.grid-item__content--clickable:active {
background-color: #f2f3f5;
}
</style>
export function ChildrenMixin(_parent, options) {
var _inject, _computed;
if (options === void 0) {
options = {};
}
var indexKey = options.indexKey || 'index';
return {
inject: (_inject = {}, _inject[_parent] = {
default: null
}, _inject),
computed: (_computed = {
parent: function parent() {
if (this.disableBindRelation) {
return null;
}
return this[_parent];
}
}, _computed[indexKey] = function () {
this.bindRelation();
if (this.parent) {
return this.parent.children.indexOf(this);
}
return null;
}, _computed),
watch: {
disableBindRelation: function disableBindRelation(val) {
if (!val) {
this.bindRelation();
}
}
},
mounted: function mounted() {
this.bindRelation();
},
beforeDestroy: function beforeDestroy() {
var _this = this;
if (this.parent) {
this.parent.children = this.parent.children.filter(function (item) {
return item !== _this;
});
}
},
methods: {
bindRelation: function bindRelation() {
if (!this.parent || this.parent.children.indexOf(this) !== -1) {
return;
}
var children = [].concat(this.parent.children, [this]);
sortChildren(children, this.parent);
this.parent.children = children;
}
}
};
}
export function ParentMixin(parent) {
return {
provide: function provide() {
var _ref;
return _ref = {}, _ref[parent] = this, _ref;
},
data: function data() {
return {
children: []
};
}
};
}
function flattenVNodes(vnodes) {
var result = [];
function traverse(vnodes) {
vnodes.forEach(function (vnode) {
result.push(vnode);
if (vnode.componentInstance) {
traverse(vnode.componentInstance.$children.map(function (item) {
return item.$vnode;
}));
}
if (vnode.children) {
traverse(vnode.children);
}
});
}
traverse(vnodes);
return result;
} // sort children instances by vnodes order
export function sortChildren(children, parent) {
var componentOptions = parent.$vnode.componentOptions;
if (!componentOptions || !componentOptions.children) {
return;
}
var vnodes = flattenVNodes(componentOptions.children);
children.sort(function (a, b) {
return vnodes.indexOf(a.$vnode) - vnodes.indexOf(b.$vnode);
});
}
严谨转载