【问题标题】:How Can I capture parent component event in an event emitted by a child event如何在子事件发出的事件中捕获父组件事件
【发布时间】:2021-07-18 16:31:38
【问题描述】:

我正在尝试在 Vue 中创建一个动态表,分为两个级别:子组件包含以 'idx' 作为 :key 的单元格,父组件在表中具有以 'line' 作为:key 的子组件。

我的问题是:当我捕获自定义事件 @update-cellValue 时,我将 idx、oldValue 和 newValue 带到了作用域,但我无法访问发出事件的父组件的详细信息( v-for 的哪一行)。我的意思是,我的意图是同时拥有 (line, idx) 并像矩阵(2D 数组)一样工作。

我有一个解决方法在一个级别上完成所有操作,只需在 "child's component" 中直接使用 v-for ,但我想将它分别放在两个不同的组件中

子(嵌套)组件 -> 包含单元格的表格行

<template>
  <div >
    <tr class='center'>
      <!-- add title to the tr as prop -->
      <td 
        id='cell'
        @click="selectCellEv"
        v-for="(cell, idx) in cells" :key="idx">
      <input type=number @input="updateCellValueEv" 
        v-model.lazy.trim="cells[idx]"/>
      </td>
  </tr>
  </div>

</template>

<script>
// var editable = document.getElementById('cell');
// editable.addEventListener('input', function() {
    // console.log('Hey, somebody changed something in my text!');
// });
export default {
  name: 'CaRow',
  props: {
    cellValArr: {
      type: Array,
      required: false,
      default: () => [],
    },
    title: {
      type: String,
      default: `noNameRow`
    }
  },
  data(){
      return {
          cells: []
      }
  },

  methods: {
    updateCellValueEv(event){
      const idx = event.target.parentElement.cellIndex;
      let val = event.target.value;
      if (val === '') val = 0;
      const oldNumber = parseFloat(this.cells[idx]);
      const newNumber = parseFloat(val);
      if(!isNaN(newNumber) && !isNaN(oldNumber)){
        // console.log(`new ${newNumber}, old ${oldNumber}`)
        this.$emit('update-cellValue', idx, newNumber, oldNumber);
        this.cells[idx] = newNumber;
      }
    },
  },
  created() {    
    this.cellValArr.map((val,idx) => {
      this.cells[idx] = val;
    });
  },
}
</script> 

父组件(将在应用程序中直接使用)-> 包含子组件作为行的表格

<table class="center">
  <CaRow
  v-for="(line, idx) in table" 
  :key="idx"
  :cellValArr="table[idx]"
  @update-cellValue="updateCellVal"
  >{{line}} </CaRow>
</table>
</template>

<script>
import CaRow from './components/CaRow.vue'
export default {
  name: 'App',
  components: {
    CaRow
  },
  data(){
    return{
      table: [[1,2,3],
              [4,5,6],
              [7,8,9]],
      selectedCell: null,
    }
  },
  methods: {
    updateCellVal(idx, newValue, oldValue) {
      console.log(`cell[${idx}: New Value= ${newValue}, Old Value= ${oldValue}]`)
      // this.table[line][idx] = newValue;
      //HERE IS THE PROBLEM!!!
      //LINE IS NOT IN THIS SCOPE
    }
  },
}
</script> 

【问题讨论】:

    标签: vue.js vuejs2 vue-component


    【解决方案1】:

    CaRow.vue 中,将事件数据包装到单个对象中:

    //this.$emit('update-cellValue', idx, newNumber, oldNumber);
    this.$emit('update-cellValue', { idx, newValue: newNumber, oldValue: oldNumber });
    

    然后在父模板中,更新事件处理程序绑定以传递行索引(在此上下文中为idx)和$event(存储发出的事件数据的特殊变量):

    <CaRow @update-cellValue="updateCellVal(idx, $event)">
    

    并更新处理程序以接收行索引和$event

    export default {
      methods: {
        updateCellVal(line, { idx, newValue, oldValue }) {
          console.log({ line, idx, newValue, oldValue });
        }
      }
    }
    

    Vue 2 cannot detect the change when you directly set an item with the index,所以你必须使用this.$set()

    //this.table[line][idx] = newValue;
    this.$set(this.table[line], idx, newValue);
    

    demo

    【讨论】:

      猜你喜欢
      • 2019-05-22
      • 1970-01-01
      • 2018-05-11
      • 2022-12-05
      • 1970-01-01
      • 1970-01-01
      • 2020-10-06
      • 2019-11-21
      • 1970-01-01
      相关资源
      最近更新 更多