【问题标题】:Vue listen to deep props not triggeringVue 监听 deep props 不触发
【发布时间】:2018-10-12 18:08:08
【问题描述】:

我必须遵循一组组件来创建一个表

  • 表格 - 使用标题(传递列)和行列表,给出 rowData 和列

  • header - 利用传递的列并使用 headerCell 传递列属性

  • headerCell
  • row - 循环遍历给定的列并显示数据

我的问题如下,我希望在标题上单击(比如可见性)将 columnDefinition 更新为可见 true | false 并被行监视以相应地更新可见性。 但是无论我尝试过什么,观察者仍然没有触发。我究竟做错了什么?

/**** Table ***/
<template>
    <table>
    <HeaderRow :columns=computedColumns :groups=columnGroups v- 
        on:column:change=onColumnChange></HeaderRow>
    <tbody>
         <Row v-for="(row, index) in computedData" :key=index :data=row 
              :columns=computedColumns :rowIndex=index ></Row>
    </tbody>
    </table>
</template>
<script>
import Row from "./Row.vue";
import HeaderRow from "./HeaderRow.vue";
export default {
	computed: {
    /* If this.columns is set (columns is a prop) than map it to a new array, otherwise 
       try to identify the columns from the row data */
		computedColumns: function() {
      if (this.columns && this.columns.length) {
				return this.columns.map(col => {
                    return Object.assign({
                        title: '',
                        name: '',
                        description: undefined,
                        className: '',
                        style: '',
                        visible: true,
                        sort: false,
                        group: undefined,
                        defaultValue: undefined,
                    }, col)
                });
			} else {
				return (
					this.data &&
					this.data
						.map(function(row) {
							return Object.keys(row);
						})
						.reduce(function(arr, row) {
							return arr.concat(
								row.filter(function(value, index) {
									return arr.indexOf(value) == -1;
								})
							);
						}, [])
						.map(function(column) {
							return {
								title: column,
								name: column
							};
						})
				);
			}
		},
   }

/*** HeaderCell ***/ 
    <th @click=toggleColumn :class=className><span>{{column.title}}</span></th>
    ...
    ...
    toggleColumn: function(e) {
    		this.visible = !this.visible;
    		this.column.visible = this.visible;
    		this.$emit("column:change", {
    			column: this.column,
    			columnIndex: this.columnIndex
    		});
    	}

/***   Row  ****/
    <template>
    <tr>
      <td  v-for="(cell, index) in cells" :key=index :class=cell.className 
    :style=cell.style v-html=cell.value ></td>
    </tr>
    </template>
    <script>
    export default {
    props: {
        data: {
            default: []
        },
        columns: {
            default: "",
            type: Array
        },
        rowIndex: {
            default: -1
        }
    },
    watch: {
        columns: {
            handler: function () {
                console.log('change occurred')
            },
            deep: true
        }
    },

【问题讨论】:

  • 你的props的数据格式是什么=columns
  • 你能告诉我们computedColumns方法是什么吗?

标签: vue.js vue-component


【解决方案1】:

我注意到您的 columns 属性正在使用 computedColumns

最好看看这是什么,因为当您从该计算属性返回值时,它可能会失去反应性。

例如,如果您的父母有以下情况:

computed: {
    computedColumns() {
        // return new set of columns
        return [
            {id: 1, visible: false},
            {id: 2, visible: false},
            {id: 3, visible: false}
        ]
    }
}

那么computedColumns 属性将不会有任何反应。因此,您将无法观看。

但是,如果你有一个例子:

data() {
    return {
        columns: [
            {id: 1, visible: false},
            {id: 2, visible: false},
            {id: 3, visible: false}
        ]
    }
},
computed: {
    computedColumns() {
        // return reactive data attribute
        return this.columns
    }
}

因为您引用的是原始数据属性,所以您将保持反应性。

因此,您可能需要重新考虑如何设置 columns 属性以保持反应性。

这是一个概述此示例的fiddle

【讨论】:

  • 我已经更新了原始代码 sn-p 以显示计算结果。基本上我有第二种情况,但是它使用了一个可能会停止反应的地图功能。
  • 如上所述,计算列会丢失反应性。相反,我所做的是在 columns 属性上添加了一个监视,并使用适当的转换分配了 computedColumns(现在在数据下),使其具有反应性
  • 太好了,很高兴你能成功。如果您认为值得,请随意投票。干杯
猜你喜欢
  • 2019-06-19
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-03
  • 1970-01-01
相关资源
最近更新 更多