如何将更新的数据传递给已经渲染的子 vue 组件

Posted

技术标签:

【中文标题】如何将更新的数据传递给已经渲染的子 vue 组件【英文标题】:How to pass updated data to already child vue component rendered 【发布时间】:2019-07-15 12:48:23 【问题描述】:

我正在尝试将一些 vars 更新到父组件中。我的情况是这样的:

我有一个父组件:

    import LugarListComponent from './LugarListComponent';
    import LugarAddComponent from './LugarAddComponent'

    export default 
        components:
            'lugar-list-component' : LugarListComponent,
            'lugar-add-component' : LugarAddComponent,
        ,
        data()
            return 
                show: false,
                nombre: '',
                desc : '',
            
        ,
        methods:
            showComponent: function () 
                this.show = true;
            ,
            hideComponent: function () 
                this.show = false;
            ,
            setLugar: function(lugar)
                this.show = true;
            
        ,
        mounted() 
            //console.log('Component mounted.')
        
    
<template>
    <div class="container">
        <h3>Lugares</h3>

        <div style="text-align: right">
            <button type="button" class="btn btn-primary" v-show="!show" v-on:click.prevent="showComponent"><i class="fa fa-plus"></i> Adicionar</button>
            <button type="button" class="btn btn-success" v-show="show" v-on:click.prevent="hideComponent"><i class="fa fa-arrow-left"></i> Regresar</button>
        </div>
        <br>

        <lugar-list-component v-show="!show" @setLugar="setLugar"></lugar-list-component>
        <lugar-add-component v-show="show" @hideComponent="hideComponent"></lugar-add-component>
    </div>
</template>

该组件有两个子组件,用于列出地点的 lugar-list 和用于添加地点的 lugar-add。当我显示其中一个时,我有一个用于控制的 show var。

我想编辑一个地方,但我想将数据发送到 lugar-add 以将他的值显示到此组件中,但我没有找到任何解决方案将变量更新为 lugar-add。这里我展示了这个组件的代码。

对于 lugar-add

export default 
        data()
            return 
                image: '',
                nombre: '',
                desc : ''
            
        ,
        methods: 
            onImageChange(e) 
                let files = e.target.files || e.dataTransfer.files;
                if (!files.length)
                    return;
                this.createImage(files[0]);
            ,
            createImage(file) 
                let reader = new FileReader();
                let vm = this;
                reader.onload = (e) => 
                    vm.image = e.target.result;
                ;
                reader.readAsDataURL(file);
            ,
            uploadImage()
                axios.post('/lugar',
                    image: this.image,
                    nombre: this.nombre,
                    desc: this.desc
                ).then(response => 
                    if(response.status == 200)
                        this.$emit('hideComponent')
                    
                );
            ,
            setAttributes(lugarEdit)
                console.log('disparado');
                this.nombre = lugarEdit.nombre;
                this.desc = lugarEdit.desc;
            
        ,
        mounted() 
            //console.log('Component mounted.');
            this.$on(
                'setAttributes',
                function(lugar) 
                    this.nombre = lugar.nombre;
                    this.desc = lugar.desc;
                
            );
        
<template>
    <div class="container">
        <div class="form-group">
            <label>Nombre</label>
            <input type="text" v-model="nombre" class="form-control" placeholder="Nombre del lugar">
        </div>

        <div class="form-group">
            <label for="descTexArea">Descripci&oacute;n</label>
            <textarea v-model="desc" class="form-control" id="descTexArea" rows="3"></textarea>
        </div>

        <div class="form-group">
            <label for="exampleFormControlFile1">Subir im&aacute;genes</label>
            <input type="file" v-on:change="onImageChange" class="form-control-file" id="exampleFormControlFile1">
        </div>

        <div class="form-group">
            <button type="button" class="btn btn-primary" @click="uploadImage">Adicionar</button>
        </div>


        <div class="col-md-3" v-if="image">
            <img :src="image" class="img-responsive"  >
        </div>
    </div>
