BootstrapVue的v-for循环内b-form-file图片预览watch不生效如何解决
问题原因
你代码存在两个核心错误导致功能异常:
- 模板中
b-form-file的绑定语法错误:v-model是Vue内置的双向绑定指令,不需要额外加冒号,你写的:v-model会被解析为绑定名为v-model的自定义属性,无法实现和item.request的双向绑定,这是watch未触发的主要原因。 - watch处理逻辑错误:
files是数组,watch触发时newValue是整个files数组,你直接读取newValue.src相当于读取数组的src属性,得到的是undefined,自然无法完成base64转码,也不能给对应项的src赋值。
优化实现方案
更推荐使用b-form-file的@change事件处理上传逻辑,无需写复杂的深度监听,逻辑更清晰可控:
修正后模板代码
<template> <div> <div v-for="item in files" :key="item.id"> <b-button v-b-toggle="item.id" variant="danger btn-block mb-2"> Upload {{ item.id }}</b-button> <b-collapse :id="item.id" class="mt-2"> <div class="m-2 mt-3"> <table class="table table-striped mt-2"> <tbody> <div class="mt-3 mb-2 ml-1">Upload</div> <b-form-file v-model="item.request" placeholder="Upload ..." class="mb-2" @change="handlePreview(item)" ></b-form-file> <b-img v-if="item.src" :src="item.src" class="mb-3" fluid block rounded ></b-img> </tbody> </table> </div> </b-collapse> </div> </div> </template>
修正后脚本代码
<script> const base64Encode = (data) => new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(data); reader.onload = () => resolve(reader.result); reader.onerror = (error) => reject(error); }); export default { data() { return { files: [ { id: "1", src: null, request: null }, { id: "2", src: null, request: null }, { id: "3", src: null, request: null }, ], }; }, methods: { async handlePreview(item) { if (!item.request) { item.src = null return } try { item.src = await base64Encode(item.request) } catch(e) { item.src = null } } } }; </script>
补充说明
如果你坚持要使用watch实现,需要修改监听逻辑:遍历整个files数组,判断每一项的request是否存在且未生成对应的src,再执行转码逻辑。但这种方式会在数组任意值变化时都触发遍历,性能不如直接绑定@change事件。
内容的提问来源于stack exchange,提问作者patrick96
相关产品推荐
相关产品推荐

