如何将对象数组作为道具传递给组件,然后将数组的成员作为道具传递给嵌套组件?

Posted

技术标签:

【中文标题】如何将对象数组作为道具传递给组件,然后将数组的成员作为道具传递给嵌套组件?【英文标题】:How can I pass down an array of objects as a prop to a component and then pass down the array's members as props to nested components? 【发布时间】:2016-12-18 21:10:48 【问题描述】:

在这篇文章的底部的编辑中,我说明了我想要完成的事情以及几乎已经奏效的事情

以下是我的应用程序,其中在应用程序上方定义了 <oo-upload><oo-uploads> 组件。本质上,<oo-uploads> 显示了一个 <oo-upload> 组件表,用于为我的应用程序构建文件上传插件。 uploads 变量是所有上传的列表,upload 定义每个单独的上传。

<body>

    <script type="x/template" id="oo-upload-template">
        <td>@ upload.file.name </td>
        <td>@ upload.file.size </td>
        <td>
            <div class="ui indicating progress floated" v-progress="upload.progress">
                <div class="bar"><div class="progress"></div></div>
            </div>
        </td>
        <td>
            <button class="ui primary button" v-on:click="upload" v-if="status < 1">Upload</button>
            <button class="ui red button" v-on:click="destroy" v-if="status == 2">Delete</button>
        </td>
    </script>

    <script type="x/template" id="oo-uploads-template">
        <table class="ui very basic table">
            <thead>
                <tr>
                    <th class="two wide">Filename</th>
                    <th class="two wide">Filesize</th>
                    <th class="ten wide">Status</th>
                    <th class="two wide">Actions</th>
                </tr>
            </thead>

            <tbody>
                <tr v-show="uploads.length==0">
                    <td colspan="4" class="ui center aligned">No files added!</td>
                </tr>
                <tr v-for="upload in uploads">
                    <oo-upload :upload="upload"></oo-upload>
                </tr>
            </tbody>

            <tfoot class="full-width">
                <tr>
                    <th colspan="4">
                        <div class="ui right floated small green labeled icon button" v-on:click="uploadDialog">
                            <i class="plus icon"></i> Upload File
                            <input type="file" style="display:none;" v-el:uploader v-on:change="addFiles" multiple>
                        </div>
                    </th>
                </tr>
            </tfoot>
        </table>
    </script>

    <div id="app">
        <div class="ui container">
            <oo-uploads :uploads="uploads"></oo-uploads>
        </div>
    </div>
    <script type="text/javascript" src="js/app.js"></script>
</body>

问题是objUpload 对象没有被传递给&lt;oo-upload&gt; 组件的每个实例。相反,Vue 调试器说组件被传递的是一个函数,而不是一个对象。 &lt;oo-uploads&gt; 接收 uploads 作为道具没有任何问题。

var Vue = require('vue'),
    VueRouter = require('vue-router'),
    VueResource = require('vue-resource'),
    Vuex = require('vuex'),
    VueValidator = require('vue-validator');

/*
PLUGINS
 */

Vue.use(VueResource);

/*
CUSTOM DIRECTIVES
 */

Vue.directive('progress', 
    bind: function () 
        $(this.el).progress();
    ,
    update: function (value) 
        $(this.el).progress('set percent', value);
    
);

/*
OBJECTS
 */

function objUpload (file) 
    this.progress = 0;
    this.file = file;
    this.status = 0;


/*
COMPONENTS
 */

Vue.component('oo-upload', 
    props: ['upload'],
    template: '#oo-upload-template',
    methods: 
        upload: function () 
            this.upload.status = 1;
            this.$http.post('/upload', this.upload.file,  progress: function (pe) 
                this.progress = Math.floor(pe.loaded/pe.total * 100);
            ).then(function (result) 
                this.upload.status = 2;
            , function (result) 
                this.upload.status = -1;
            )
        ,
        destroy: function () 

        
    
);

Vue.component('oo-uploads', 
    props: ['uploads'],
    template: '#oo-uploads-template',
    methods: 
        uploadDialog: function () 
            $(this.$els.uploader).click();
        ,
        addFiles: function () 
            var uploader = this.$els.uploader;
            for (var i = 0; i < uploader.files.length; i++) 
                var file = uploader.files[i];
                this.uploads.push(new objUpload(file));
            
        
    
)

/*
CONSTANTS
 */

Vue.http.headers.common['X-CSRF-TOKEN'] = $('meta[name="_token"]').attr('content');

/*
INSTANCE
 */

var vm = new Vue(
    el: '#app',
    data: 
        uploads: [],
    ,
);

编辑:如果我将uploads 数组直接传递给&lt;oo-uploads&gt; 内的&lt;oo-upload&gt; 的单个实例,它将整个数组向下传递就好了,但由于某种原因它不会遍历数组并传递只是 objUpload 对象。

EDIT2:本质上,我想要做的是将我传递的数据范围限制为该组件所需的数据。我希望上传组件仅对分配给它的上传起作用。我认识到我的实践可能很差,或者我的实现可能是不可能的,我只需要一个关于如何完成类似事情的指针。

【问题讨论】:

【参考方案1】:

根据Vue.js documentation

因此,建议在模板中始终使用单个根级别的普通元素。

尝试用tr 包裹oo-upload-template 并更改

<tr v-for="upload in uploads">
  <oo-upload :upload="upload"></oo-upload>
</tr>

<tr is="oo-upload" v-for="upload in uploads" :upload="upload"></tr>

Example fixed fiddle

【讨论】:

你知道为什么这些行显示在表格上方而不是 内作为行吗? 哎呀,忘了那个可怕的table case...docs中说的table只能包含thead、tbody、tfoot和tr,这些元素应该是table的直接子元素 因为自定义标签将被吊出,因此无法正确呈现。我已经更新了答案以使用is 我按照您的建议进行了所有更改,但直到我破坏了 upload 并将其属性单独传递为 &lt;tr is="oo-upload" v-for="upload in uploads" :file="upload.file" :status="upload.status" :progress="upload.progress"&gt;&lt;/tr&gt; 后它才开始工作。我不知道为什么...

以上是关于如何将对象数组作为道具传递给组件,然后将数组的成员作为道具传递给嵌套组件?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Reactjs 中的 useEffect 挂钩访问道具

为啥数组中的两个对象中只有一个作为道具传递?

使用 React Hooks 获取帖子并将它们作为附加道具传递给另一个组件

Vue.js - 如何将 prop 作为 json 数组传递并在子组件中正确使用?

VueJs:将动态组件作为道具传递给另一个组件并渲染它们

如何将对象(或关联数组)作为属性值传递给我的 Web 组件