两个兄弟组件之间的数据传输问题(Vue js)

Posted

技术标签:

【中文标题】两个兄弟组件之间的数据传输问题(Vue js)【英文标题】:Data transfer problem between two siblings components (Vue js) 【发布时间】:2020-12-07 04:13:01 【问题描述】:

我有三个组件,其中一个是其他组件的父项从LeftBarTalksList 组件,然后TalksList 发出另一个事件并再次监听LeftBar,最后该组件将talk 对象重新定义为空对象。

这是我的父组件LeftBar

<template>
    <v-navigation-drawer  permanent clipped app light>
        <talks-list v-if="inRoute('messages')" :talk="talk" @talkAdded="talkAdded()"/>
        <template v-if="inRoute('messages')" v-slot:prepend>
            <followed-browser @newTalk="addTalk($event)"/>
        </template>
    </v-navigation-drawer>
</template>

<script>
    import FollowedBrowser from "./FollowedBrowser";
    import TalksList from "./TalksList";
    import  mapGetters  from "vuex";
    export default 
        data()
            return 
                talk: 
            
        ,
        components: 
            FollowedBrowser,
            TalksList
        ,
        methods: 
            addTalk(talk)
                this.talk = talk;
            ,
            talkAdded()
                this.talk = ;
            
        
    
</script>

这是我的两个孩子:

TalksList.vue

<template>
    <v-container class="my-0 px-5">

        <v-list flat>
            <v-list-item-group class="my-0">
                <div class="ma-0 pa-0" v-for="(talk, index) in talks" :key="index">
                    <v-divider v-if="talk.divider"></v-divider>
                    <v-list-item v-else class="px-2" style="cursor: pointer">
                        <template>

                            <v-list-item-avatar>
                                <v-img :src="correctedImageUrl(talk.recipient)"></v-img>
                            </v-list-item-avatar>

                            <v-list-item-content>
                                <v-list-item-title>
                                    <span class="blue--text text--lighten-1"> completeName(talk.recipient) </span>
                                </v-list-item-title>
                                <v-list-item-subtitle>
                                    <span> talk.recipient.username </span>
                                </v-list-item-subtitle>
                            </v-list-item-content>

                        </template>
                    </v-list-item>

                </div>
            </v-list-item-group>
        </v-list>
    </v-container>

</template>

<script>
    import axios from "axios";
    export default 
        data()
            return 
                talks: []
            
        ,
        props: 
            talk: 
                type: Object,
                default: null,
                required: true
            
        ,
        watch: 
            talk(val)
                if(val)
                    this.talks.splice(0, 1, val);
                    this.$emit("talkAdded");
                
            
        
    
</script>

FollowedBrowsed.vue

<template>
    <div style="display: inline">
        <v-dialog scrollable v-model="dialog" max- max->

            <v-card :loading="loading">
                <v-text-field dense outlined color="blue lighten-1" label="Nombre de usuario" class="px-5" append-icon="mdi-magnify" v-model="browsedUsername"/>
                <v-divider></v-divider>
                <v-card-text style="height: 300px;" class="px-2">
                    <v-list>
                        <v-list-item class="px-2" style="cursor: pointer" v-for="listUser in filteredFollowed" :key="listUser.id" @click.prevent="newTalk(listUser)">
                            <v-list-item-content>
                                <v-list-item-title>
                                    <span class="blue--text text--lighten-1"> completeName(listUser) </span>
                                </v-list-item-title>
                                    <v-list-item-subtitle>
                                        <span> listUser.username </span>
                                </v-list-item-subtitle>
                            </v-list-item-content>
                        </v-list-item>
                    </v-list>
                </v-card-text>
            </v-card>
        </v-dialog>
    </div>
</template>

<script>
    import  mapGetters  from "vuex";
    import axios from "axios";
    export default 
    data()
        return 
            browsedUsername: "",
            loading: false,
            dialog: false,
            skeleton: true,
            followed: []
        
    ,
    watch: 
        dialog(dialog)
            if(!dialog)
                this.browsedUsername = "";
                this.item = null;
            
        
    ,
    computed: 
        ...mapGetters(
            authenticated: "auth/authenticated",
            user: "auth/user"
        ),
        filteredFollowed()
            return this.followed.filter((user) => 
                return user.username.toLowerCase().indexOf(this.browsedUsername.toLowerCase()) !== -1;
            )
        
    ,
    mounted()
        axios.get("all_followers_followed/followed")
            .then((response) => 
                if(response.data)
                    this.followed = response.data;
                    this.skeleton = false;
                
            )
            .catch((error) => 
                console.log(error)
            );
  ,

  methods: 
     async newTalk(user)
        this.loading = "blue lighten-1";
        await axios.post("messages/new_talk", recipient_id: user.id)
           .then((response) => 
              if(response.data)
                 this.dialog = false;
                 this.$emit("newTalk", 
                    messages_number: 0,
                    recipient: user,
                    sender: this.user
                 );
              
           )
           .catch((error) => 
              console.log(error);
           );
     
  

当在FollowedBrowser 组件内部调用newTalk 方法时,会发出newTalk 事件,但之后我的屏幕会冻结,就像应用程序处于无限循环中一样,我不知道为什么。我省略了一些我认为不相关的代码。

谁能帮帮我。

提前致谢。

【问题讨论】:

我认为这是因为您的talk-list 收到了一个prop talk 并且在它更改时也会发出talkAdded,这将导致父级再次更改talk。因此是无限循环。 可能是,我想会是这样,但我想不出另一种解决方案将talk 对象传递给TalkList 组件...有什么想法吗? . 【参考方案1】:

我解决了...如此简单,我只需在TalksList 中获取talk 道具的副本,在watch 中输入以下内容:

watch: 
    talk(val)

        if(val)

            if(this.talks.length)
                this.talks.unshift( divider: true );
            

            let buffer = new Object();
            let talk = new Object();

            buffer.data = val;
            talk = buffer.data;

            this.talks.unshift(talk);
        
    
,

【讨论】:

以上是关于两个兄弟组件之间的数据传输问题(Vue js)的主要内容,如果未能解决你的问题,请参考以下文章

vue.js 组件之间传递数据

vue.js 组件之间传递数据

通俗易懂:Vue.js 组件之间传递数据

vue-兄弟组件传值

vue兄弟组件之间方法调用

React组件间通信