最近在做一个多图片上传的组件,需求是做到多文件依次上传,并显示上传进度条。

逻辑部分实现了以后,在更新进度条视图的时候出现一点问题:动态计算生产的进度 progress 属性不会自动更新。

原来的代码是这样写的:

let files = this.filePicker.files;
if(!files.length) {
return;
} let arr = [];
for(let i = 0, len = files.length; i < len; i++) {
let item = files[i];
// 每个文件初始进度为0
item.progress = '0'; arr.push(obj);
} this.fileArr = arr;

这里直接将 file 对象添加一个 progress 属性记录上传进度,并初始化为0,然后上传时候实时计算更新 progress。但奇怪的是这个 progress 在视图里并不会自动更新,岿然不动,一直都是0。还了N中办法,百思不得其解。

后来一怒之下做了一个小 demo,看看问题到底出现在哪里,把不想关的代码都剔除,只保留核心代码,并用最简单的数据来模拟一下。代码如下:

// 用数组模拟 files, 用对象模拟 file 对象
let files = [];
for(let i = 0, len = 5; i < len; i++) {
let obj = {name: 'name_' + 1}; files.push(obj);
} let arr = [];
for(let i = 0, len = files.length; i < len; i++) {
files[i].progress = '0';
arr.push(files[i]);
}

这里仅仅是把 files 对象换成了数组来模拟,把 file 对象换成了普通对象模拟。

神奇的是,这样居然就自动更新了。

由于文件 file 后来都保存在数组里,这说明唯一的区别就在 file 对象上面!于是打算用普通对象保存 file 对象的属性再试试。

let files = this.filePicker.files;
if(!files.length) {
return;
} let arr = [];
for(let i = 0, len = files.length; i < len; i++) {
let item = files[i];
let obj = {}; obj.name = item.name;
obj.size = item.size; obj.progress = '0'; arr.push(obj);
}

这样视图也是可以自动更新的,果然是 file 对象和普通对象的区别。

它们究竟是什么区别呢?看一下他们的类型先。

console.log('files type', Object.prototype.toString.call(files));
// files type [object FileList]
console.log('arr type', Object.prototype.toString.call(arr));
// arr type [object Array] console.log('item type', Object.prototype.toString.call (files[0]));
// item type [object File]
console.log('obj type', Object.prototype.toString.call (obj));
// obj type [object Object]

原来 files 是 FileList 类型,file 是 File 类型。而普通的 obj 是 Object 类型。

Vue 的数据更新利用的是 Object.defineProperty 的 getter setter 函数来实现的,而 Vue 默认没有对 File 对象设置 getter setter, 因此用 File 对象不会自动更新。

解决办法,就是用普通对象保存 file 对象里需要的信息,然后用来构造视图数据。或者自己手动设置 File 对象的 setter,也可以自动更新。代码如下:

<div id="app">
<input type="text" id='a'>
<span id='b'></span> <input type="file" id='file'>
<button type="button" id='button'>点击更改file属性</button>
</div> <script>
// 普通对象设置 setter
var obj = {};
Object.defineProperty(obj, 'hello', {
set: function(newVal) {
document.getElementById('a').value = newVal;
document.getElementById('b').innerHTML = newVal;
}
}); document.addEventListener('keyup', function(e){
obj.hello = e.target.value;
}); // File 对象设置 setter
var fileInput = document.getElementById('file');
var file;
fileInput.addEventListener('change', function(e){
file = fileInput.files[0]; Object.defineProperty(file, 'progress', {
set: function(newVal) {
// document.getElementById('a').value = newVal;
document.getElementById('b').innerHTML = newVal;
}
});
}); document.getElementById('button').addEventListener('click', function(){
file.progress = 'hello file';
}); </script>

