组件使用预览:
<template>
<display-content :column="{ '500': 3, '1000': 5, '1400': 8 }">
<display-item v-for="item in 20" :key="item" class="loops">
自定义内容区域 {{item}}
</display-item>
</display-content>
</template>
<style>
/deep/.loops {
border: #ccc solid 1px;
margin-bottom:10px;
margin-right: 6px;
&:last-child {
margin-right: 0px;
}
}
</style>
组件使用方法:
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
column | 共有两种方式传参 (第二种可配置分辨率) 1.数字 2.对象 { width : number } / { 分辨率: 列数 } 注意事项:Render 处理VNnode 时需要补空白区域, 并复制陈列中最后一个迭代的样式。请慎重单独对某个陈列元素处理margin 属性 | Number / Object | - | 5 |
组件:<display-content>
<script>
import displayItem from './display-item'
export default {
name: 'display-content',
props: ['column'],
components: {
displayItem
},
render (h) {
let nodeList = []
let list = []
let defaultSlots = []
this.$slots.default.forEach(vnode => {
if (list.length === this.columnNum) {
nodeList.push(h('div', { class: ['content'] }, list))
list = []
}
if (vnode.componentOptions && vnode.componentOptions.tag === 'display-item') {
list.push(vnode)
} else {
defaultSlots.push(vnode)
}
})
if (list.length) {
let num = this.columnNum - list.length
let item = list[list.length - 1]
let {classs, styles} = this.getStyle(item)
for (let i = 0; i < num; i++) {
list.push(h('display-item', { staticClass: classs, style: styles }))
}
nodeList.push(h('div', { class: ['content'] }, list))
}
return h('div', {
class: ['main-conetnt']
}, [...nodeList, ...defaultSlots])
},
computed: {
columnNum () {
if (Object.prototype.toString.call(this.column) === '[object Object]') {
this.getResize()
let list = this.getColumnData()
let num = 0
for (let i = 0; i < list.length; i++) {
const element = list[i]
if (i === 0) {
num = element.num
} else {
if (element.width <= this.cwidth) {
num = element.num
}
}
}
return num
} else {
return this.column || 5
}
}
},
mounted () {
this.cwidth = document.body.clientWidth
this.getResize()
},
destroyed () {
removeEventListener('resize', this.resizeFn)
},
methods: {
getColumnData () {
let list = []
for (let key in this.column) {
if (Number(key) || Number(this.column[key])) {
list.push({ width: Number(key), num: Number(this.column[key]) })
}
}
return list.sort((a, b) => a - b)
},
getResize () {
if (typeof this.column !== 'number') {
window.addEventListener('resize', this.resizeFn, false)
}
},
resizeFn () {
if (this.timer) clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.cwidth = document.body.clientWidth
}, 300)
},
getStyle (vnode) {
let data = vnode.data
let styles = { flex: '1', opacity: 0 }
let classs = []
if (data.staticClass) {
classs = [...classs, ...data.staticClass.split(' ')]
}
if (data.staticStyle) {
styles = Object.assign(styles, data.staticStyle)
}
if (data.class) {
if (typeof data.class === 'string') {
classs = [...classs, ...data.class.split(' ')]
} else {
for (let key in data.class) {
if (data.class[key]) classs.push(key)
}
}
}
if (data.style) {
let styleList = data.style.split(';')
styleList.forEach(value => {
let [a, b] = value.split(':')
styles[a] = b
})
}
return { styles, classs }
}
},
data () {
return {
timer: undefined,
cwidth: 1024
}
}
}
</script>
<style lang="less" scoped>
.main-conetnt {
width: 100%;
position: relative;
}
.content {
display: flex;
}
</style>
组件:<display-item>
<template>
<div class="loop-main">
<slot />
</div>
</template>
<script>
export default {
name: 'display-item',
data () {
return {}
}
}
</script>
<style lang="less" scoped>
.loop-main {
position: relative;
flex: 1;
box-sizing: border-box;
transition: ease-in-out 0.2s;
}
</style>
测试效果: