在Vue中控制与道具相关的元素的可见性

时间:2019-03-04 10:23:19

标签: javascript vue.js

Vue相当新,但仍在尝试理解原理。

我正在尝试创建一个自定义组件,该组件采用项目的分层列表并将其显示在平面列表中。我希望能够基于click事件隐藏和显示每个项目。它基本上是一个自定义的树组件。我正在努力实现这种行为。

我试图创建一个计算属性,将一个isVisible属性添加到每个项目,并在模板绑定show指令中将该属性添加到该属性。但这不起作用,因为计算的属性不是反应性的,并且不会监视我添加的任何属性。

我觉得这应该很简单,而且我没有使用Vue的基础知识。我能想到的选择是:

1-通过isVisible向每个项目添加Vue.set()属性。

2-保留数据对象中可见项目的列表。

实现此目标的最佳方法是什么?

关于第一种方法的尝试如下,该方法未呈现列表中的任何项目,并且收到Vue警告:

[Vue warn]: Property or method "isVisible" is not defined on the 
instance but referenced during render. Make sure that this 
property is reactive, either in the data option, or for class- 
based components, by initializing the property. See: 
https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive- 
Properties.

<template>
    <table>
        <tr>
            <th v-for="(header,col) in headers" :key="col" >
                <td> {{ header.name }} </td>
            </th>
        </tr>
        <template v-for="item in flat_items">
            <tr v-show="isVisible" v-bind:key="item.id">
                <td v-for="(header,id) in headers" :item="item" :key="header.id">
                    <template v-if="item.children && id==0"> 
                        <v-icon>chevron_right</v-icon> 
                    </template>
                    {{ item[header.value] }}
                </td>
            </tr>
        </template>
    </table>
</template>
<script>
    export default {
    name: 'table-tree',
    props: [
        'items',
        'headers'
    ],
    data: function() {
        return {
            ui_item_props : {
                isVisible: true
            },
        }
    },  
    methods: {
        flatten : function(arr, parent_id) {
            var a = [];
            var arrLength = arr.length;
            for (var i=0;i<arrLength;i++) {
                var children = arr[i].children;
                var item = arr[i]
                a.push({...item, parent:parent_id})
                if(Array.isArray(children)){
                    a = a.concat(this.flatten(children,item.id))
                }
            }
            return a
        },
        addPropsObj : function(obj,props) {
            var k;
            for (k in props){
                this.$set(obj,k,props[k])
            }
        },
        addPropsRec : function(arr, props) {
            var arrLength=arr.length
            for(var i=0;i<arrLength;i++){
                this.addPropsObj(arr[i], props);
                if(Array.isArray(arr[i].children)){
                    this.addPropsRec(arr[i].children, props)
                }
            }
        }
    },
    computed: {
        flat_items : function() {
            return this.flatten(this.items,null)
        }
    },
    mounted: function() {
        this.addPropsRec(this.items,this.ui_item_props)
    }
}
</script>

1 个答案:

答案 0 :(得分:1)

  

[Vue警告]:属性或方法“ isVisible”未在   实例,但在渲染过程中被引用。确保该属性   是反应性的,无论是在data选项中,还是基于类的   组件,通过初始化属性。看到:   https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-   属性。

此错误是不言自明的,您没有创建isVisible属性,但是正在模板中使用它。
但是在data/computed object中仅添加isVisible属性将无法解决您的问题。
您可以做的是为isVisible数组中的每个元素添加一个flat_items属性,然后在v-show中使用该变量:

<tr v-show="item.isVisible" v-bind:key="item.id">

然后,您必须管理对象可见性的状态,例如:

 <v-icon @click="manageVisibility(item)">chevron_right</v-icon> 

在您的JavaScript中:

manageVisibility(item) {
    Vue.set(item, 'isVisible', !item.isVisible);
}