Vue 普通对象数据更新与 file 对象数据更新的更多相关文章

  1. HTML5 File 对象

    实例说明1: <div class="container"> <input type="file" id="file" m ...

  2. File对象的常用方法

    File对象不仅可以表示文件,还可以表示目录,源码注释是这么说的:An abstract representation of file and directory pathnames. File类最常 ...

  3. 用TypeScript开发Vue——如何通过vue实例化对象访问实际ViewModel对象

    用TypeScript开发Vue--如何通过vue实例化对象访问实际ViewModel对象 背景 我个人很喜欢TypeScript也很喜欢Vue,但在两者共同使用的时候遇到一个问题. Vue的实例化对 ...

  4. AIR 中的 File 对象 所访问的文件夹位置

    AIR 中的 File 对象 所访问的文件夹位置 Link 关于File.cacheDirectory的一点说明 According to the Apple guidelines, data tha ...

  5. Python 读写文件和file对象(转)

    1.open使用open打开文件后一定要记得调用文件对象的close()方法.比如可以用try/finally语句来确保最后能关闭文件. file_object = open('thefile.txt ...

  6. 标准I/O库之流和FILE对象

    对于标准I/O库,它们的操作是围绕流(stream)进行的.当用标准I/O库打开或创建一个文件时,我们已使一个流与一个文件相关联. 对于ASCII字符集,一个字符用一个字节表示.对于国际字符集,一个字 ...

  7. 关于Android Assets读取文件为File对象

    关于Android Assets读取文件为File对象的问题,在Assets里面放置文件,在使用的时候,一般是使用AssetManger对象,open方法获取InputStream 然后进行其他操作. ...

  8. 相对路径与绝对路径构造file对象

    package file; import java.io.File; public class FileTest1 { public static void main(String[] args) { ...

  9. VBS基础篇 - 对象(5) - File对象

    VBS基础篇 - 对象(5) - File对象   描述:提供对文件所有属性的访问,从FSO对象的GetFile方法获得. 使用File对象        要用File对象模型来编程必须先用FileS ...

随机推荐

  1. solr query的post方式

    众所周知, solr 是通过 GET 方式来进行查询的. 那么solr 是否支持POST 方式进行查询呢? 通过一番调研,发现SOLR其实是支持POST方式进行查询的. 方式为: 使用form 方式提 ...

  2. 持续集成接口自动化-jmeter+ant+jenkins(一)

    ant 批量执行Jmeter 一.环境准备 1.JDK环境:http://www.oracle.com/technetwork/java/javase/downloads/index.html 2.A ...

  3. HBase架构

    文章作者:luxianghao 文章来源:http://www.cnblogs.com/luxianghao/p/6573817.html  转载请注明,谢谢合作. 免责声明:文章内容仅代表个人观点, ...

  4. 菜鸟Scrum敏捷实践系列(三)用户故事的组织---功能架构的规划

    菜鸟Scrum敏捷实践系列索引 菜鸟Scrum敏捷实践系列(一)用户故事概念 菜鸟Scrum敏捷实践系列(二)用户故事验收 菜鸟Scrum敏捷实践系列(三)用户故事的组织---功能架构的规划 采用Sc ...

  5. jquery.zclip.js 不起作用

    最近有用到复制的这个功能,选用jQuery的插件,正常使用的时候,没有任何问题: $('#copy_mobile_watch_address').zclip({ path: '/dist/plugin ...

  6. pcntl_fork 导致 MySQL server has gone away 解决方案

    pcntl_fork 前连数据库,就会报 MySQL server has gone away 错误.原因是子进程会继承主进程的数据库连接,当mysql返回数据时,这些子进程都可以通过这个连接读到数据 ...

  7. flex与后台及页面间对象的传递

    1.从flex中发送请求后,利用<s:RemoteObject/>启用回调方法,类似于jQuery的post函数: <fx:Declarations>        <s ...

  8. CSS常见兼容性问题总结

    原文链接:渔人码头 http://www.cnblogs.com/imwtr/p/4340010.html?utm_source=tuicool&utm_medium=referral 浏览器 ...

  9. 自适应滤波——线性预测(LPC)

    作者:桂. 时间:2017-03-26  10:12:07 链接:http://www.cnblogs.com/xingshansi/p/6621914.html 声明:欢迎被转载,不过记得注明出处哦 ...

  10. 【Hexo】(一)使用HEXO配置环境,创建Hello World

    现场直播,呵呵,就是我完成一步,就记录一下: 一.配置环境 1.安装 Node 下载地址:Node.js 2.安装 Git(win环境下) 下载地址:Git Git 绑定 GitHub账户: ①打开G ...