Создание настольного приложения Vue 3 с помощью Pinia, Electron и Quasar

Недавно я задумал переписать свое приложение Electron «Scrum Daily Standup Picker» на Vue 3. Первоначальный релиз я написал на Angular, но я хотел провести рефакторинг кодовой базы и переписать его на Vue 3.

Почему? Потому что я люблю Vue и хочу иметь публичную витрину, на которую я могу ссылаться потенциальным клиентам.

Почему Quasar?

Quasar — это лицензированный MIT фреймворк на базе Vue.js с открытым исходным кодом, который предназначен для создания SPA, SSR, PWA, мобильных приложений, десктопных приложений и браузерных расширений, используя одну кодовую базу. Он обрабатывает настройку сборки и предоставляет полную коллекцию UI-компонентов, соответствующих Material Design.

Девиз Quasar таков:

Напишите код один раз и одновременно разверните его как веб-сайт, мобильное приложение и/или электронное приложение.

Использование Quasar значительно экономит время разработки по этим причинам:

  • Он основан на Vue.js.
  • Он предоставляет множество компонентов пользовательского интерфейса, которые следуют рекомендациям Material Design.
  • Регулярный цикл выпуска новых версий, включающий новые функции.
  • Он обеспечивает поддержку каждого режима сборки (SPA, SSR, PWA, мобильное приложение, настольное приложение и расширение для браузера).
  • У него есть собственный CLI, который обеспечивает приятный опыт разработчика. Например, мы можем собрать наше приложение как SPA, мобильное или настольное приложение в одной папке проекта.

Читайте подробнее о том, почему Quasar может быть хорошим выбором для вашего следующего проекта.

Установка Quasar CLI

Исходный код следующей демонстрации доступен на GitHub

# Node.js >=12.22.1 is required.

$ yarn global add @quasar/cli
# or
$ npm install -g @quasar/cli
Вход в полноэкранный режим Выйти из полноэкранного режима

Давайте начнем с создания нового проекта с помощью Quasar CLI:

▶ quasar create vue3-electron-demo

  ___
 / _  _ _ ______  ___ ___
