(и Vue)

Обновлено: исходные коды в этой статье были изначально для Quasar Framework v0.17 (затем были обновлены до Quasar Framework v1.0.0). Я переписал проводник, чтобы использовать Quasar Framework v2 (Vue 3). Вы можете получить доступ к новому репо здесь.

Введение

Что такое Электрон?

Electron - это фреймворк, который позволяет создавать кроссплатформенные настольные приложения с использованием javascript, HTML и CSS.

Если вы можете создать веб-сайт, вы можете создать настольное приложение. Electron - это платформа для создания собственных приложений с использованием веб-технологий, таких как JavaScript, HTML и CSS. Он заботится о сложных частях, поэтому вы можете сосредоточиться на ядре вашего приложения.

С Electron вы получаете два процесса: основной процесс и процесс рендеринга. Вы можете рассматривать основной процесс как внутренний код, а процесс рендеринга - как внешний код.

Домашняя страница Электрон

Что такое Квазар?

Quasar Framework - это перспективный фреймворк с открытым исходным кодом под лицензией MIT, работающий на Vue.

С Quasar вы можете построить:

1. SPA (одностраничное приложение)
2. SSR (серверное приложение с рендерингом) (+ дополнительное управление клиентом PWA)
3. PWA (прогрессивное веб-приложение)
4. Мобильные приложения ( Android, iOS,…) через Apache Cordova
5. Многоплатформенные настольные приложения (с использованием Electron)

По сути, это универсальное решение для веб-разработчиков с богатым набором компонентов, основанных на инновационных идеях и концепциях, которые снимают боль (также известную как метод Квазара для квазарианцев) управления проектом с помощью eslint, webpack. , babel и т. д., чтобы вы могли продолжить разработку своего приложения (веб, настольного компьютера или мобильного устройства).

Домашняя страница Quasar Framework

Что такое проводник?

Файловый менеджер - это графический пользовательский интерфейс (GUI), который позволяет пользователю визуализировать файловую систему операционной системы и перемещаться по ней.

Зачем нужен учебник?

Почему нет?

Помимо сарказма, позвольте мне сказать несколько вещей. Я работаю с Vue изо дня в день и использую Quasar Framework. Мы совместно приняли это решение еще в сентябре 2017 года. Использовать Vue и тем более Quasar было рискованно. С тех пор, на момент написания этой статьи, Vue (120k) имеет больше звезд на Github, чем React (116k) или Angular (42k), а популярность Quasar (7,7k) быстро растет благодаря своему универсальному устройству. решение. Пока что мы чувствуем, что наша ставка окупилась пиками, поскольку мы готовимся к выпуску 5.0 нашего продукта (Домашняя страница IntelliView Technologies) после преобразования с Angular.

Хорошо, вернемся к почему учебник? В нашем продукте есть интеллектуальная камера, которая создает видео с предупреждениями, которые Пользователи могут экспортировать на свои компьютеры, а также архивировать видео. С этим видео у нас есть настраиваемый SVG, который запускается как наложение поверх видео, чтобы пользователь мог видеть аналитику. Поскольку SVG является настраиваемым, нам нужно было написать автономную программу просмотра для этих экспортированных видео, которая также может воспроизводить связанный SVG в качестве наложения. Таким образом, мы использовали Electron и Quasar для разработки специального настольного приложения, которое соответствует нашим потребностям. Итак, да, у меня нет такого опыта работы с Electron, но я кое-чему научился, и в этом уроке я поделюсь с вами.

Об учебнике

Это не полное руководство с пошаговыми инструкциями. Исходный код проекта находится в свободном доступе, и вы можете загрузить или разветвить проект и расширить его.

Я буду обсуждать проектные решения, решения по кодам, электронную безопасность и выделю различные проблемы и задачи кодирования, которые мне пришлось преодолеть, чтобы создать этот проект. Возможно, вы уже являетесь опытным программистом, знакомым со всем, что я хочу сказать, или вы просто можете узнать что-то, о чем не знали. В любом случае, это в основном история событий, которые позволили реализовать этот проект.

Дизайнерские решения

Конечная цель

