赞
踩
<template>
<grid class="grid-demo" isScale>
<grid-item class="grid-demo-item">1</bg-grid-item>
<grid-item class="grid-demo-item">2</bg-grid-item>
<grid-item class="grid-demo-item">3</bg-grid-item>
<grid-item class="grid-demo-item">4</bg-grid-item>
<grid-item class="grid-demo-item">5</bg-grid-item>
<grid-item class="grid-demo-item">6</bg-grid-item>
<grid-item class="grid-demo-item">7</bg-grid-item>
<grid-item class="grid-demo-item">8</bg-grid-item>
<grid-item class="grid-demo-item">9</bg-grid-item>
</grid>
<template>
<style scoped>
.grid-demo{
background-color: #2b2d42;
}
.grid-demo-item{
color: #fff;
background-color: #41497D;
}
</style>
<script setup>
import {ref, inject, watch} from 'vue'
defineOptions({
name: 'GridItem'
})
const isScale = inject("isScale");
// 自适应高度等于宽度
const liDom = ref();
const height = ref("");
watch(() => liDom.value, (dom) => {
if (isScale) {
height.value = dom.clientWidth + "px";
} else {
height.value = "";
}
}, {
deep: true,
});
</script>
<template>
<li class="grid-layout-item" ref="liDom">
<slot />
</li>
</template>
<style scoped lang="scss">
.grid-layout-item {
float: left;
list-style: none;
height: v-bind(height);
line-height: v-bind(height);
text-align: center;
vertical-align: middle;
margin-bottom: 10px;
}
</style>
<script setup>
import {useSlots, provide, ref, computed, watch, onMounted} from "vue";
defineOptions({
name: "Grid"
})
const props = defineProps({
/** 间隔 */
gutter: {type: Number, default: 10},
/** 列数 */
column: {type: Number, default: 3},
/** 约束宽=高 */
isScale: {type: Boolean, default: false},
})
provide('isScale', props.isScale)
// 插槽列表
const slotList = useSlots()?.default() || []
// 渲染列表
const renderList = ref([])
const columnNum = ref(props.column || 1)
// 尾行编号
const lastRow = ref(0);
const gridStyles = computed(() => {
return {
overflow: "hidden",
padding: `${props.gutter}px`,
margin: "0px"
}
})
function _SlotListHandler(el, index) {
if (typeof el.type === "object" && el.type.name === "GridItem") {
if (!el.props) el.props = {};
if (!el.props.style) el.props.style = {};
el.props.style.width = `calc((100% - ${props.gutter * (columnNum.value - 1)}px) / ${columnNum.value})`;
// 右边距设置和下边距设置
el.props.style.marginRight = `${props.gutter}px`;
el.props.style.marginBottom = `${props.gutter}px`;
// 每行最后一个不加右边距
if ((index + 1) % columnNum.value === 0) el.props.style.marginRight = "0px";
// 最后一行不加下边距
if ((index + 1) >= lastRow.value * columnNum.value){
el.props.style.marginBottom = 0;
}else{
el.props.style.marginBottom = `${props.gutter}px`
}
return el;
} else if (typeof el.type === 'symbol') {
let _list = [];
el.children.forEach((childrenEl, childrenIndex) => {
_list.push(_SlotListHandler(childrenEl, childrenIndex));
})
return _list;
}
return false;
}
function renderSlot(list) {
renderList.value = [];
lastRow.value = Math.ceil((list[0]?.children||[]).length / columnNum.value) - 1;
list.forEach((el, index) => {
let _e = _SlotListHandler(el, index);
if (_e instanceof Array) {
renderList.value.push(..._e);
} else if (typeof _e === 'object') {
renderList.value.push(_e);
}
});
}
watch(
() => slotList,
(list) => {
console.log('list:', list)
renderSlot(list);
},
{deep: true}
)
onMounted(()=>{
renderSlot(slotList);
})
</script>
<template>
<div class="grid-layout">
<ul :style="gridStyles">
<component v-for="(element, key) in renderList" :key="key"
:is="element"/>
</ul>
</div>
</template>
<style scoped lang="scss">
.grid-layout {
list-style: none;
}
</style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。