最近在开发过程中,遇到了一个陌生又熟悉的需求:选择文件夹。看似简单,实则有坑。本文记录了我的坑坑开采过程。

需求说明

用户选择一个文件夹(注意不是文件,而是文件夹),然后从前端获取文件夹的本地全局路径,进行其他一系列操作。

第一个想法

前端开发的第一个想法就是使用Input然后Typeu003dfile来获取文件路径,这样就可以获取到路径了。因此,我实现了一个版本:

函数 () {

让 inputObj u003d document.createElement('input');

inputObj.setAttribute('id', '_ef');

inputObj.setAttribute('类型', '文件');

inputObj.setAttribute('style', 'visibility:hidden');

inputObj.setAttribute('webkitdirectory', '');

inputObj.setAttribute('目录', '');

document.body.appendChild(inputObj);

inputObj.addEventListener('change', function (a,b,c) {

让 obj u003d document.getElementById('_ef');

让文件 u003d obj.files;

试试{

if (files.length > 1 || files.length u003du003du003d 0) {

console.log('请选择一个文件');

} 其他 {

控制台日志(文件);

}

obj.removeEventListener('change', function(){

console.log('删除更改事件监听成功');

});

document.body.removeChild(obj);

} 捕捉 (e){

控制台.错误(e);

}

});

inputObj.click();

}

新建一个隐藏的Input,监听Change事件,根据内部文件的路径获取文件夹的路径。但是,最终结果如下:

是的,你得到的不仅是相对路径,还有浏览器的系统提示,如下图,很不友好。通常我们在开发使用vscade的时候可以选择目录。我们该怎么做呢?

终端方案初探

搜索了一下,发现前端没有这个能力,浏览器也不会让你这样操作。因为测试工具使用的是 Electron,所以将注意力转向了终端。很快,就发现有人实现了。

根据文章:电子打开选择文件框这个功能简单实现:

但是当我在本地运行代码时,我惊喜地发现报错了。这是有毒的:

据说在Electron中的代码中引用了FS,然后因为找不到FS而报错。搜索后发现是Webpack 5,因为新版本的Webpack JS不再内置部分节点,所以当有依赖时,需要通过fallback手动导入:

但是,我发现核心模块中没有fs模块。好生气~

试一试

于是我开始尝试通过Externals引入Electron,是这样的:

不,它会报告require is not defined,即Externals会尝试写一个对编译文件的引用:

常量电子 u003d 要求('电子');

虽然可以写,但不能解析。无法达到介绍的效果,,,

试试两个

现在怎么解决引入Electron模块的问题,于是翻到Electron Api,发现有一个预加载的Api,可以在程序Dom加载后执行一些Js逻辑,

我很开心。我只要在Window下挂载模块,就可以进行前端调用,所以实现如下:

main.js

让 mainWindow u003d new BrowserWindow({

宽度:宽度,

高度:高度,

最小高度:338,

最小宽度:600,

显示:假,

自动隐藏菜单栏:真,

网络偏好:{

预加载:path.join(__dirname, 'preload.js')

}

});

preload.js

window.ipcRenderer u003d 需要('电子').ipcRenderer;

跑了之后还是看不懂!!!!窗口下没有ipcRenderer属性,但是preload里已经设置好了,所以定位到preload JS果然:

打印的对象实际上是一个全局对象。为什么?这里的窗口不是和前端窗口一样吗?我无法弄清楚实施有什么问题。

试三个

前端窗口没有这个属性,说明没有设置成功,或者不是同一个作用域的变量。再次查看API后,我们找到了线索:

! zoz100037](https://programming.vip/images/doc/f53085a1ab194076e18854205debb157.jpg)

在webPreferences的默认配置中,contextIsolation默认为True,即默认预加载脚本运行的上下文只能访问自己的特殊文档和全局窗口。那么,这就是设置 Window 属性失败的原因吗?所以尝试关闭它:

main.js

让 mainWindow u003d new BrowserWindow({

宽度:宽度,

高度:高度,

最小高度:338,

最小宽度:600,

显示:假,

自动隐藏菜单栏:真,

网络偏好:{

上下文隔离:假,

预加载:path.join(__dirname, 'preload.js')

}

});

成功!最后经过多次尝试,成功获取终端API,优雅实现文件夹选择功能。

总结

混合发展还需要调整思路。前端思维很容易碰壁。还有就是需要仔细阅读API,尤其是对于平时不是很熟悉的应用。互相鼓励。

Logo

前往低代码交流专区

更多推荐