| | | | | | |/ _` / __|/ _` | '__ |
| |_| | |_| | (_| __  (_| | |
  ___\__ ,_| __,_|___ /__,_|_|

? Project name (internal usage for dev) vue3-electron-demo
? Project product name (must start with letter if building mobile apps) Quasar App
? Project description A Quasar Framework app
? Author Michael Hoffmann <michael.hoffmann@mokkapps.de>
? Pick your CSS preprocessor: SCSS
? Check the features needed for your project: ESLint (recommended), TypeScript
? Pick a component style: Composition
? Pick an ESLint preset: Prettier
? Continue to install project dependencies after the project has been created? (recommended) NPM
Войти в полноэкранный режим Выход из полноэкранного режима

Мы выбрали SCSS в качестве нашего CSS-препроцессора, ESLint & Typescript в качестве дополнительных функций, Vue 3’s Composition API и Prettier для форматирования кода.

Не выбирайте Vuex, поскольку мы добавим другую библиотеку состояний в следующей главе. Если вы случайно добавили Vuex, удалите его вручную из вашего package.json.

Прочитайте официальную документацию для получения дополнительной информации о Quasar CLI.

Добавьте Pinia в качестве библиотеки магазина Vue

Мы будем использовать Pinia в качестве библиотеки магазина Vue, которая в настоящее время является рекомендуемой библиотекой состояния для Vue.

Сначала нам нужно установить Pinia:

yarn add pinia
# or with npm
npm install pinia
Войдите в полноэкранный режим Выйти из полноэкранного режима

Чтобы иметь возможность зарегистрировать Pinia в нашем экземпляре приложения Vue, нам нужно создать загрузочный файл Quasar:

Частым случаем использования Quasar-приложений является запуск кода до инстанцирования корневого экземпляра приложения Vue, например, внедрение и инициализация собственных зависимостей (примеры: компоненты Vue, библиотеки…) или просто настройка некоторого стартового кода вашего приложения.

Наш загрузочный файл называется pinia.ts и находится по адресу src/boot:

import { boot } from 'quasar/wrappers';
import { createPinia } from 'pinia';

export default boot(({ app }) => {
  app.use(createPinia());
});
Вход в полноэкранный режим Выход из полноэкранного режима

Нам также нужно добавить этот новый файл в quasar.conf.js:

module.exports = configure(function (ctx) {
  return {
    ...
    // app boot file (/src/boot)
    // --> boot files are part of "main.js"
    // https://quasar.dev/quasar-cli/boot-files
    boot: ['pinia'], ...
  }
}
Войти в полноэкранный режим Выход из полноэкранного режима

Теперь мы можем создать новую папку pinia в src.

Мы не можем назвать эту папку store, так как это имя зарезервировано для официальной интеграции Vuex.

Базовый магазин может выглядеть следующим образом:

import { defineStore } from 'pinia';

// useStore could be anything like useUser, useCart
// the first argument is a unique id of the store across your application
const useStore = defineStore('storeId', {
  state: () => {
    return {
      counter: 0,
      lastName: 'Michael',
      firstName: 'Michael',
    };
  },
  getters: {
    fullName: state => `${state.firstName} ${state.lastName}`,
  },
  actions: {
    increment() {
      this.counter++;
    },
  },
});

export default useStore;
Вход в полноэкранный режим Выход из полноэкранного режима

Мы можем использовать этот магазин в любом компоненте Vue:

<template>Counter: {{ store.counter }}</template>

<script setup lang="ts">
import { useStore } from '@/stores/counter';

const store = useStore();
</script>
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь мы можем запустить приложение Vue с помощью Quasar CLI:

quasar dev
Войти в полноэкранный режим Выйти из полноэкранного режима

Приложение Vue обслуживается по адресу http://localhost:8080:


Quasar Dev Mode

Настройка Electron

Прочитайте это введение, если вы новичок в Electron.

Для разработки/сборки приложения Quasar Electron нам необходимо добавить режим Electron в наш проект Quasar:

$ quasar mode add electron
Войти в полноэкранный режим Выйти из полноэкранного режима

Каждое приложение Electron имеет два потока: основной поток (занимается окном и кодом инициализации — из недавно созданной папки /src-electron) и поток рендеринга (который занимается фактическим содержимым вашего приложения из /src).

Новая папка имеет следующую структуру:

.
└── src-electron/
├── icons/ # Icons of your app for all platforms
| ├── icon.icns # Icon file for Darwin (MacOS) platform
| ├── icon.ico # Icon file for win32 (Windows) platform
| └── icon.png # Tray icon file for all platforms
├── electron-preload.js # (or .ts) Electron preload script (injects Node.js stuff into renderer thread)
└── electron-main.js # (or .ts) Main thread code
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь мы готовы запустить наше приложение Electron:

$ quasar dev -m electron
Войти в полноэкранный режим Выйти из полноэкранного режима

Эта команда откроет окно Electron, в котором будет отображаться ваше приложение вместе с инструментами разработчика, открытыми бок о бок:


Quasar Electron Dev

Читайте официальную документацию для получения дополнительной и подробной информации о разработке приложений Electron с помощью Quasar.

Управление Electron из кода Vue

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

Например, если мы хотим показать диалог для открытия файлов, Electron предоставляет API для отображения диалогов системы для открытия и сохранения файлов, оповещения и т.д.

Сначала нам нужно установить @electron/remote:

npm install -D @electron/remote
Вход в полноэкранный режим Выход из полноэкранного режима

Затем нам нужно изменить src-electron/electron-main.js и инициализировать @electron/remote:

import { app, BrowserWindow, nativeTheme } from 'electron'
import { initialize, enable } from '@electron/remote/main'import path from 'path'
import os from 'os'

initialize();
let mainWindow;

function createWindow () {
  /**
   * Initial window options
   */
  mainWindow = new BrowserWindow({
    icon: path.resolve(__dirname, 'icons/icon.png'), // tray icon
    width: 1000,
    height: 600,
    useContentSize: true,
    webPreferences: {
      contextIsolation: true,
      // More info: /quasar-cli/developing-electron-apps/electron-preload-script
      preload: path.resolve(__dirname, process.env.QUASAR_ELECTRON_PRELOAD)
    }
  })

  // ....

  enable(mainWindow.webContents);}
Вход в полноэкранный режим Выход из полноэкранного режима

Если мы хотим использовать Electron API из нашего кода Vue, нам нужно добавить некоторый код в src-electron/electron-preload.js:

import { contextBridge } from 'electron';
import { dialog } from '@electron/remote';
// 'electronApi' will be available on the global window context
contextBridge.exposeInMainWorld('electronApi', {
  openFileDialog: async (title, folder, filters) => {
    // calling showOpenDialog from Electron API: https://www.electronjs.org/docs/latest/api/dialog/
    const response = await dialog.showOpenDialog({ title, filters, properties: ['openFile', 'multiSelections'], }); return response.filePaths;
  }
});
Вход в полноэкранный режим Выход из полноэкранного режима

Далее мы создадим src/api/electron-api.ts для доступа к этому коду из нашего приложения Vue:

export interface ElectronFileFilter {
  name: string;
  extensions: string[];
}

export interface ElectronApi {
  openFileDialog: (
    title: string,
    folder: string,
    filters: ElectronFileFilter
  ) => Promise<string[]>;
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
export const electronApi: ElectronApi = (window as { electronApi: ElectronApi })
  .electronApi;
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь мы можем использовать этот API в любом месте нашего компонента Vue:

<template>
  <q-btn @click="openElectronFileDialog">Open Electron File Dialog</q-btn>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { electronApi } from 'src/api/electron-api';

export default defineComponent({
  name: 'PageIndex',
  components: { },
  setup() {
    const openElectronFileDialog = async () => {
      return electronApi.openFileDialog('Test', 'folder', { name: 'images', extensions: ['jpg'] });
    };

    return { openElectronFileDialog };
  },
});
</script>
Войти в полноэкранный режим Выйти из полноэкранного режима

Нажатие на кнопку теперь должно открыть диалог файлов родной ОС:


Electron File Dialog

Заключение

Quasar позволяет нам быстро разрабатывать настольные приложения Electron на Vue с высококачественными компонентами пользовательского интерфейса, которые следуют рекомендациям Material Design.

Наиболее значительным преимуществом по сравнению с пользовательским проектом Electron + Vue из GitHub является то, что Quasar имеет регулярный цикл выпуска и предоставляет руководства по обновлению старых версий.

Посмотрите на мой GitHub-репозиторий «Scrum Daily Standup Picker», чтобы увидеть более сложный проект «Quasar-Electron-Vue3-Typescript-Pinia». Исходный код следующей демонстрации доступен на GitHub.

Если вам понравилась эта статья, следуйте за мной в Twitter, чтобы получать уведомления о новых статьях блога и других материалах от меня.

Также (или дополнительно) вы можете подписаться на мою рассылку.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *