【问题标题】:How to call a method in a Vue component from programmatically inserted component如何从以编程方式插入的组件调用 Vue 组件中的方法
【发布时间】:2020-01-14 18:06:45
【问题描述】:

我正在尝试从以编程方式插入的子组件调用方法。 这是我的代码。

MultipleFileUploader.vue

<template>

    <div class="form-group" id="multiple-file-uploader">
        <div>
            <multiple-file-uploader-part
                    :name="uploadername" :index="1"
                    @remove="deleteUploader" @fileselected="fileSelected($event)">
            </multiple-file-uploader-part>
        </div>
    </div>

</template>

<script>
    import MultipleFileUploaderPart from './MultipleFileUploaderPart.vue';
    let index_count = 1;
    export default {
        components: {
            'multiple-file-uploader-part':MultipleFileUploaderPart,
        },
        props: {
            uploadername: {
                type: String,
                default: 'files',
            }
        },
        data() {
            return {
                next_id:1,
            }
        },
        methods: {
            fileSelected: function (target) {
                var UploaderPart = Vue.extend(MultipleFileUploaderPart);
                new UploaderPart().$on('fileselected','fileSelected')
                    .$mount('#multiple-file-uploader');
            },
            deleteUploader: function (idToRemove) {
                this.uploaders = this.uploaders.filter(
                    uploaders_id => {
                        return uploaders_id.id !== idToRemove;
                    }
                )
            }
        },
    }
</script>

<style scoped>

</style>

MultipleFileUploaderPart.vue

<template>
    <div v-bind:id="name + '['+index+']'">
        <div class="input-group margin">
            {{index}}
            <input type="file" accept="application/pdf,image/jpeg,image/png"
                   v-bind:name="name + '['+index+']'"
                   v-on:change="fileSelectedMethod($event.target)">
            <div class="input-group-btn">
                <button @click="removeClicked"
                        class="btn btn-danger btn-sm"
                        v-if="index != 1"
                        type="button">
                    Delete{{index}}
                </button>
            </div>
        </div>
        <p v-if="size_error" style="color: red">File size must be less than 2MB</p>
    </div>
</template>

<script>
    export default {
        props: {
            name: {
                type: String,
            },
            index: {
                type: Number,
            },
        },
        data() {
            return {
                size: '',
                size_error: false,
            }
        },
        methods: {
            removeClicked: function () {
                document.getElementById(this.name+'[' + this.index + ']' ).remove();
                this.$emit('remove', this.index);
            },
            fileSelectedMethod: function (target) {
                this.size = target.files[0].size;
                if (this.size < 2000000) {
                    this.size_error = false;
                    this.$emit('fileselected', target);
                } else {
                    target.value = null;
                    this.size_error = true;
                    console.log(target.files);
                }
            }
        }
    }
</script>

<style scoped>

我想要实现的是,当一个文件输入被一个文件填充时,会创建一个MultipleFileUploaderPart。并且当这个组件中的文件输入元素被填充时,另一个MultipleFileUploaderPart被插入。

我想从新插入的组件中调用 MultipleFileUploaderfileSelected 方法,以便创建另一个组件。

我还想在单击删除按钮时删除MultipleFileUploaderPart 组件。

我怎样才能做到这一点?还是有更好的方法?

编辑: 这是我最初拥有的。 MultipleFileUploader.vue

<template>

    <div class="form-group">
        <div>
            <multiple-file-uploader-part
                    v-for="uploader in uploaders"
                    :name="uploadername" :index="uploader.id"
                    @remove="deleteUploader" @fileselected="fileSelected($event)">
                slot
            </multiple-file-uploader-part>
        </div>
    </div>

</template>

<script>
    import MultipleFileUploaderPart from "./MultipleFileUploaderPart";

    let index_count = 1;
    export default {
        //name: "MultipleFileUploader",
        components: {MultipleFileUploaderPart},
        props: {
            uploadername: {
                type: String,
                default: 'files',
            }
        },
        data() {
            return {
                uploaders: [
                    {
                        id: index_count++,
                    },
                ]
            }
        },
        methods: {
            fileSelected: function (target) {
                if(target.value){
                    this.uploaders.push({
                        id: index_count++,
                    })
                }

            },
            deleteUploader: function (idToRemove) {
                this.uploaders = this.uploaders.filter(
                    uploaders_id => {
                        return uploaders_id.id !== idToRemove;
                    }
                )
            }
        },
    }
</script>

MultipleFileUploaderPart.vue

<template>
    <div class="input-group margin">
        {{index}}
        <input type="file" accept="application/pdf,image/jpeg,image/png"
               v-bind:name="name + '['+index+']'"
               v-on:change="fileSelectedMethod($event.target)">
        <div class="input-group-btn">
            <button @click="$emit('remove',index)"
                    class="btn btn-danger btn-sm"
                    v-if="index != 1"
                    type="button">
                Delete{{index}}
            </button>
        </div>
        <br>
        <p v-if="size_error" style="color: red">File size must be less than 2MB</p>
    </div>

</template>

<script>
    export default {
        props: {
            name: {
                type: String,
            },
            index: {
                type: Number,
            },
        },
        data() {
            return {
                size: '',
                size_error: false,
            }
        },
        methods: {
            checkFileSize: function () {

            },
            fileSelectedMethod: function (target) {
                console.log(target);
                console.log(target.files);
                this.size = target.files[0].size;
                console.log(this.size);
                if (this.size < 2000000) {
                    this.size_error = false;
                    this.$emit('fileselected', target);
                } else {
                    target.value = null;
                    this.size_error = true;
                    console.log(target.files);
                }
            }
        }
    }
</script>

And this happens. please click

当我单击“删除”按钮时,正确的子组件被删除,但输入表单中的文件仍保留在那里。这就是我寻求另一种方法的原因。

【问题讨论】:

    标签: javascript vue.js vuejs2


    【解决方案1】:
    1. uploaders 声明为一个对象数组,其中包含创建 MultipleFileUploaderPart 所需的所有道具。
    2. 在主 MultipleFileUploader 中的 MultipleFileUploaderPart 上使用 v-for 以反应性生成 MultipleFileUploaderPart 组件
    3. 使用从 MultipleFileUploaderPart 到 MultipleFileUploader 的 $emit 来发出创建和删除事件,以便 MultipleFileUploader 可以添加或删除 uploaders 数组中的元素。
    4. 请不要直接从 DOM 中删除或创建元素,让 VueJ 来完成这项工作。

    【讨论】:

    • 感谢您的回答。实际上,这就是我首先尝试的。这不起作用。组件被添加和删除,但文件输入中的文件仍然存在。我编辑了这个问题。请检查。
    • 至少你必须在声明 v-for="uploader in uploaders" 的地方添加 :key="uploader.id"。
    • 是的,有 uploader.id 作为 :index="uploader.id" 传递的。不是 ;key 但没关系,对吧?
    猜你喜欢
    • 1970-01-01
    • 2017-09-03
    • 2021-05-16
    • 2020-02-12
    • 2016-05-01
    • 1970-01-01
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多