</template>

这里我使用事件来隐藏这个组件并显示 lugar-list 组件。这是 lugar-list 的代码

export default 
        name: 'lugar-list-component',
        data:function()
            return 
                listLugares : [],
                id : '',
            
        ,
        methods:
            getLugares: function () 
                fetch('/lugar')
                    .then(response => response.json())
                    .then(res => 
                        this.listLugares = res;
                    )
            ,
            setId: function(id)
                this.id = id;
            ,
            removeLugar: function(id)
                this.id = id;
                axios.delete('lugar/'+id)
                    .then(response => 
                        this.getLugares();
                    );
            ,
            editLugar: function(id)
                this.id = id;

                axios.get('lugar/'+id)
                    .then(response => 
                        this.$emit('setLugar',response);
                    );
            ,
        ,
        mounted() 
            this.getLugares();
        
    
<template>
    <div class="container">

        <table class="table table-striped">
            <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">Nombre</th>
                <th scope="col">Desc.</th>
                <th scope="col">Fecha</th>
                <th scope="col">Acciones</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="(item, index) in listLugares">
                <th scope="row"> index+1 </th>
                <td> item.nombre </td>
                <td> item.desc </td>
                <td> item.created_at </td>
                <td>
                    <button type="button" class="btn btn-success" v-on:click.prevent="editLugar(item.id)"><i class="fa fa-edit"></i> Editar</button>
                    <button type="button" class="btn btn-danger" v-on:click.prevent="removeLugar(item.id)"><i class="fa fa-remove"></i> Eliminar</button>
                </td>
            </tr>

            </tbody>
        </table>


    </div>
</template>

希望你能理解我。谢谢。

【问题讨论】:

【参考方案1】:

我没有找到其他使用带参数的路由的解决方案,我相信这是最好的解决方案。

这是我的路线


        path: '/lugar', component: require('./components/lugar/LugarComponent').default,
        children: [
             path: '', component: LugarList ,
            
                path: 'add/:id?',
                name: 'lugarAdd',
                component: LugarAdd
            ,
            
                path: 'list',
                component: LugarList
            
        ]
    

添加地点的路线有一个可选参数。

现在,在 Add 组件中,我使用以下代码获取参数:

this.id = this.$route.params.id;
                this.modeEdit = true;

                axios.get('/lugar/'+this.id)
                    .then(response => 
                        this.nombre = response.data.nombre;
                        this.desc = response.data.desc;

                        for(let i = 0; i<response.data.images.length; i++)
                            this.image.push(response.data.images[i]);
                        
                    );

当我获得地点 ID 时,我会通过 axios 请求其信息。

【讨论】:

【参考方案2】:

从第一个子组件发出一个事件来更新父组件。然后将要更新的值作为道具传递给第二个子元素。

【讨论】:

我对此进行了测试。问题是我认为该组件确实被渲染了,我在 lugar-list 组件中有一个事件,用于通知父组件我要编辑的位置,“editLugar”。这个函数触发了父级的setLugar函数,这里我得到了位置,但我不知道如何发送这个新数据来添加组件。 我不确定你的意思。您只是想在子组件上触发一个动作,或者向它添加一些数据?如果你想添加一些数据,那么你应该将父组件中的所有数据都放在一个数据中。然后在从第一个孩子接收数据时,附加/更新父母的数据。然后,您将数据(始终是最新的)从父级传递给第二个子级作为道具。对 prop 的更改将自动反映在子组件中。

以上是关于如何将更新的数据传递给已经渲染的子 vue 组件的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据传递给嵌套的子组件vue js?

微信小程序如何将接口获取的数据传递给自定义组件

如何将一个组件中查询的数据传递给另一个组件以用作查询变量?

ReactJS - 如何将“全局”数据传递给深度嵌套的子组件?

Vue:将数据传递给动态组件

如何将数据传递给 Vue.js 中的路由器视图