【问题标题】:Vue js send image blob between child components and show preview of imageVue js在子组件之间发送图像blob并显示图像预览
【发布时间】:2020-03-18 21:25:50
【问题描述】:

我有这个结构的三个组件

1.ParrentComponent(
  -1.ChildComponent
  -2.Child
)

1.Child 组件通过文件输入加载图像并在该控制器中进行预览。单击提交按钮后,我需要将此 blob 图像发送给第二个孩子并在那里显示该预览。

我的问题是当我将图像发送到图像中的第二个子 url 时,图像中的 URL 是相同的,但图像不显示,只是显示了 alt

1.孩子:

<template>
    <div id="insert-component">
        <div id="insert-new" >
            <h2 class="text-md-left">Nová kategória</h2>
            <div class="mt-2 text-left">
                <a href="#" id="img-button" class=" d-flex flex-wrap" v-on:click.stop="loadImage()">
                    <img v-bind:src="category_img" alt="logo" id="preview">
                    <input type="file" class="d-none" id="load-category-image"  v-on:input="handleFileSelected">
                    <button class="btn btn-dark btn-block" >Pridať obrázok</button>
                </a>
                <small class="text-danger d-none error" id="img-error">Súbor musí byť png, jpg alebo jpeg</small>
            </div>
            <div class="form-group mt-2 text-left">
                <div>
                <label for="category_name">Názov kategórie:</label>
                <input type="text" required name="name" class="form-control" v-model="category_name" id="category_name">
                <small class="text-danger d-none error"  id="name-error">*Názov je povinný</small>
                </div>
                <label for="category_description" class="mt-2">Popis kategórie:</label>
                <textarea name="description" class="form-control" rows="4" v-model="category_description" id="category_description">
                </textarea>
            </div>
        </div>
        <button class="btn btn-success btn-block my-2" v-on:click.prevent="submit()">Pridať kategóriu</button>
    </div>
</template>

<script>
    export default {
        name: "InsertComponent",
        props: [ 'updateTableData' ],
        data: function () {
            return {
                category_name: "",
                category_description: "",
                category_img:"/storage/images/no_image.png",
                file:null
            }
        },
        methods: {
            loadImage(){
                document.getElementById('load-category-image').click();
            },
            submit(){
                if(this.checkIfEmptyById('category_name')){
                    this.showErrors('name-error');
                    return
                }
                let item = this.createNewItem();
                this.updateTableData(item);
                this.clearInputs();
            },
            createNewItem(){
                return {
                    category_img: this.category_img,
                    category_name: this.category_name,
                    category_description: this.category_description,
                    created_at: null,
                    updated_at: null,
                    id: null,
                    file:this.file
                };
            },
            clearInputs(){
              this.category_name="";
              this.category_description="";
              this.category_img="/storage/images/no_image.png";
            },
            handleFileSelected() {
                let loadedFile = document.getElementById('load-category-image').files[0];
                if(this.checkIfFileIsImage(loadedFile))
                {
                    this.file = loadedFile;
                    //this.category_img="/storage/images/"+loadedFile.name;
                    this.changeImagePreview();
                }
                else{
                    //show image error
                    let imgError = document.getElementById('img-error');
                    imgError.classList.remove('d-none');
                }
            },
            checkIfFileIsImage(file){
                const acceptedImageTypes = ['image/jpg', 'image/jpeg', 'image/png'];
                return acceptedImageTypes.includes(file['type']);
            },
            changeImagePreview(){
                let loadedFile = document.getElementById('load-category-image').files;
                this.category_img = URL.createObjectURL(loadedFile[0]);
            },
        },
    }
</script>

第二个孩子:

<template>
    <div class="text-center">
        <b-table striped hover :items="items" :fields="fields">
            <template v-slot:cell(category_img)="data">
                <img v-bind:src="'/storage/images/'+data.item.category_img" alt="img" width="50px" height="50px" class="rounded-circle">
            </template>
            <template v-slot:cell(category_name)="data">
                {{data.item.category_name | capitalize}}
            </template>
            <template v-slot:cell(category_description)="data">
                {{data.item.category_description | capitalize}}
            </template>
            <template v-slot:cell(actions)="data">
                <div class="d-flex justify-content-center">
                <a href="#" class="btn btn-info mr-1"><i class="fas fa-edit"></i></a>
                <a href="#" class="btn btn-danger"><i class="fas fa-times-circle"></i></a>
                </div>
            </template>
        </b-table>
    </div>
</template>

<script>
    export default {
        name:"TableComponent",
        props: ['tableData'],
        data() {
            return {
                fields: [
                    {
                        key: 'category_img',
                        label:'Img',
                        sortable: false
                    },
                    {
                        key: 'category_name',
                        label:'Name',
                        tdClass: 'capitalize-first-letter',
                        sortable: true,
                        variant: 'dark'
                    },
                    {
                        key: 'category_description',
                        thClass: 'd-none d-md-block',
                        tdClass: 'd-none d-md-block text-left',
                        label:'Description',
                        sortable: false,
                    },
                    {
                        key: 'actions',
                        sortable: false,
                    }
                ],
                items: this.tableData
            }
        },

父组件只是在这些组件之间传递数据,并不重要,数据是否传递良好。问题只是那个图像。谢谢帮助

这看起来像:(右侧孩子 1,左侧孩子 2)

【问题讨论】:

    标签: javascript vue.js


    【解决方案1】:

    如果我错了,请纠正,但在您的 Child 中,您将函数作为道具传递,这在 vue 中是一种反模式。您应该始终遵循props down event up 设计模式。

    不管怎样,继续你的问题。在您的Child 2 上,您有以下行

    items: this.tableData
    

    此行会将this.tableData 的值分配给items。这仅在组件的已创建钩子部分上分配。如果此表数据发生更改(我很确定确实如此),item 变量将不会被更新。你应该有手表看道具并重新分配给item

    watch: {
      tableData: (value) => {
        this.item = value;
      }
    }
    

    【讨论】:

    • 1.Tsx 以获取具有该模式的提示。 2:是的,但我的组件现在正在更新。更新新数据没有问题。现在可以了。问题仅在该图像中,正如您在上图中看到的那样...右侧是预览还可以,但在 img 列的左侧,您可以在前两行看到不是。右侧的 img 只是 blob(我只是从我的电脑中选择它,它只是预览,尚未保存)
    • 您是否尝试过在 chrome 上检查它并查看 :src='...' 的值?
    • Ouuu 现在我可以看到它了...我在左侧有重复的 src 地址开头。谢谢帮助
    • @YoungL。如果此答案帮助您解决了问题,请将其标记为正确答案
    猜你喜欢
    • 1970-01-01
    • 2021-04-06
    • 2011-10-08
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    相关资源
    最近更新 更多