[vxe-table] @enter.keyup.native realisiert die Verwendung einiger Methoden zum Bewegen des Eingabecursors nach rechts in der Liste und in der vxe-Tabelle (spezifische Implementierung + Fallstricke)

Anforderungen:
vxe-table-Tabelle
1. Beim Hinzufügen wird das erste Eingabefeld in der ersten Zeile von vxe-table fokussiert.
2. Nachdem die Eingabe abgeschlossen ist, drücken Sie die Eingabetaste, um automatisch zum nächsten Eingabefeld in derselben Zeile zu springen.
3. Wann Nachdem die Eingabe im letzten Eingabefeld derselben Zeile abgeschlossen ist, drücken Sie die Eingabetaste, um zum ersten Eingabefeld zurückzukehren und den Status auszuwählen. Das Kontrollkästchen befindet sich im ausgewählten Status. 4. Klicken Sie auf Hinzufügen. Wenn die
Bildlaufleiste zu lang ist, um die erste Spalte abzudecken, nach links verschieben. Scrollen Sie zum Anfang.
5. Es gibt zwei Dropdown-Felder in der Tabelle, die native LEL-Select-Komponente und die gekapselte Select-Komponente. Wenn das Bedienfeld geöffnet ist, verschieben Sie die Komponente Auf und ab und drücken Sie die Eingabetaste, um Werte zuzuweisen, und klicken Sie direkt, um Werte zuzuweisen. 6. Es gibt
Die gekapselte Komponente, Eingabefeld + El-Tabelle, zeigt die El-Tabelle an, wenn ein Wert eingegeben wird. Der El-Popover wird verwendet, um einen zu erreichen Effekt ähnlich dem Dropdown-Feld „el-select“. Das SVG-Symbol wird hinzugefügt. Klicken Sie, um das Popup-Fenster zu öffnen. Nachdem Sie auf eine Zeile doppelgeklickt oder auf „OK“ geklickt und einen Wert zugewiesen haben, muss das Eingabefeld fokussiert werden.

Anforderungen + Optimierung, es hat zwei Tage gedauert,

Fallstricke, auf die ich gestoßen bin:
1. Das el-select-Auswahlfeldfenster wird geöffnet. Nachdem Sie geklickt haben, um einen Wert auszuwählen, und die Eingabetaste gedrückt haben, um nach rechts zu springen, öffnet el-select immer noch das Feld. 2. In derselben Zeile der
Liste Drücken Sie an einer beliebigen Stelle die Eingabetaste, um das Enter-Ereignis auszulösen.
3. Im Enter-Ereignis kann das benutzerdefinierte Attribut nicht abgerufen werden.
4. Wenn die letzte Spalte derselben Zeile in der Liste eingegeben wird, springt sie zur fokussierten Spalte und ausgewählter Status in der ersten Spalte.
5. Die Liste ist horizontal zu lang und die Bildlaufleiste wird angezeigt. Erhöhen, um die Bildlaufleiste auf die erste Spalte und den Fokus zurückzusetzen. 6.
Drücken Sie die Eingabetaste und springen Sie nach rechts, um zur ersten Spalte zu springen Nächstes Eingabefeld. Beim Fokussieren wird das nächste Eingabefeld aufgrund einer Behinderung der Bildlaufleiste nicht vollständig angezeigt. So schieben Sie die Bildlaufleiste ganz nach rechts
7. vxe – So aktivieren Sie das Tabellen-Kontrollkästchen manuell und behalten den ursprünglichen Prüfeffekt bei

Ideen umsetzen;

1. Definieren Sie eine js-Datei im Ordner „utils“. Binden Sie nach der globalen Registrierung Eingabeereignisse an Bearbeitungskomponenten wie Eingabefelder und Dropdown-Felder. 2. Fügen Sie benutzerdefinierte
Indizes zu allen Dom-Elementen der Liste hinzu.

Hinweis: Der Beispielcode enthält nur Code, der sich auf Funktionen bezieht

1. Auf der übergeordneten Seite ist vxe-table in Unterkomponenten gekapselt

    <vxeTable
              ref="vxeTableRef"           
              :columns="columns"
              :data-source="list"
              @selectAllEvent="selectAllEvent"
              @getList="getList"           
              @addRow="addRow"
              @handleDelList="handleDelList"
              :formData="formData"
              :enterFlag.sync="enterFlag"
            ></vxeTable>

   