Конечная цель - иметь файловый менеджер, который может просматривать файловую систему пользователя. Я хочу, чтобы он работал как с Linux, так и с Windows, поскольку мы делаем настольное приложение. Однако, поскольку я в основном разработчик Linux (C ++ и Web), мне нужно получить копию Windows для работы. У Microsoft есть виртуальная машина (виртуальная машина) с предустановленной Windows 10, которую вы можете скачать и которая имеет 90-дневный лимит. Это будет отлично работать! Я могу использовать Virtual Box для импорта виртуальной машины и установки всех моих инструментов и одновременной работы в Linux и Windows. Если бы Apple сделала виртуальную машину для Mac, я бы обязательно позаботился о том, чтобы она работала и для этого.

Одна вещь, которую мне нужно было иметь в виду, - это то, что в Linux файловая система находится в одной иерархии. Все файлы и папки находятся в корне. Windows отличается тем, что каждый жесткий диск - это, по сути, корень файлов и папок, содержащихся на жестком диске. Это будет проблемой, так как мне нужно будет получить жесткие диски, используемые Windows, а затем обращаться с каждым как с корневым.

Существующие проводники файлов

Взглянем на проводник Windows:

Давайте посмотрим на файлы Ubuntu:

Оба обозревателя файлов предлагают режимы сетки и списка. У них также есть (необязательная) адресная строка вверху. Слева находится разноплановая навигация. Затем есть область содержимого посередине, в которой отображаются как файлы, так и папки.

Дизайн

Я хочу сохранить похожий внешний вид, чтобы пользователь уже был знаком с использованием моего файлового проводника с первого запуска.

Вот что я сделаю:

  1. Имейте доступную только для чтения адресную строку, которая показывает текущий путь. Я назову ее строкой навигации. Для каждой части пути пользователь сможет щелкнуть по ней, чтобы упростить обратный переход.
  2. Показывать ярлыки слева. Это покажет ссылки на ряд заранее определенных путей. И Windows, и Linux разделяют эту концепцию. Например, папки главная, документы и загрузки. Я не хочу жестко кодировать это, поэтому мне придется исследовать, есть ли способ получить их через Electron.
  3. Под ярлыками я хочу показать дерево обхода, которое расширяет каждую папку, чтобы показать дополнительные папки. Я смогу использовать для этого компонент Quasar QTree. Он обеспечивает ленивую загрузку каждого узла дерева, так что это будет идеально, поскольку я хочу загружать данные по запросу, чтобы все работало быстро.
  4. В основной области содержимого я хочу показать содержимое папки. Содержимое может содержать другие папки, а также файлы. Я хочу отобразить имя файла и отобразить значок, представляющий тип MIME для наиболее часто используемых файлов. В области содержимого я также хочу, чтобы пользователь мог переключаться между представлениями сетки и списка. И, наконец, если пользователь дважды щелкнет папку в области содержимого, пользовательский интерфейс перейдет к выбранной папке.
  5. В области содержимого, если во время просмотра добавляются, удаляются, изменяются дополнительные файлы, они обновляются автоматически. Есть отличный пакет под названием Chokidar, который я могу использовать для просмотра файлов и отправки уведомлений.
  6. Наконец, если файл представляет собой изображение, а не общий значок, я хочу показать эскиз фактического изображения.

Вот что я не буду делать:

  1. Двойной щелчок по файлу не откроет его. Хотя это было бы неплохо, в настоящее время это не входит в мои задачи.
  2. Пользователь не сможет создавать, удалять или изменять файлы. Это будет приложение только для чтения, чтобы обеспечить только возможности проверки концепции.
  3. Пользователь не сможет получить информацию (свойства) о выбранном файле.

В общем, пользователь не может ничего делать, кроме как перемещаться по файловой системе.

Эти элементы, скорее всего, я сделаю, если расширю этот проект с помощью дополнительных функций.

Проблемы безопасности

Как я выяснил, у Electron есть проблемы с безопасностью, в зависимости от того, сколько мощности вы ему даете. Я хочу быть уверенным, что ограничиваю Electron, при этом сохраняя необходимую мне мощность. Что касается этого аспекта, при настройке Electron я позабочусь о том, чтобы использовать следующее:

На самом деле это настройка по умолчанию для этой опции. Но я действительно хотел выделить это здесь.

Если задано значение false, политика одного и того же происхождения будет отключена (обычно с использованием проверенных людьми веб-сайтов) и для параметра allowRunningInsecureContent будет установлено значение true, если эти параметры не были установлены пользователем. По умолчанию верно.

Вы можете прочитать о других опциях здесь.

