This is the 8th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021.

preface

When we are doing the management background system, whether there are too many operation buttons (more than three)? The following figure

Implementation approach

  • Total utilization slotslot+refImplementation, but can be implemented in two ways, this component is all combined.
  • Public HTML code:
<div :ref="`operation+${customRef}`" class="operation-container">
    <div :ref="`operation+${customRef}_button`">
      <slot />
    </div>
    <el-popover
      popper-class="btns-container"
      :placement="placement"
      width="auto"
      trigger="hover"
    >
      <slot />
      <i v-show="isFold" slot="reference" class="el-icon-more fold-icon" />
    </el-popover>
 </div>
Copy the code

A:

Start with a simple implementation that simply exceeds len (e.g. $refs[operation+${this.customRef}_button].children, const children = this.$refs[operation+${this.customRef}_button].children, IsFold =true; DOM nodes len to children. Length-1 are hidden;

this.isFold = children.length > this.len
// When the number of buttons is not equal to len, hide from Len-1 to make the button display
const isLen = children.length === this.len ? this.len : this.len - 1 
children.forEach((child, ins) = > {
       child.style.display = ins >= isLen ? 'none' : 'inline-block'
})
Copy the code

Method 2:

When the width of the parent container is smaller than the width of the content, the button needs to appear. If the button exceeds the width of the parent container, it can be hidden. The key to obtain these two widths is to use the above two methods. Other instructions are also commented in the code. Const childrenWidth = children.map(item => item.offsetwidth) // array.isarray (children)===false

// Get the width of the parent container (including the edges)
const offsetWidth = this.$refs[`operation+The ${this.customRef}`].offsetWidth
// Get the width of the content in the Dom
const scrollWidth = this.$refs[`operation+The ${this.customRef}`].scrollWidth
this.isFold = offsetWidth < scrollWidth
if (this.isFold) {
    // const childrenWidth = children.map(item => item.offsetWidth) // Array.isArray(children)===false
    const childrenWidth = []
    for (let i = 0; i < children.length; i++) {
          childrenWidth.push(children[i].offsetWidth)
    }
    let maxCount = 0
    const showMaxIndex = childrenWidth.findIndex((item, ins) = > {
           maxCount = item + maxCount + (ins ? 10 : 0)
           return maxCount > offsetWidth
     })
     children.forEach((item, index) = > {
           item.style.display = index >= showMaxIndex ? 'none' : 'inline-block'
      })
      maxCount = null // Empty variable, free
}
Copy the code

Complete component code

props instructions
customRef Any number/string
len Len =0: calculate the number of display according to the width; Len >0: Displays len buttons by default
placement With el – popoverConfiguration items for placement
<template>
  <div :ref="`operation+${customRef}`" class="operation-container">
    <div :ref="`operation+${customRef}_button`">
      <slot />
    </div>
    <el-popover
      popper-class="btns-container"
      :placement="placement"
      width="auto"
      trigger="hover"
    >
      <slot />
      <i v-show="isFold" slot="reference" class="el-icon-more fold-icon" />
    </el-popover>
  </div>
</template>
<script>
export default {
  name: 'ColumnOperation'.props: {
    customRef: {
      type: [Number.String].default: 0
    },
    len: {
      type: Number.default: 0 // len=0: count the display number according to the width; Len >0: Displays len buttons by default
    },
    placement: {
      type: String.default: 'left'}},data() {
    return {
      width: ' '.isFold: false}},mounted() {
    this.domInit()
  },
  methods: {
    domInit() {
      const children = this.$refs[`operation+The ${this.customRef}_button`].children // type: Array
      this.$nextTick(() = > {
        if (this.len) {
          this.isFold = children.length > this.len
          const isLen = children.length === this.len ? this.len : this.len - 1
          children.forEach((child, ins) = > {
            child.style.display = ins >= isLen ? 'none' : 'inline-block'})}else {
          // Get the width of the parent container (including the edges)
          const offsetWidth = this.$refs[`operation+The ${this.customRef}`]
            .offsetWidth
          // Get the width of the content in the Dom
          const scrollWidth = this.$refs[`operation+The ${this.customRef}`]
            .scrollWidth
          this.isFold = offsetWidth < scrollWidth
          if (this.isFold) {
            // const childrenWidth = children.map(item => item.offsetWidth) // Array.isArray(children)===false
            const childrenWidth = []
            for (let i = 0; i < children.length; i++) {
              childrenWidth.push(children[i].offsetWidth)
            }
            let maxCount = 0
            const showMaxIndex = childrenWidth.findIndex((item, ins) = > {
              maxCount = item + maxCount + (ins ? 10 : 0)
              return maxCount > offsetWidth
            })
            children.forEach((item, index) = > {
              item.style.display =
                index >= showMaxIndex ? 'none' : 'inline-block'
            })
            maxCount = null // Empty variable, free}}})}}</script>

<style lang="scss">
@import '.. /.. /styles/variables';
.operation-container {
  box-sizing: border-box;
  overflow: hidden;
  white-space: nowrap;
  min-width: 60px;
  display: flex;
  align-items: center;
  justify-content: start;
  .fold-icon {
    // position: absolute;
    // right: 12px;
    // top: calc(50% - 5px);
    color: $comTheme;
    cursor: pointer;
    margin-left: 10px; }}.btns-container {
  min-width: 60px; // &> * {//margin-right: 5px; / /}}</style>
Copy the code
  • Other component calls
<ColumnOperation> <el-button type="text" size="small"> </el-button> //... <el-button type="text" size="small"> Edit </el-button> <el-button type="text" size="small">Copy the code

conclusion

Look at the code does not feel quite small, heh heh… Writing this is much more comfortable than business, you can debug the code appropriately, writing business is constantly “tuning business”, repetitive and no brain… -wuwuwu……