//新增
handleAddList(){
    
    
this.list.unshift({
    
    
          id: this.uuid(),
          money: 0,
          cash: 0,
          checked:false
        })
        this.list.forEach(item=>{
    
    
          item.checked = false
        })
        this.dealFirstInput()
},

 dealFirstInput(index, flag) {
    
    
      this.$nextTick(() => {
    
    
        // vxe-body--row从1开始
              let lastIndex
        if (flag == 'up') {
    
    
          lastIndex = index +1
        } else if (flag == 'down') {
    
    
          lastIndex = index + 2
        }
        // 增加下行
        if (index>=0&&flag) {
    
    
          // 获取第一个输入框元素
          const lastElement = `.vxe-table--body-wrapper .vxe-table--body .vxe-body--row:nth-child(${
     
     lastIndex}) .vxe-body--column:nth-child(3) .el-input__inner`
          const tolastInput = this.$refs.vxeTableRef.$refs.vxeTable.$el.querySelector(lastElement)
          // // 聚焦第一个输入框
          tolastInput.focus()
        } else {
    
    
          // 新增和增加上行
          // 获取第一个输入框元素
          const firstInput = this.$refs.vxeTableRef.$refs.vxeTable.$el.querySelector(
            '.vxe-table--body-wrapper .vxe-table--body .vxe-body--row:nth-child(1) .vxe-body--column:nth-child(3) .el-input__inner'
          )
          // // 聚焦第一个输入框
          firstInput.focus()
        }

        this.enterFlag = true
      })
    },
//列表操作列增加上行,增加下行
    addRow(row, index, key) {
    
    
     const newObj = {
    
     money: 0, cash: 0, id: this.uuid() }
     if (index >= 0) {
    
    
          this.enterFlag = !this.enterFlag

          if (key === 'previous') {
    
    
            this.list.splice(index, 0, newObj)
            this.dealFirstInput(index, 'up')

            return
          }
          this.list.splice(index + 1, 0, newObj)
          this.dealFirstInput(index, 'down')
        }
        }

2. Innerhalb der Unterkomponente vxe-table

    <el-form :model="form" ref="form" :rules="rules" :show-message="false">

      <vxe-table     
        ref="vxeTable"
        class="mytable-scrollbar"
        :row-config="{ height: 36 }"
        border
        @scroll="handleScroll"
        show-overflow
        resizable
        @checkbox-all="selectAllEvent"
        @checkbox-change="selectAllEvent"
        :footer-method="footerMethod"
        :data="list"
        :column-config="{ resizable: true }"
        @resizable-change="resizableChange"
      :checkbox-config="{ checkAll: true }"
     
      >
       <vxe-column type="checkbox" width="60" fixed="left" :header-align="'center'" :align="'center'" :resizable="false"></vxe-column>
         <template v-for="config in newColumns">
          <vxe-column
            :key="config.field"
            :width="config.width"
            :field="config.field"
            :visible="config.visible"
            :header-align="'center'" 
            :align="'center'"
            :fixed="config.freeze === true ? 'left' : ''"
            :min-width="config.field"
            :resizable="true"
          >
                    <template #default="{ row, $rowIndex, $columnIndex }" v-if="config.field == 'xxx'">
              <el-form-item :prop="'list.' + $rowIndex + '.notes'" :rules="rules.xxx">
                <el-input
                  ref="input"
                  v-model="row.xxx"
                  @keyup.enter.native="$event => tableKeydown($event, $rowIndex, $columnIndex)"              
                  clearable
                ></el-input>
              </el-form-item>
            </template>
                        <template #default="{ row, $rowIndex, $columnIndex }" v-else-if="config.field == 'xxx'">
              <el-select
                :ref="'select' + $columnIndex + 'input' + $rowIndex"
                v-model="row.xxx"
                @keyup.enter.native="$event => tableKeydown($event, $rowIndex, $columnIndex)"
                clearable
                filterable
                :disabled="isEnabled"
              >
                <el-option v-for="item in deptOption" :key="item.deptId" :value="item.deptId" :label="item.deptName"></el-option>
              </el-select>
            </template>
                  </vxe-column>
      </vxe-table>
          </el-form>

 props: {
    
    
    enterFlag: {
    
    
      type: Boolean,
      default: false,
    },
    }
watch:{
    
    
    enterFlag: {
    
    
      handler(newVal) {
    
    
        if (newVal === true) {
    
    
          this.getAllInput()
        }
      },
      deep: true,
    },
}
    // 滚动事件
    getAllInput() {
    
    
      setTimeout(() => {
    
    
        this.$nextTick(() => {
    
    
          this.$refs.vxeTable.scrollTo(0)
        })
      }, 500)
    },

Das Wichtigste ist js

