首页 > 解决方案 > Vue 监听 deep props 不触发

问题描述

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

我的问题如下,我希望标题上的单击(例如可见性)将 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
        }
    },

标签: vue.jsvue-component

解决方案


我注意到您的 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 属性以保持反应性。

这是概述此示例的小提琴。


推荐阅读