跟我一起使用electron搭建一个文件浏览器应用吧(三)
第二篇博客中我们可以看到我们构建的桌面应用会显示我们的文件及文件夹。
In the second blog, we can see that the desktop application we built will display our files and folders.
但是有一点就是它不能进行点击查看里面的内容,接下来我们继续改造我们的项目吧~
But one thing is that it can't Click to see the contents. Next, let's continue to transform our project.
第一步重构代码,将代码进行逻辑分组
The first step is to refactor the code and group it logically.
fileSystem.js
'use strict';
const async = require('async');
const fs = require('fs');
const osenv = require('osenv');
const path = require('path');
let shell;
if (process.versions.electron) {
shell = require('electron').shell;
} else {
shell = window.require('nw.gui').Shell;
}
function getUsersHomeFolder() {
return osenv.home();
}
function getFilesInFolder(folderPath, cb) {
fs.readdir(folderPath, cb);
}
function inspectAndDescribeFile(filePath, cb) {
let result = { file: path.basename(filePath), path: filePath, type: '' };
fs.stat(filePath, (err, stat) => {
if (err) {
cb(err);
} else {
if (stat.isFile()) {
result.type = 'file';
}
if (stat.isDirectory()) {
result.type = 'directory';
}
cb(err, result);
}
});
}
function inspectAndDescribeFiles(folderPath, files, cb) {
async.map(files, (file, asyncCb) => {
let resolvedFilePath = path.resolve(folderPath, file);
inspectAndDescribeFile(resolvedFilePath, asyncCb);
}, cb);
}
function openFile(filePath) {
shell.openItem(filePath);
}
module.exports = {
getUsersHomeFolder,
getFilesInFolder,
inspectAndDescribeFiles,
openFile
};
userInterface.js
'use strict';
let document;
const fileSystem = require('./fileSystem');
const search = require('./search');
const path = require('path');
function displayFolderPath(folderPath) {
document.getElementById('current-folder')
.innerHTML = convertFolderPathIntoLinks(folderPath);
bindCurrentFolderPath();
}
function clearView() {
const mainArea = document.getElementById('main-area');
let firstChild = mainArea.firstChild;
while (firstChild) {
mainArea.removeChild(firstChild);
firstChild = mainArea.firstChild;
}
}
function loadDirectory(folderPath) {
return function (window) {
if (!document) document = window.document;
search.resetIndex();
displayFolderPath(folderPath);
fileSystem.getFilesInFolder(folderPath, (err, files) => {
clearView();
if (err) {
return alert('Sorry, we could not load your folder');
}
fileSystem.inspectAndDescribeFiles(folderPath, files, displayFiles);
});
};
}
function displayFile(file) {
const mainArea = document.getElementById('main-area');
const template = document.querySelector('#item-template');
let clone = document.importNode(template.content, true);
search.addToIndex(file);
clone.querySelector('img').src = `images/${file.type}.svg`;
clone.querySelector('img').setAttribute('data-filePath', file.path);
if (file.type === 'directory') {
clone.querySelector('img')
.addEventListener('dblclick', () => {
loadDirectory(file.path)();
}, false);
} else {
clone.querySelector('img')
.addEventListener('dblclick', () => {
fileSystem.openFile(file.path);
},
false);
}
clone.querySelector('.filename').innerText = file.file;
mainArea.appendChild(clone);
}
function displayFiles(err, files) {
if (err) {
return alert('Sorry, we could not display your files');
}
files.forEach(displayFile);
}
function bindDocument (window) {
if (!document) {
document = window.document;
}
}
function bindSearchField(cb) {
document.getElementById('search').addEventListener('keyup', cb, false);
}
function filterResults(results) {
const validFilePaths = results.map((result) => { return result.ref; });
const items = document.getElementsByClassName('item');
for (var i = 0; i < items.length; i++) {
let item = items[i];
let filePath = item.getElementsByTagName('img')[0]
.getAttribute('data-filepath');
if (validFilePaths.indexOf(filePath) !== -1) {
item.style = null;
} else {
item.style = 'display:none;';
}
}
}
function resetFilter() {
const items = document.getElementsByClassName('item');
for (var i = 0; i < items.length; i++) {
items[i].style = null;
}
}
function convertFolderPathIntoLinks (folderPath) {
const folders = folderPath.split(path.sep);
const contents = [];
let pathAtFolder = '';
folders.forEach((folder) => {
pathAtFolder += folder + path.sep;
contents.push(`<span class="path" data-path="${pathAtFolder.slice(0,-1)}">${folder}</span>`);
});
return contents.join(path.sep).toString();
}
function bindCurrentFolderPath() {
const load = (event) => {
const folderPath = event.target.getAttribute('data-path');
loadDirectory(folderPath)();
};
const paths = document.getElementsByClassName('path');
for (var i = 0; i < paths.length; i++) {
paths[i].addEventListener('click', load, false);
}
}
module.exports = { bindDocument, displayFiles, loadDirectory, bindSearchField, filterResults, resetFilter };
app.js
'use strict';
const fileSystem = require('./fileSystem');
const userInterface = require('./userInterface');
const search = require('./search');
function main() {
userInterface.bindDocument(window);
let folderPath = fileSystem.getUsersHomeFolder();
userInterface.loadDirectory(folderPath)(window);
userInterface.bindSearchField((event) => {
const query = event.target.value;
if (query === '') {
userInterface.resetFilter();
} else {
search.find(query, userInterface.filterResults);
}
});
}
window.onload = main;
app.css
body {
padding: 0;
margin: 0;
font-family: 'Helvetica','Arial','sans';
}
#toolbar {
top: 0px;
position: fixed;
background: red;
width: 100%;
z-index: 2;
}
#current-folder {
float: left;
color: white;
background: rgba(0,0,0,0.2);
padding: 0.5em 1em;
min-width: 10em;
border-radius: 0.2em;
margin: 1em;
}
#main-area {
clear: both;
margin: 2em;
margin-top: 3em;
z-index: 1;
}
.item {
position: relative;
float: left;
padding: 1em;
margin: 1em;
width: 6em;
height: 6em;
text-align: center;
}
.item .filename {
padding-top: 1em;
font-size: 10pt;
}
#search {
float: right;
padding: 0.5em;
min-width: 10em;
border-radius: 3em;
margin: 2em 1em;
border: none;
outline: none;
}
span.path:hover, img:hover {
opacity: 0.7;
cursor: pointer;
}
index.html
<html>
<head>
<title>Lorikeet</title>
<link rel="stylesheet" href="app.css" />
<script src="app.js"></script>
</head>
<body>
<template id="item-template">
<div class="item">
<img class="icon" />
<div class="filename"></div>
</div>
</template>
<div id="toolbar">
<div id="current-folder"></div>
<input type="search" id="search" results="5" placeholder="Search" />
</div>
<div id="main-area"></div>
</body>
</html>
search.js
'use strict';
const lunr = require('lunr');
let index;
function resetIndex() {
index = lunr(function () {
this.field('file');
this.field('type');
this.ref('path');
});
}
function addToIndex(file) {
index.add(file);
}
function find(query, cb) {
if (!index) {
resetIndex();
}
const results = index.search(query);
cb(results);
}
module.exports = { addToIndex, find, resetIndex };
安装lunr.js他支持对文件夹和文件的搜索
Install lunr. js, which supports searching for folders and files
cnpm install lunr --save
这个lunr的版本号最好为0.7.2,不用最新的。
The lunr version number is best 0.7.2, not the latest.
运行项目我们可以看到效果为
We can see the effect of running the project is as follows