Это создает дополнительную проблему, поскольку вы больше не можете использовать протокол file: // в процессе средства визуализации. В этом случае я хочу иметь возможность показывать эскизы файлов на основе изображений. Итак, мне нужно передать их из основного процесса в процесс рендерера через экземпляр веб-сервера, например express.

Квазар

Quasar позволяет легко начать работу. Но, во-первых, вы должны установить его глобально. Вы можете сделать это, набрав npm install -g quasar-cli ( edit: теперь он заменен на npm install -g @ quasar / cli) . После глобальной установки вы можете получить к нему доступ, так как теперь он находится на вашем пути.

Чтобы начать проект, из командной строки:

quasar init имя-проекта

Это создаст новую папку на основе вашей текущей папки и запустит процесс формирования шаблонов. Но сначала вам зададут несколько вопросов о вашем проекте:

Чтобы запустить веб-приложение, вы можете набрать quasar dev или создать готовый к работе веб-сайт с помощью quasar build .

На данный момент я не сказал Quasar добавить Electron. Итак, я набираю:

quasar dev -m electronic -t mat

Quasar обнаружит, что необходимо установить Electron, сделает это, а затем продолжит сборку для разработки.

Система папок, которую создает Quasar, логична и проста для понимания:

Очень приятная особенность Quasar - макеты. По сути, это контроллер для макета страницы, и вы создаете страницы и компоненты, которые будут загружены в ваш макет. Для большей части своей работы я использую только один макет, но у вас может быть несколько вариантов, в зависимости от ваших потребностей.

Я хочу, чтобы Quasar создал страницу для использования с помощью команды quasar new ‹something›:

$ quasar новый

Вот что я буду создавать:

  1. Основной макет: автоматически создается Quasar при инициализации проекта.
  2. Страница содержимого с использованием этой команды Quasar: quasar new p contents
  3. А затем наши компоненты: хлебные крошки, ярлыки, folderTree, gridItem и gridItemImage. Их можно создать сразу с помощью этой команды Quasar: quasar new p хлебные крошки, ярлыки, folderTree, gridItem, gridItemImage

На всякий случай, мой компонент gridItem будет содержать изображение и текст и будет отображаться в области содержимого как в режиме сетки, так и в режиме списка проводника файлов. Компонент gridItemImage будет дочерним по отношению к компоненту gridItem и будет отвечать за отображение изображений. Это может быть типовой значок, основанный на MIME-типе, или, если файл изображения, то фактическое изображение. Он также будет отвечать за центрирование изображений, которые могут быть меньше, чем область отображения.

Задача №1: модификации строительных лесов

Первое, что я делаю, это обновляю кое-что в моем разделе скриптов в package.json. Для удобства сборки я добавляю следующее:

Первый с командой lint-fix - это потому, что я ленив. Когда я забываю сделать что-то, на что жалуется eslint, я использую yarn lint-fix (или npm run lint -fix), и если проблему можно исправить, она исчезнет.

Команда dev предназначена для параллельной разработки во время работы. Изменения в вашем коде вызывают HMR (горячая перезагрузка модуля).

Наконец, две последние команды build-linux и build-win32 предназначены для создания готовых к работе приложений. build-linux следует вызывать в системе Linux, а build-win32 следует вызывать в системе Windows. (Примечание: для Windows я на самом деле буду создавать 64-битное приложение. Electron использует «win32» для обозначения системы Windows, а не ее «арочного» типа.)

Наконец, я добавляю в сгенерированный файл eslintrc.js следующее:

‘Brace-style’: [2, ‘stroustrup’, {‘allowSingleLine’: false}],

Только потому, что мне нравится использовать этот стиль.

Задача № 2: файлы и папки

Первое, что я хочу сделать, это получить список файлов и папок из локальной файловой системы. Я написал служебную функцию для этого, потому что не был уверен, хочу ли я сделать это в основном процессе Electron или в процессе рендеринга. В конце концов, для удобства я выбрал процесс рендеринга.

Эта служебная функция walkFolders является функцией генератора JavaScript.

Функции-генераторы представляют собой мощную альтернативу [пользовательским итераторам]: они позволяют определять итерационный алгоритм путем написания единственной функции, выполнение которой не является непрерывным. Функции генератора записываются с использованием синтаксиса function *. При первоначальном вызове функции генератора не выполняют никакого кода, вместо этого возвращая тип итератора, называемый генератором. Когда значение потребляется путем вызова метода next генератора, функция Generator выполняется до тех пор, пока не встретит ключевое слово yield.

