javascript - Vue js在子组件之间发送图像blob并显示图像预览

标签 javascript vue.js

我有具有这种结构的三个组件

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

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

我的问题是,当我将图像发送到图像中的第二个子网址时,图像是相同的,但图像不显示,仅显示 alt

1. child :

<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>

第二个 child :

<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) enter image description here

最佳答案

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

无论如何,继续解决你的问题。在您的 Child 2 上,您有以下行

items: this.tableData

此行会将 this.tableData 的值分配给 items。这只分配给组件的创建的钩子(Hook)部分。如果此表数据发生变化(我相当确定它会发生变化),则 item 变量将不会更新。您应该有一个 watch 来监视 Prop 并重新分配给 item

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

关于javascript - Vue js在子组件之间发送图像blob并显示图像预览,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60747711/

相关文章:

javascript - 在 SVN 窗口中缩小 JS 和 CSS 的步骤

javascript - createObjectURL 在 Chrome 中返回未定义

javascript - 使用 Snap.svg 在 z 空间中移动 SVG 组

css - 如何制作 v-tabs-items 和 v-tab-item 填充高度

javascript - 如何阻止 Android 硬件后退按钮在 react-native 的 react-navigation 中运行?

javascript - 使用 React Native 为数组中的每个对象打印图像

vue.js - 在子项 vueJS.2 之间切换 "active"类

vue.js - 如何创建导入另一个组件的 Vue 包

javascript - 无法使用命名空间 'ThemeDefinition' 作为 Vuetify 中的类型

mysql - 消息: "Method Illuminate\Validation\Validator::validateTazker does not exist."