本文的例子学习自 <<跨平台桌面应用开发基于Electron与NW.js>>这本书
跟我一起使用electron搭建一个文件浏览器应用吧(三)的更多相关文章
- 跟我一起使用electron搭建一个文件浏览器应用吧(二)
这个文件浏览器应用可以具备以下两种功能噢- This file browser application can have the following two functions. 一:用户浏览文件夹和 ...
- 跟我一起使用electron搭建一个文件浏览器应用吧(四)
在软件的世界里面,创建一个新项目很容易,但是坚持将他们开发完成并发布却并非易事.分发软件就是一个分水岭, 分水岭的一边是那些完成的被全世界用户在用的软件,而另外一边则是启动了无数项目却没有一个完成的. ...
- Electron构建一个文件浏览器应用(一)
在window.mac.linux系统中,他们都有一个共同之处就是以文件夹的形式来组织文件的.并且都有各自的组织方式,以及都有如何查询和显示哪些文件给用户的方法.那么从现在开始我们来学习下如何使用El ...
- Electron构建一个文件浏览器应用(二)
在前一篇文章我们已经学习到了使用Electron来构建我们的文件浏览器了基础东西了,我们之前已经完成了界面功能和显示文件或文件夹的功能了,想看之前文章,请点击这个链接 .现在我们需要在之前的基础上来 ...
- Electron为文件浏览器创建图标(三)
在前面的文章中,请看之前文章,我们已经完成了使用 electron做文件浏览器这么一个应用,现在我们需要为应用创建图标操作.为应用创建图标以后,我们就可以从计算机中与其他应用区分开来,如果我们自己会做 ...
- django 搭建一个投票类网站(三)
之前修改index的视图的代码,工作原理是先试用loader方法加载视图,然后HTTPResponse方法初始化一个HTTPResponse对象并返回给浏览器.对于很多django视图来说,他们的工作 ...
- 如何搭建一个WEB服务器项目(三)—— 实现安卓端联网登录
安卓端调用服务器登录函数进行验证登录 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解,并不一定正确,希望不要误人子弟.欢迎各位大佬来评论区提出问题或者是指出错误,分享宝贵经验 ...
- 比nerdtree更好的文件浏览器:vimfiler
通过:VimFilerExplorer来打开一个文件浏览器 h:收起 t:展开 -:close 回车:进入或展开 空格:收起
- php写的非常简单的文件浏览器
php写的非常简单的一个文件浏览器,仅供参考. <?php /** * php文件浏览程序函数 showDir() * * $dirName 输入目录路径,默认php文件一级目录,不需输入: * ...
随机推荐
- 基于Python的ModbusTCP客户端实现
Modbus协议是由Modicon公司(现在的施耐德电气Schneider Electric)推出,主要建立在物理串口.以太网TCP/IP层之上,目前已经成为工业领域通信协议的业界标准,广泛应用在工业 ...
- 'config.h' file not found 解决过程
最近将ReactNative业务集成进现有APP项目中,出现了几个具有代表性的问题,下面记录一下 问题1. [!] CocoaPods could not find compatible versio ...
- 全景3d
Three.js Tour.js Run.js 3D Css3 酷家乐:https://www.kujiale.com/ 爱空间:http://bj.ikongjian.com/?utm_source ...
- Linux内核分析:期中总结
第一章:计算机是如何工作的 计算机大部分都是用冯诺依曼体系结构,即存储程序计算机. 两个层面: 1.硬件: cpu(IP寄存器:指针,指向内存的某块区域)——总线——内存(代码与数据) 2.程序员: ...
- Oracle 转移符问题
注:select '''' from dual; --输出一个单引号 select '''''' from dual; --输出两个单引号 select '''''''' ...
- 第三个Sprint ------第七天
APP.java代码 package com.app.senior_calculator; import java.io.Serializable; import java.util.ArrayLis ...
- Spring MVC静态资源处理(转)
原文地址: http://www.cnblogs.com/fangqi/archive/2012/10/28/2743108.html 优雅REST风格的资源URL不希望带 .html 或 .do 等 ...
- IO学习
---恢复内容开始--- 命名规则: 1.类名使用 UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外:(领域模型 的相关命名)DO / BO / DTO / VO 等. 2.方法名 ...
- python模块_pcharm导入包的问题
1.添加pip包 2.导入项目需要由内置包(library root)
- apache2.4.29安装脚本
#!/bin/bash . /etc/init.d/functions yum install -y expat-devel gcc gcc-c++ zlib-devel openssl-devel ...