首页 > 解决方案 > Vue 2 将选定的数据发送回父组件

问题描述

努力理清如何从 Typeahead 组件中获取选定的值以传递回父组件。我允许用户从各种数据中搜索以将记录链接到帖子。一旦用户单击其中一个预先输入的下拉记录,我就会将该项目传递给 sendlink 方法 - 我已经检查过数据是否正常传递。当我使用 selected-link 事件进行发射时,我没有在父组件中获取数据。

PostList.vue

<template>
    <div>
        <div v-if='posts.length === 0' class="header">There are no posts yet!</div>
            <form action="#" @submit.prevent="createPost()" class="publisher bt-1 border-fade bg-white" autocomplete="off">
                <div class="input-group">
                    <input v-model="post.content" type="text" name="content" class="form-control publisher-input" placeholder="What's the lastest?" autofocus>
                    <span class="input-group-btn">
                        <button type="submit" class="btn btn-primary">Post</button>
                    </span>
                </div>
                <span class="publisher-btn file-group">
                  <i class="fa fa-camera file-browser"></i>
                  <input type="file">
                </span>
            </form>
            <div @click="doit" v-on:selected-link="onSelectedLink">{{ modellink.name }}</div>
             <typeahead
                source="/api/typeahead"
                placeholder="Link Post to Trip, Business, etc"
                filter-key="title"
                :start-at="3">
             </typeahead> 
            <post v-for="post in posts"
                     :key="post.id"
                     :post="post"
                     @post-deleted="deletePost($event)">
            </post>
    </div>
</template>
<script>
    var axios = require("axios");
    import post from './PostItem.vue';
    import typeahead from './Typeahead.vue';
    export default {
        components: {
            post, 
            typeahead
        },
        props: ['postableId', 'postableType', 'model'],
        data: function() {
            return {
                modellink: {
                   "name": "n/a",
                   "description": "",
                   "id": null,
                   "model": "n/a"
                },
                post: {
                        id: 1,
                        content: "",
                        edited: false,
                        created_at: new Date().toLocaleString(),
                        user: {
                            id: 1,
                            name: '',
                        }
                    },
                posts: [
                    {
                        id: 1,
                        content: "",
                        edited: false,
                        created_at: new Date().toLocaleString(),
                        user: {
                            id: 1,
                            name: '',
                        }
                    }
                ]
            };
        },        
        created() {
            this.fetchPostsList();
        },

        methods: {
            onSelectedLink: function (talink) {
                alert(JSON.stringify(talink, null, 4));
                this.link = talink
            },
            doit() {
                alert(JSON.stringify(this.modellink, null, 4));
            },
            fetchPostsList() {
                if( this.postableId ) {
                    axios.get('/api/' + this.postableType + '/' + this.postableId + '/posts').then((res) => {
                        this.posts = res.data;
                    });
                } else {
                    axios.get('/api/post').then((res) => {
                        //alert(JSON.stringify(res.data[0], null, 4));
                        this.posts = res.data;
                    });
                }
            },

            createPost() {
                axios.post('api/post', {content: this.post.content, user_id: Laravel.userId, vessel_id: Laravel.vesselId })
                    .then((res) => {
                        this.post.content = '';
                        // this.post.user_id = Laravel.userId;
                        // this.task.statuscolor = '#ff0000';
                        this.edit = false;
                        this.fetchPostsList();
                    })
                    .catch((err) => console.error(err));
            },
            deletePost(post) {
                axios.delete('api/post/' + post.id)
                    .then((res) => {
                        this.fetchPostsList()
                    })
                    .catch((err) => console.error(err));
            },
        }
    }
</script>

Typeahead.vue

<template>
    <div>
        <input 
            v-model="query"
            @blur="reset"
            type="text" 
            class="SearchInput" 
            :placeholder="placeholder">     
            <transition-group name="fade" tag="ul" class="Results">
                <li v-for="item in items" :key="item.id">
                    <span @click="sendlink(item)">
                        <strong>{{ item.name }}</strong> - <small>{{ item.model }}</small><br>
                        <small>{{ item.description }}</small>
                    </span>
                </li>
            </transition-group>
             <p v-show="isEmpty">Sorry, but we can't find any match for given term :( </p>
    </div>
</template>

<script>
    var axios = require("axios");
    export default {
        name: 'Typeahead',
        props: {
            modellink: {
                type: Object,
                required: false
            },
            source: {
                type: [String, Array],
                required: true
            },
            filterKey: {
                type: String,
                required: true
            },
            startAt: {
                type: Number,
                default: 3
            },
            placeholder: {
                type: String,
                default: ''
            }
       },
        data() {
            return {
                items: [],
                query: '',
                taitem: ''
            }
        },
        computed: {
            lookup() {
                if(this.query.length >= this.startAt) {
                    axios.get(this.source + '/' + this.query).then((res) => {
                        this.items = res.data;
                        return res.data;
                    });
                }
            },
            isEmpty() {
                if( typeof this.lookup === 'undefined'  ) {
                    return false
                } else {
                    return this.lookup.length < 1
                }
            }
        },
        methods: {
            sendlink: function (taitem) {
              this.$emit('selected-link', taitem);
            },
            reset() {
                this.query = ''
            }            
        }
    }
</script>

标签: vue.jsvuejs2componentsvue-componenttypeahead

解决方案


在 PostList.vue 中,将v-on:selected-link="onSelectedLink"div 从 div 移动到 typeahead ,如下所示。当从子组件向父组件发出事件时,父组件上的侦听器需要位于子组件标签上才能工作。

 <div @click="doit">{{ modellink.name }}</div>
         <typeahead
            source="/api/typeahead"
            placeholder="Link Post to Trip, Business, etc"
            filter-key="title"
            :start-at="3"
            v-on:selected-link="onSelectedLink">
         </typeahead> 

推荐阅读