自适应浏览器宽度陈列 组件 - vue 可配置不同分辨率 显示列数

 

组件使用预览:

<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>

 

组件使用方法:

methods
参数说明类型可选值默认值
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>

 

测试效果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值