【问题标题】:Vue - passing apollo query result from parent to child componentVue - 将阿波罗查询结果从父组件传递给子组件
【发布时间】:2019-09-25 10:23:24
【问题描述】:

我有一个调用这个 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>

我的子组件(BusinessContextTeamPanel)获取输入道具并像这样使用它:

<template>
    <div v-if="business_contexts.length > 0">
        <div v-for="teams in business_contexts" :key="teams.id">
                        <div v-for="team in teams.businessContextTeams" :key="team.id" style="padding-top: 20px;min-width: 400px">
                            <div style="height: 25px; color: #83d6c0;">

                                <div style="width: 7%; font-size: 10px; float: left; padding-top: 8px; cursor: pointer;" class="fa fa-minus-circle" ></div>

                                <div style="width: 50%; float: left; padding-right: 10px;">
                                    <div class="gov-team-text" @click="editTeam(team)">{{ team.team.name }}</div>
                                </div>

                                <div style="width: auto; float: right;">
                                    <b-badge variant="light">{{ team.role }}</b-badge>
                                </div>
                                <div style="width: 45%; margin-left: 4%; float: right;">
                                </div>
                            </div>
                            <div style="clear: both; margin-bottom: 15px;"></div>
                        </div>

                    </div>
    </div>
</template>

v-if 这里抛出

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

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>

我错过了什么?

【问题讨论】:

    标签: vuejs2 apollo


    【解决方案1】:

    要么你的 apollo 查询不工作,要么它没有及时准备好让子组件尝试使用它。

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

    如果查询正常,则可能是您的子组件在数据准备好之前尝试访问数据。改变你的 v-if 从

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

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

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

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

    【讨论】:

    • 我可以在父项中看到来自{{ business_contexts }} 的数据,我也可以从子项中看到它,但是v-if 仍然会提高 undefined 的长度,即使您进行了更改。 v-if 下方的v-for 怎么能正确显示来自business_contexts 的数据,但是 v-if 却崩溃了?
    • 您确定是 v-if 引发了该错误吗?我提供的 if 语句中的 &amp;&amp; 使其短路 - 如果 && 之前的部分未评估为真,则 && 之后的部分将不会执行。因此,如果 business_contexts 未定义,则它不会评估business_contexts.length &gt; 0,因此该错误消息确实不应该出现。仔细检查未定义的错误现在没有从其他地方抛出;您的子组件mounted() 也试图在变量准备好之前访问它。我将在此更新我的答案
    • 是的,绝对是这样,您的mounted() 挂钩将在数据准备好之前运行。您想延迟加载组件,直到它准备好。或者您必须设计您的子组件以仅在该数据存在后才查找该数据-mounted() 为时过早。例如,您可以改为从观察者调用 loadData(),或者您可以完全取消 loadData() 并将 this.showNoTeamMsg 和 this.allRoles 设置为计算属性。这意味着他们也将是被动的,耶
    • 是的,你完全正确,我的想法是,道具将在安装孩子之前加载数据,关于观察者和计算值的优点,感谢。但是仍然困扰我 v-for 如何正确呈现数据?它像异步管道一样使用吗?
    • 别担心! Vue 模板对我来说仍然有点神奇,但我的理解是它们会在响应变量发生更改时重新加载。因此,即使出现错误,business_contexts 稍后也可用,模板会重新加载,此时不再有错误
    猜你喜欢
    • 2019-09-28
    • 1970-01-01
    • 2021-11-06
    • 2017-12-02
    • 2020-02-04
    • 2022-11-21
    • 2021-09-09
    • 2020-07-26
    • 2019-11-12
    相关资源
    最近更新 更多