详解Vue 普通对象数据更新与 file 对象数据更新


Posted in Javascript onApril 26, 2017

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

逻辑部分实现了以后,在更新进度条视图的时候出现一点问题:动态计算生产的进度 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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
地震发生中逃生十大法则
May 12 Javascript
关于javascript document.createDocumentFragment()
Apr 04 Javascript
兼容多浏览器的iframe自适应高度(ie8 、谷歌浏览器4.0和 firefox3.5.3)
Nov 04 Javascript
IE6/7/8中Option元素未设value时Select将获取空字符串
Apr 07 Javascript
jquery的attr方法禁用表单元素禁用输入内容
Jun 23 Javascript
jQuery设置和获取HTML、文本和值示例
Jul 08 Javascript
Javascript实现禁止输入中文或英文的例子
Dec 09 Javascript
JS实现的Select三级下拉菜单代码
Aug 20 Javascript
jquery判断复选框是否选中进行答题提示特效
Dec 10 Javascript
详解微信小程序开发—你期待的分享功能来了,微信小程序序新增5大功能
Dec 23 Javascript
详解使用React.memo()来优化函数组件的性能
Mar 19 Javascript
深入理解Vue的数据响应式
May 15 Vue.js
微信小程序实现给循环列表添加点击样式实例
Apr 26 #Javascript
微信小程序 request接口的封装实例代码
Apr 26 #Javascript
微信小程序中hidden不生效原因的解决办法
Apr 26 #Javascript
微信小程序 flex实现导航实例详解
Apr 26 #Javascript
微信扫码支付零云插件版实例详解
Apr 26 #Javascript
JavaScript实现的冒泡排序法及统计相邻数交换次数示例
Apr 26 #Javascript
微信小程序 实例开发总结
Apr 26 #Javascript
You might like
PHP计划任务、定时执行任务的实现代码
2011/04/23 PHP
IIS下PHP的三种配置方式对比
2014/11/20 PHP
php中print(),print_r(),echo()的区别详解
2014/12/01 PHP
php文件读取方法实例分析
2015/06/20 PHP
Laravel学习教程之request validation的编写
2017/10/25 PHP
ext form 表单提交数据的方法小结
2008/08/08 Javascript
jquery插件制作 表单验证实现代码
2012/08/17 Javascript
网页加载时页面显示进度条加载完成之后显示网页内容
2012/12/23 Javascript
jQuery实现动画效果的简单实例
2014/01/27 Javascript
一看就懂:jsonp详解
2015/06/01 Javascript
JavaScript的设计模式经典之代理模式
2016/02/24 Javascript
基于javascript实现最简单的选项卡切换效果
2016/05/16 Javascript
浅析JavaScript中的对象类型Object
2016/05/26 Javascript
AngularJs实现分页功能不带省略号的代码
2016/05/30 Javascript
纯js实现手风琴效果代码
2020/04/17 Javascript
Angular2生命周期钩子函数的详细介绍
2017/07/10 Javascript
React-Native使用Mobx实现购物车功能
2017/09/14 Javascript
JS运动改变单物体透明度的方法分析
2018/01/23 Javascript
详解datagrid使用方法(重要)
2020/11/06 Javascript
原生JavaScript实现换肤
2021/02/19 Javascript
对比Python中__getattr__和 __getattribute__获取属性的用法
2016/06/21 Python
Python合并字典键值并去除重复元素的实例
2016/12/18 Python
Python3.6.0+opencv3.3.0人脸检测示例
2018/05/25 Python
详解python3中tkinter知识点
2018/06/21 Python
Python 常用模块 re 使用方法详解
2019/06/06 Python
python随机数分布random均匀分布实例
2019/11/27 Python
python实现扑克牌交互式界面发牌程序
2020/04/22 Python
html5+css3实现一款注册表单实例
2013/04/17 HTML / CSS
【HTML5】Canvas绘制简单图片教程
2016/05/13 HTML / CSS
美国婴儿用品及配件购买网站:Munchkin
2019/04/03 全球购物
servlet面试题
2012/08/20 面试题
写好自荐信的几个要点
2013/12/26 职场文书
医学生职业规划范文
2014/01/05 职场文书
学雷锋演讲稿汇总
2014/05/10 职场文书
政法干警核心价值观心得体会
2014/09/11 职场文书
2016习总书记系列重要讲话心得体会
2016/01/15 职场文书