Теперь, когда у меня есть функция, которая даст нам то, что я хочу, я могу назвать ее так:

Первая функция отвечает за получение данных и их фильтрацию только для папок. Вторая функция получает весь контент (файлы и папки). Их можно было бы объединить в одну функцию с параметром, чтобы решить, хотите ли вы вернуть все или только папки, но, в зависимости от уровня навыков читателя, я не хотел добавлять слишком много путаницы.

Первоначально, когда я писал этот код, я просто выводил console.log (). У меня еще не было функции createNode.

Задача № 3: QTree

В моем компоненте folderTree я хочу использовать компонент Quasar QTree. Дерево принимает массив объектов. Каждый объект содержит метку (папка или имя файла), nodeKey (абсолютный путь к файлу или папке), расширяемый (я установлю значение true для папки), ленивый (если дочерние элементы этого узла будут загружаться лениво - по запросу), дочерние элементы (пустой массив, в котором вложенные папки с отложенной загрузкой будут загружены, каждый со своим собственным узлом), и данные (мое собственное дополнение, содержащее дополнительные метаданные для этого узла).

Возможно, вы заметили, что я использую path.sep, который содержит разделитель путей в зависимости от текущей операционной системы. Это очень важно при создании кроссплатформенного программного обеспечения. Чтобы получить к нему доступ, вам потребуется const path = require ('path') в области сценария вашего кода.

Задача №4: получить диски Windows

При разработке этого проекта я понял, что в Linux все файлы и папки находятся в корневой системе. Даже смонтированные диски находятся под рутом. Это очень удобно. Однако под Windows вы получаете диски. Мне нужен был способ определить, какие диски используются операционной системой.

Я попробовал пару пакетов, и они сработали, но потом, когда я пошел компилировать свой проект для Linux, он сломался. Сами пакеты были ограничены сборками Windows, и мне нужен был способ сказать, что это необязательно. Я попробовал маршрут npm для optionalPackages в package.json, но у меня это вообще не сработало. На самом деле, я не мог утруждать себя попытками понять это, поэтому решил попробовать свои силы. Я бы назвал его, только если бы приложение все равно запускалось под Windows.

Таким образом была создана моя функция getWindowsDrives:

И, к счастью, это позволяет мне без проблем создавать для Linux и Windows.

И вызов его работает так:

Примечание. process.platform доступен в коде, написанном для Electron (поскольку он исходит из Node), без необходимости запрашивать / импортировать его.

Свойство process.platform возвращает строку, определяющую платформу операционной системы, на которой выполняется процесс Node.js.

Чтобы увидеть возможные значения, нажмите здесь.

Задача № 5: подмена выбранного QTree и отложенная загрузка

Этого я не ожидал. Принцип работы QTree основан на взаимодействии с пользователем. Вы щелкаете узел дерева и можете перейти к различным дочерним узлам и так далее. Я хотел сказать QTree открыть узел, который еще даже не был загружен. Например, когда Пользователь нажимает на один из ярлыков. У него действительно нет возможности узнать несуществующий-дочерний-дочерний-из-дочернего-узла.

Чтобы сделать это, вам придется написать забавный код. По сути, начиная с уровня корневого узла и продвигаясь к желаемому дочернему узлу. Итак, почти рекурсивно, но вам придется подождать, пока QTree вызовет свою функцию отложенной загрузки на всех узлах, у которых есть дочерние элементы, которые еще не были загружены.

Чтобы сделать это, потребуется некоторое творческое мышление, но я сразу же нашел решение, используя комбинацию функции Vue nextTick и обмена сообщениями глобальной шины событий Vue.

Примечание: вас не смущают статьи о создании глобальной шины событий во Vue. Это старые статьи. Последняя версия Vue поддерживает это напрямую.

В моем компоненте folderTree я хочу получить доступ к глобальной шине событий для отправки сообщений самому себе. Итак, когда у компонента есть доступное сообщение, я хочу, чтобы вызывалась функция expandTree.

Каждый раз, когда вы используете глобальную шину событий, убедитесь, что вы выключаете ее, когда компонент, который она использует, выгружается. Если ваш компонент будет перезагружен несколько раз, это может иметь непредвиденные последствия.

HTML для моего QTree выглядит так:

а метод рекурсивного расширения дерева выглядит так:

