最近在写Vue uploader组件
基本功能完成后,开始着手写测试
于是卡在了 input file 触发 change的问题
- 有问题就google吧! 放弃百度吧!
具体思路如下
如何往input里 设置文件呢?
let input = inputWrapper.element;
let file1 = new File(['xxx'],'xxx.txt');
let file2 = new File(['yyy'],'yyy.txt');
input.files[0] = file1;
input.files[1] = file2;
报错
TypeError: Failed to set an indexed property on 'FileList': Index property setter is not supported.
at Context.eval (webpack-internal:///./tests/unit/uploader.spec.js:53:20)
意思不能这样给 input 设置文件
那就尝试把 input 的文件变成数组
input.files = [file1,file2];
结果又报错了
TypeError: Failed to set the 'files' property on 'HTMLInputElement': The provided value is not of type 'FileList'.
求助 google 了
- google 搜索 js set files for input file 然后每个链接点进去
- 得到答案
里面有句信息如—— e.dataTransfer.files;
- 重点就是这个 dataTransfer
target.addEventListener('drop', (e) => {
e.preventDefault();
body.classList.remove('dragging');
fileInput.files = e.dataTransfer.files;
});
最后给了一个链接
-
这就是答案所在(我也开始讨厌写缩写的人了,写缩写简直就是zz,完全看不懂含义,非常容易让正在思考的大脑短路一下)
const dT = new ClipboardEvent('').clipboardData || // Firefox < 62 workaround exploiting https://bugzilla.mozilla.org/show_bug.cgi?id=1422655
new DataTransfer(); // specs compliant (as of March 2018 only Chrome)
dT.items.add(new File(['foo'], 'programmatically_created.txt'));
inp.files = dT.files;
<input type="file" id="inp">
- 修改我们的代码
const data = new DataTransfer();
data.items.add(file1);
data.items.add(file2);
input.files = data.files;
通过 google get到的 如何用js触发 input[type="file"] 的change 事件
拷贝代码在jsbin运行
let input = document.createElement('input');
input.type = 'file';
input.multiple = true;
let file1 = new File(['xxxxxxxxx'], 'xxx.txt');
let file2 = new File(['yyyyyyyyy'], 'yyy.txt');
input.addEventListener('change',()=>{
console.log(input.files);
})
const data = new DataTransfer()
data.items.add(file1)
data.items.add(file2);
input.files = data.files;
完美运行。把正确代码挪到测试代码里!悲剧发生了。
- 死活不触发 change 事件,而在 jsbin 里 运行正常。卡了一下午都没找到答案
- 继续 google (google就是神器啊!)
- 搜索 input file trigger change
- get到答案
- 如果js里不触发事件,你就构造个事件对象来模拟触发吧!
it('可以上传一个文件', () => {
const wrapper = mount(Uploader,{
propsData: {
name:'file',
action:'/upload',
method:'post',
parseResponse:()=>{},
fileList:[],
},
slots:{
default:`<button id="xxxx">上传</button>`,
},
listeners:{
'update:fileList':(fileList)=>{
wrapper.setProps({fileList})
}
}
});
console.log(wrapper.html())
wrapper.find('#xxxx').trigger('click');
console.log(wrapper.html()) // 点击 button会创建一个 input[type="file"] 步骤正确执行
let inputWrapper = wrapper.find('input[type="file"]');
let input = inputWrapper.element;
let file1 = new File(['xxxxxxxxx'], 'xxx.txt');
let file2 = new File(['yyyyyyyyy'], 'yyy.txt');
input.addEventListener('change',()=>{
console.log('change~~~~');
});
const data = new DataTransfer();
data.items.add(file1)
data.items.add(file2);
input.files = data.files;
// 解决 input.files 设置后 死活不触发 change事件
// google 搜索 input file trigger change
// 答案参考 https://gist.github.com/Lochlan/ccbe22e7c5e80b6d7966
var event = document.createEvent("UIEvents");
event.initUIEvent("change", true, true);
input.dispatchEvent(event);
});
结论
虽然无法解释为什么在 jsbin里 完美运行,但在 测试文件里 就不触发 input的change,但经过一通 google 依旧解决了问题!
- 有问题就 google 吧!
- 会一点英语的重要性