Vuejs2 Vue-将apollo查询结果从父组件传递到子组件

Vuejs2 Vue-将apollo查询结果从父组件传递到子组件,vuejs2,apollo,Vuejs2,Apollo,我有一个调用apollo查询的父组件: <template> <div class="row" style="flex-wrap: nowrap; width:102%"> <BusinessContextTeamPanel :business_contexts="business_contexts"></BusinessContextTeamPanel></BusinessContextTeamDet

我有一个调用apollo查询的父组件:

<template>
        <div class="row" style="flex-wrap: nowrap; width:102%">
            <BusinessContextTeamPanel :business_contexts="business_contexts"></BusinessContextTeamPanel></BusinessContextTeamDetailPanel>
        </div>
</template>
    <script>
        apollo: {
                    business_contexts: {
                        query: gql`query ($businessContextId: uuid!) {
                           business_contexts(where: {id: {_eq: $businessContextId }}) {
                               id
                               businessContextTeams {
                                 id
                                 team {
                                   name
                                   id
                                 }
                                 role
                               }
                           }
                         }`,
                        variables: function() {
                            return {
                                businessContextId: this.currentContextId
                            }
                        }
                    }
                },
    </script>
这里的
v-if
抛出

无法读取未定义的属性“length”

v-for
工作时。 当我试图在子组件挂载钩子上调用的子方法(
loadData()
)中使用道具时,我也会得到
undefined

<script>
    import Treeselect from '@riophae/vue-treeselect';
    import _ from "lodash";


    export default {
        name: "BusinessContextTeamPanel",
        components: { Treeselect },
        props: ['business_contexts'],
        data() {
            return {
                itemModel: {},
                allRoles: [],
                formTitle: "",
                filteredTeams: [],
                showNoTeamMsg: false
            }
        },
        mounted() {
            this.loadData();
        },
        methods: {
            loadData() {
                let roles = [];
                _.forEach(["Admin", "Contributor", "Owner", "Master", "Viewer", "User"], function (role) {
                    roles.push({id: role, label: role});
                });
                console.log(this.business_contexts); // here I get undefined
                this.allRoles = roles;
                this.showNoTeamMsg = this.business_contexts.length === 0;
            }
        }
    }
</script>

从“@riophae/vue Treeselect”导入Treeselect;
从“洛达斯”进口;
导出默认值{
名称:“BusinessContextTeamPanel”,
组件:{Treeselect},
道具:['business_contexts'],
数据(){
返回{
itemModel:{},
所有角色:[],
表格名称:“,
筛选数据组:[],
showNoTeamMsg:错误
}
},
安装的(){
这是loadData();
},
方法:{
loadData(){
让角色=[];
_.forEach([“管理员”、“贡献者”、“所有者”、“主控者”、“查看者”、“用户”],函数(角色){
roles.push({id:role,label:role});
});
console.log(this.business_contexts);//这里没有定义
this.allRoles=角色;
this.showNoTeamMsg=this.business_contexts.length==0;
}
}
}

我遗漏了什么?

要么您的apollo查询不起作用,要么它没有及时准备好供子组件尝试使用

为了进行调试,在父组件的模板中添加{{business_contexts}},这样您就可以查看它了。这将确认查询是否有效

如果查询正在工作,则可能是您的子组件正在尝试在数据准备就绪之前访问数据。将您的v-if从

<div v-if="business_contexts.length > 0">


编辑:更好的做法是,将父组件更改为根本不尝试加载子组件,直到父组件具有以下数据:

<BusinessContextTeamPanel v-if="business_contexts" :business_contexts="business_contexts"></BusinessContextTeamPanel></BusinessContextTeamDetailPanel>


我可以在父级中看到
{{business\u contexts}}中的数据
我也可以从子级中看到它,但是
v-if
仍然会增加未定义的长度,即使您进行了更改。为什么v-if下方的
v-for
正确显示了
business\u上下文中的数据,但v-if崩溃了?您确定是v-if引发了该错误吗?我提供的if语句中的
&&
使其短路-如果前面的部分计算结果不为true,则后面的部分将不会执行。因此,如果未定义业务上下文,那么它将不会计算
business\u contexts.length>0
,因此错误消息确实不可能出现。再次检查未定义的错误现在没有从其他地方抛出;您的子组件mounted()也正在尝试在变量准备就绪之前访问它。我会更新我的答案,提供更多关于这个的信息是的,这肯定是它,你的mounted()钩子将在数据准备好之前运行。您希望延迟加载组件,直到它准备就绪。或者,您必须对子组件进行工程设计,以便在数据存在后才查找该数据-mounted()为时过早。例如,您可以从观察者处调用loadData(),也可以完全取消loadData(),将this.showNoTeamMsg和this.allRoles转换为计算属性。这意味着它们也将是反应性的,耶,你完全正确,我的想法是,道具将在孩子上马之前加载数据,关于观察者和计算值的优点,谢谢。但是仍然困扰着我为什么v-for能够正确地呈现数据?它像异步管道一样使用吗?不用担心!Vue模板对我来说仍然有点神奇,但我的理解是,它们将在对反应变量进行更改时重新加载。因此,即使出现错误,业务上下文稍后也会变为可用,模板会重新加载,此时不再出现错误
<div v-if="business_contexts && business_contexts.length > 0">
<BusinessContextTeamPanel v-if="business_contexts" :business_contexts="business_contexts"></BusinessContextTeamPanel></BusinessContextTeamDetailPanel>