Вы заметите, что если вы дадите компоненту HTML ref = ”name”, вы сможете напрямую обращаться к этому компоненту с помощью this. $ Refs ['name'] или this. $ refs.name. Так уж получилось, что у QTree есть некоторые функции, которые доступны. getNodeByKey возвращает узел с указанным ключом, isExpanded вернет true, если узел развернут, а setExpanded вернет вызвать функцию отложенной загрузки и развернуть узел после получения данных. Я отмечу прямо сейчас, что setExpanded - это «недокументированная» функция, и мне пришлось найти ее, фактически заглянув в код QTree, но без нее я не смог бы иметь такую ​​функциональность.

Уловка в приведенном выше коде заключается в том, чтобы получить каждый узел, двигаясь вниз к нужному мне узлу. Если узел не развернут, вызовите кнопку setExpanded. Если я нахожусь на нужном мне узле, то все готово, в противном случае создайте развернуть-дерево в функции this - ›$ nextTick. Это позволяет выполнить отложенную загрузку до того, как произойдет следующая итерация обхода узла.

Я бы не сказал, что это хорошее поведение. Как программисты, мы не должны использовать недокументированные функции. Однако, как программисты, мы все написали что-то, что использовалось не так, как предполагалось. Когда вы делаете что-то подобное (используя любой сторонний код), вы должны написать проблему (или две), чтобы автор мог внести коррективы. А еще лучше, если у вас есть время, создайте PR (запрос на вытягивание) с нужной вам функциональностью.

Задача № 6: отображение изображений из файлов

Помните, что выше в разделе Проблемы безопасности я сделал следующее:

В какой-то момент я использовал протокол file: // для доступа к изображениям в файловой системе, чтобы их можно было отображать вместо общего значка. Что ж, протокол file: // больше не доступен в процессе рендерера. Наилучший способ сейчас будет таким же, как если бы вы использовали веб-страницу и веб-сервер.

В electronic-main.js у меня есть следующий код (вверху):

и внизу:

Здесь вы увидите, что я создаю веб-сервер (экспресс) для передачи файлов изображений в процесс средства визуализации. Также обратите внимание на код ipcMain.on. Каждый раз, когда пользователь переходит в другую папку в процессе рендерера, я отправляю сообщение IPC (межпроцессное взаимодействие) в основной процесс. Затем, когда файл запрашивается у процесса средства визуализации, все это объединяется в функцию router.get.

Код, вызывающий это, находится в компоненте gridItemImage в функции getImage. Фрагмент выглядит так:

Теперь, если вы действительно хотите быть в безопасности, здесь могут происходить самые разные вещи. 1) Вы можете выбрать случайный номер порта для использования, и процесс средства визуализации может запросить его у основного процесса для использования в его вызовах HTTP GET. 2) Вы можете сгенерировать уникальный ключ (или GUID), который процесс средства визуализации может запросить у основного процесса для использования в его вызовах HTTP GET.

Задача № 7: просмотр файлов и папок

Каждый раз, когда пользователь выбирает папку и появляются новые файлы или некоторые удаляются, я хотел, чтобы они отображались немедленно. Есть отличный пакет под названием Чокидар, который может сделать это за вас. Этот пакет используется такими качественными приложениями, как Visual Studio Code (я предпочитаю редактор) и webpack.

Каждый раз, когда выбранная папка изменяется, я вызываю эту функцию:

Я обязательно удаляю все «часы» в существующей папке и создаю новые «часы» в новой папке. Всякий раз, когда что-то меняется, я отправляю сообщение «rescan-current-folder», которое в конечном итоге улавливается этой функцией:

Обзор

Это был обзор создания электронного проводника файлов с помощью Quasar (и Vue). Как я упоминал ранее, проект находится в свободном доступе на GitHub для загрузки или разветвления. Я надеюсь, что вы узнали некоторые вещи, о которых вы, возможно, еще не знали, и помогли вам немного узнать о Quasar (чтобы по-настоящему оценить Quasar, загрузите или разветвите проект).

Если вам нужна дополнительная информация о самом Quasar, вот несколько ссылок:
CLI: https://github.com/quasarframework/quasar-cli
КОМПОНЕНТЫ: https: // github.com/quasarframework/quasar
ДОКУМЕНТЫ: https://quasar-framework.org/
ДИСКОРД: http://chat.quasar-framework.org/ женщина
ФОРУМ: «https://forum.quasar-framework.org/

TWITTER: https://twitter.com/quasarframework
STEEM: http://steemit.com/@ квазаркаркас