export function tableKeydown(e, rowIndex, columnIndex) {
    
    
  //事件对象兼容
  let ev = e || window.event || arguments.callee.caller.arguments[0]
  //通过ev 获取 当前input 名称 用于判断属于哪列
  let className = ev.target.offsetParent.className
  //获取所有input
  let inputAll = document.querySelectorAll('.mytable-scrollbar .el-input__inner')
  //获取所有索引组成的数组
  const inputIndexs = []
  for (var i = 0; i < inputAll.length; i++) {
    
    
    inputIndexs.push(i)
  }
  //按索引,增加自定义属性,这里遇到的坑是js中之前已经增加过自定义属性,代码复制过来的时候没有改,导致一直查找不到我现在增的
  //自定义属性customFocusIndex,一定要保证自定义属性的唯一性
  for (var i = 0; i < inputIndexs.length; i++) {
    
    
    inputAll[i].setAttribute('customFocusIndex', inputIndexs[i])
  }
  let attrIndex = parseInt(ev.target.getAttribute('customFocusIndex'))

  // ev.keyCode == 13代表按下的是回车,向上键33,向下键34
  if (ev && ev.keyCode == 13) {
    
    
  //每次回车+1,下一个输入框的索引
    attrIndex += 1
    //如果遇到禁用列,多加一次索引
    for (var i = attrIndex; i < inputAll.length; i++) {
    
    
      if (inputAll[i] && inputAll[i].disabled) {
    
    
        attrIndex += 1
      } else {
    
    
        break
      }
    }
    //一行一共有多少列,这里写死了
    const rowline = rowIndex * 12
//第10列之后都是禁用列,这里也写死了,第10列代表最后一列
    if (columnIndex == 10) {
    
    
      // 最后一列跳转到第一列
      inputAll[rowline].focus()
      inputAll[rowline].select()
      //调用scrollTo方法,手动将滚动条滚动到第一列
      setTimeout(() => {
    
    
        this.$nextTick(() => {
    
    
          this.$refs.vxeTable.scrollTo(0)
        })
      }, 500)
  //最后一列调整到第一列的时候要手动选中复选框,使用setCheckboxRow方法
      const vxeTable = this.$refs.vxeTable
      const data = this.$refs.vxeTable.getData()
      vxeTable.setCheckboxRow(data[rowIndex],true)
      this.$refs.vxeTable.loadData(data)
      // 下拉框点击选择,下拉框比输入框多一个类名is-focus,通过此区分
      if (className.indexOf('is-focus') != -1) {
    
    
      //动态获取el-select的实例,防止重复,行索引+列索引都拼接上了
        let DictselectRef = 'select' + columnIndex + 'input' + rowIndex
        //封装的el-select组件有两层ref,根据自己定义的ref
        if (this.$refs[DictselectRef][0].$refs.selectRef) {
    
    
          // dictSelect
          this.$refs[DictselectRef][0].$refs.selectRef.visible = false
          this.$refs[DictselectRef][0].$refs.selectRef.blur()
          this.$refs[DictselectRef][0].$refs.selectRef.$refs.reference.$refs.input.hidden = true
        } else {
    
    
          // el-select 原生el-select
          this.$refs[DictselectRef].visible = false
          this.$refs[DictselectRef][0].blur()
          this.$refs[DictselectRef][0].$refs.reference.$refs.input.hidden = true
        }
      }
      return
    }
    if (className.indexOf('el-input--suffix') != -1) {
    
    
      // 下拉框点击选择
      if (className.indexOf('is-focus') != -1) {
    
    
        let DictselectRef = 'select' + columnIndex + 'input' + rowIndex
        if (this.$refs[DictselectRef][0].$refs.selectRef) {
    
    
          // dictSelect
          this.$refs[DictselectRef][0].$refs.selectRef.visible = false
          this.$refs[DictselectRef][0].$refs.selectRef.blur()
          this.$refs[DictselectRef][0].$refs.selectRef.$refs.reference.$refs.input.hidden = true
        } else {
    
    
          // el-select
          this.$refs[DictselectRef].visible = false
          this.$refs[DictselectRef][0].blur()
          this.$refs[DictselectRef][0].$refs.reference.$refs.input.hidden = true
        }
      }
     //当第8列回车的时候,会因为滚动条遮挡看不见第九列是否光标已进入,所以加了滚动条向右滚动事件
      if (columnIndex == 8) {
    
         
        let scrollLeft = this.$refs.vxeTable.$el.scrollWidth
        setTimeout(() => {
    
    
          this.$nextTick(() => {
    
    
            this.$refs.vxeTable.scrollTo(scrollLeft)
          })
        }, 500)
      }
      if (inputAll[attrIndex]) {
    
    
        inputAll[attrIndex].focus()
      }
    }
  }
}

Supongo que te gusta

Origin blog.csdn.net/weixin_49668076/article/details/132629362
Recomendado
Clasificación