从子组件更改事件 v-data-table 行的背景

Posted

技术标签:

【中文标题】从子组件更改事件 v-data-table 行的背景【英文标题】:Change background of v-data-table row on event from child component 【发布时间】:2020-02-29 21:48:47 【问题描述】:

我的父组件中有一个扩展数据表,扩展行中有一个带有按钮的子组件。当我单击子组件内的按钮时,我想更改关联行的背景颜色。我不确定如何定位该行以在事件中添加 css 类。

ScanGrid(父):

    <template>
      <v-flex v-if="items.length === 0">
        <ScanAdd @selectBatch="showScan" />
      </v-flex>
      <v-card v-else class="ma-5">
        <v-card-text>
          <v-layout align-center>
            <v-data-table
              :headers="headers"
              :items="items"
              item-key="StorageName"
              show-expand
              single-expand
              :expanded="expanded"
              hide-default-footer
              @click:row="clickedRow"
            >
              <template
                @isDeleted="deleteRow"
                v-if="groupBy === 'barCode'"
                v-slot:expanded-item=" item "
              >
                <td :colspan="12">
                  <ScanGridCode :item="item" />
                </td>
              </template>
              <template v-else v-slot:expanded-item=" item ">
                <td :colspan="12">
                  <ScanGridDef :item="item" />
                </td>
              </template>
            </v-data-table>
          </v-layout>
        </v-card-text>
      </v-card>
    </template>

    <script>
    import  API  from "@/api";
    import ScanAdd from "./ScanAdd";
    import ScanGridCode from "./ScanGridCode";
    import ScanGridDef from "./ScanGridDef";
    export default 
      name: "ScanGrid",
      props: 
        items: 
          type: Array,
          required: true
        
      ,
      components: 
        ScanGridCode,
        ScanGridDef,
        ScanAdd
      ,
      methods: 
        deleteRow(value) 
          this.isDeleted = value;
        ,
        showScan(value) 
          this.selectedId = value;
          this.addScanBatch(value);
          this.$emit("processingBatch", true);
          this.processingBatch = true;
        ,
        async addScanBatch(Id) 
          const selectedItems = await API.getPhysicalInventoryBatch(Id);
          if (selectedItems.data.Id === this.selectedId) 
            this.items = selectedItems.data.Locations;
          
        ,
        clickedRow(value) 
          if (
            this.expanded.length &&
            this.expanded[0].StorageName == value.StorageName
          ) 
            this.expanded = [];
           else 
            this.expanded = [];
            this.expanded.push(value);
          
        
      ,
      data: () => (
        isDeleted: false,
        groupBy: "barCode",
        expanded: [],
        items: [],
        toDelete: "",
        totalResults: 0,
        loading: true,
        headers: [
          
            text: "Localisation",
            sortable: true,
            value: "StorageName",
            class: "large-column font-weight"
          ,
          
            text: "Paquets scannés",
            sortable: true,
            value: "ScannedProduct",
            class: "large-column font-weight"
          ,
          
            text: "Paquets entrants",
            sortable: true,
            value: "Incoming",
            class: "large-column font-weight"
          ,
          
            text: "Paquets sortants",
            sortable: true,
            value: "Outgoing",
            class: "large-column font-weight"
          ,
          
            text: "Paquets inconnus",
            sortable: true,
            value: "Unknown",
            class: "large-column font-weight"
          
        ]
      )
    ;
    </script>

扫描网格代码(子):

    <template>
      <div class="codeContainer">
        <div class="cancelLocation">
          <v-flex class="justify-center">
            <v-btn class="ma-5" large color="lowerCase" tile  @click="deleteLocation"
              >Annuler le dépôt de cette localisation</v-btn
            >
          </v-flex>
        </div>
      </div>
    </template>

    <script>
    export default 
      name: "ScanGridCode",
      props: 
        item: 
          type: Object,
          required: true
        
      ,
      methods: 
        deleteLocation() 
          this.item.IsDeleted = true;
          this.$emit("IsDeleted", true);
        
      ,
      data: () => (
        IsDeleted: false,
        groupBy: 0,
        headersGroupCode: [
          
            text: "Code barre",
            sortable: true,
            value: "SerialNumber",
            class: "large-column font-weight-light"
          ,
          
            text: "De",
            sortable: true,
            value: "FromLocation",
            class: "large-column font-weight-light"
          ,
          
            text: "Vers",
            sortable: true,
            value: "ToLocation",
            class: "large-column font-weight-light"
          
        ]
      )
    ;
    </script>

我使用 Vuetify 2.1.7 和 Vue 2.6.10。当我单击按钮时,我调用 deleteLocation 函数。我假设我需要向我的父母 $emit 一个值,但之后我不知道如何定位 tr 来改变它的样式。

【问题讨论】:

你在使用 Vuex 吗? 是的,我是。版本 3.0.1 【参考方案1】:

由于您使用的是 Vuex,我建议使用诸如 store.state.selectedRow 之类的变量来跟踪是否选择了一行(或者如果有不止一行,则选择了哪一行)。然后你可以在你的 Vue 组件中有一个计算属性myProperty = this.$store.state.selectedRow,它会自动反映单一的事实来源,你的条件类可以绑定到这个myProperty。这意味着您无需担心发出事件。

【讨论】:

【参考方案2】:

发出事件的方法是应该做什么。所以我假设你将从 deleteLocation 函数发出。 由于您需要对行进行自定义样式,因此您需要添加项目插槽并在那里添加您的逻辑

<template v-slot:item=" item, select">
 <tr :class="key === coloredRow ? 'custom-highlight-row' : ''">

     <td :colspan="12">
    <ScanGridCode @changeColor="changeColor(key)" :item="item" />
    </td>
 //add this method to your script element
 changeColor(idx) 
      this.coloredRow = idx;
    

【讨论】:

我没有使用 select 来扩展我的行。此外,如果我在模板中定义 tr,则展开部分中的子组件仅采用第一个 td 的宽度,而不是整行。 deleteLocation 是我从是发出的。您能否更具体地说明代码?我是否在 custom-highlight-row 中声明样式? 是的,您可以在您拥有的任何类名中声明样式。

以上是关于从子组件更改事件 v-data-table 行的背景的主要内容,如果未能解决你的问题,请参考以下文章

如何捕获 v-data-table 组件上的滚动事件?

如何在 ReactJS 中将更改的状态从子组件传递给其父组件

typescript 从子组件到父组件的事件发射器

从子组件触发应用级别样式更改

Vuejs 3 从子组件向父组件发出事件

如何测试从子组件触发的自定义事件