Vue 2 将选定的数据发送回父组件

Posted

技术标签:

【中文标题】Vue 2 将选定的数据发送回父组件【英文标题】:Vue 2 Emit selected data back to parent component 【发布时间】:2018-11-16 17:02:40 【问题描述】:

正在努力解决如何从 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>

【问题讨论】:

【参考方案1】:

在 PostList.vue 中,将 v-on:selected-link="onSelectedLink" 从 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> 

【讨论】:

以上是关于Vue 2 将选定的数据发送回父组件的主要内容,如果未能解决你的问题,请参考以下文章

在设置子组件的数组状态并将其通过反应测验传递回父组件时出现问题

如何通过反应将数据从对话框发送回父容器?

React 功能组件 - 当组件返回元素数组时,如何将 refs 传递回父级?

Vue js - 多个组件,每个组件都有不同的初始选定值

React Insert功能-子组件问题

VueJs 2 点击似乎不起作用