基於Vue+Electron構建桌面應用程序實踐

Electron 是由 GitHub 開發的開源庫,用於構建擁有 HTML、CSS 和 JavaScript 的跨平臺桌面應用程序。Electron 通過把 Chromium 和 Node.js 組合到一個運行時來實現這一點,並且可以爲 Mac、Windows 和 Linux 打包應用程序 。

爲了快速入門,我使用了 Greg Holguin 的 electron-vue 樣板。它給開發人員提供了 vue-cli scanffolding、常見的 Vue 插件、打包器、測試、開發工具和其他功能。

我們要構建什麼?

我們要構建一個跟上一篇文章中所述的一樣的應用程序,基於 OpenWeatherMap API 的該應用程序用來查看用戶所選擇城市的天氣情況。

如果只想查看 Electron 支持的應用程序最終代碼,請點擊這裏:

https://github.com/NataliaTep...

安裝

Electron-vue 樣板是作爲 VueCLI 2.x 的模板構建的,包括自定義應用程序的選項。因此,需要進行全局安裝:

npm install -g vue-cli

如果喜歡用 VueCLI 的最新版本,就需要安裝全局網橋:

npm install -g @vue/cli @vue/cli-init

然後,初始化你的項目:

vue init simulatedgreg/electron-vue weather-app

這將啓動一個安裝項目,其中包括需要你做出的幾個選擇。

其中很酷的是,如果需要一些常用的插件和庫,比如 axios,可以在安裝過程中選擇它們。

幾乎所有的選擇都很明確,但是有一個問題:

我決定搜索一下,在 StackOverflow 上找到了一個有用的線索。根據這個線索,看起來 electron 構建器(electron-builder)更適合我,因此,我就改用它了。

設置項目後,需要打開應用程序所在的文件夾,運行 npm install 或 yarn install,現在我們準備好了。

瞭解應用程序結構

安裝完成後,可以在 src 中看到兩個文件夾 main 和 renderer,Electron 主進程需要用到第一個。

根據 electron-vue 的文檔,在 Electron 中運行 package.json 主腳本的進程被稱爲主進程。在主進程中運行的腳本可以通過創建 web 頁面來顯示 GUI。

在 main 文件夾中有兩個文件:index.js 和 index.dev.js。第一個是你的應用程序的主文件,是 electron 啓動用的文件。它也被用做 webpack 的生產入口文件。所有主要的流程工作都應該從這裏開始。

而 index.dev.jsis 專門用於開發,因爲它安裝了 electron-debug 和 vue-devtools。在開發應用程序時,可以不用理睬它。

另外,渲染器(renderer)進程需要 renderer 文件夾。

由於 Electron 使用 Chromium 來顯示 web 頁面,因此也用到了 Chromium 的多進程架構。Electron 中的每個 web 頁面都在自己的進程中運行,這些進程被稱爲渲染器進程。

正如你可能注意到的是,它是個“正常的”Vue 應用程序結構,擁有 assets 和 components 文件夾:main.js 和 App.vue 文件。這是後者的結構:

<template>
  <div id="app">
    <landing-page></landing-page>
  </div>
</template>

<script>
  import LandingPage from '@/components/LandingPage'

  export default {
    name: 'weather-app',
    components: {
      LandingPage
    }
  }
</script>

<style>
  /* CSS */
</style>

如果嘗試運行 dev 任務,將會得到以下結果:

因此,這裏有一個登錄頁面(landing-page)組件,也開啓了開發工具(devtools)。現在,我們可以改變它了。

快速構建(scaffolding)應用程序

與 Vuido 不同,Electron 支持的應用程序是用 HTML 標籤而不是用本機組件構建的。因此,我們將創建一個與通常的 web 應用程序類似的結構,並用 CSS 來進行樣式設計。

請注意:我沒有特意安裝任何 CSS 框架或組件庫:我希望在沒有添加任何不同的依賴項的情況下,比較一下包的大小。在兩個項目中唯一用到的庫是 axios。

第一步是去掉登錄頁面組件。然後我添加了一個簡單的輸入字段和一個按鈕:

<div id="app">
    <p>Enter the city name to check current weather in it</p>
    <section class="weather-input">
      <input type="text" v-model="query">
      <button :disabled="!query.length">Check</button>
    </section>
</div>

我們在數據中有個查詢(query)屬性來處理用戶輸入,我們將把該查詢作爲參數,進行 API 調用。

進行 API 調用

我使用了 OpenWeatherMap 當前天氣 API。它提供很多不同的信息,可以點擊這裏查看 JSON 響應的示例。

在安裝過程中,我們已經將 axios 包含在我們的應用程序中。我們來看看 src/renderer/main.js:

import Vue from 'vue';
import axios from 'axios';
import App from './App';

if (!process.env.IS_WEB) Vue.use(require('vue-electron'));
Vue.http = Vue.prototype.$http = axios;
Vue.config.productionTip = false;

因此,我們可以在組件實例中把 axios 方式用作 this.$http。在這裏,我們將只爲我們的 API 調用添加一個基本 URL:

axios.defaults.baseURL = 'http://api.openweathermap.org/data/2.5';

現在,在 App.vue 中,我們將創建一組數據屬性來顯示不同的天氣數據:

data() {
    return {
      query: '',
      error: false,
      city: '',
      country: '',
      weatherDescription: '',
      temp: null,
      tempMin: null,
      tempMax: null,
      humidity: null,
      icon: '',
    };
},

與 Vuido 版本相比,我添加了一個額外屬性,它是個圖標。API 提供天氣圖標,但是我們無法在 Vuido 應用程序中使用,因爲目前不支持顯示圖像。

我們還創建了一種方法來獲取數據:

methods: {
  showWeather() {
    this.$http
      .get(`/weather?q=${this.query}&units=metric&&appid=${API_KEY}`)
      .then(response => {
        this.city = response.data.name;
        this.country = response.data.sys.country;
        this.weatherDescription = response.data.weather[0].description;
        this.temp = response.data.main.temp;
        this.tempMin = response.data.main.temp_min;
        this.tempMax = response.data.main.temp_max;
        this.humidity = response.data.main.humidity;
        this.icon = `http://openweathermap.org/img/w/${
          response.data.weather[0].icon
        }.png`;
        this.error = false;
      })
      .catch(() => {
        this.error = true;
        this.city = '';
      });
  },
},

並把它添加到按鈕的單擊回調中:

<button :disabled="!query.length" @click="showWeather">Check</button>

現在,如果在輸入字段輸入文本,單擊按鈕,就可以在“網絡(Network)” 選項卡上觀察 API 調用:

顯示天氣數據

我們把這些數據添加到模板上:

<template>
  <main id="app">
    <p>Enter the city name to check current weather in it</p>
    <section class="weather-input">
      <input type="text" v-model="query">
      <button :disabled="!query.length" @click="showWeather">Check</button>
    </section>
    <section v-if="error" class="weather-error">
      There is no such city in the database
    </section>
    <section v-if="city.length" class="weather-result">
      <h1>{{city}}, {{country}}</h1>
      <p><em>{{weatherDescription}}</em></p>
      <div class="weather-result__main">
        <img :src="icon" alt="Weather icon">
        <div class="weather-result__temp">
          {{temp}}&deg;C
        </div>
      </div>
      <div class="weather-result__details">
        <p>Min: {{tempMin}}&deg;C</p>
        <p>Max: {{tempMax}}&deg;C</p>
        <p>Humidity: {{humidity}}%</p>
      </div>
    </section>
  </main>
</template>

我們的應用程序視圖:

image

太棒了,我們能看到真實的天氣狀況了!但是,它看起來像是 1999 年的……我們給它添加點 CSS 魔法吧(事實上,是很多 CSS 魔法)!

<style lang="scss">
* {
  margin: 0;
  padding: 0;
}
html,
body,
#app {
  height: 100%;
}

#app {
  font-family: Arial, Helvetica, sans-serif;
  font-size: 16px;
  padding: 10px;
  background: rgb(212, 228, 239);
  background: -moz-radial-gradient(
    center,
    ellipse cover,
    rgba(212, 228, 239, 1) 0%,
    rgba(134, 174, 204, 1) 100%
  );
  background: -webkit-radial-gradient(
    center,
    ellipse cover,
    rgba(212, 228, 239, 1) 0%,
    rgba(134, 174, 204, 1) 100%
  );
  background: radial-gradient(
    ellipse at center,
    rgba(212, 228, 239, 1) 0%,
    rgba(134, 174, 204, 1) 100%
  );
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#d4e4ef', endColorstr='#86aecc',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
}

.weather-input {
  display: flex;
  align-items: center;
  padding: 20px 0;
}

.weather-result {
  text-align: center;
  &__main {
    display: flex;
    align-items: center;
    justify-content: center;
    padding-top: 5px;
    font-size: 1.3rem;
    font-weight: bold;
  }
  &__details {
    display: flex;
    align-items: center;
    justify-content: space-around;
    color: dimgray;
  }
}

.weather-error {
  color: red;
  font-weight: bold;
}

input {
  width: 75%;
  outline: none;
  height: 20px;
  font-size: 0.8rem;
}

button {
  display: block;
  width: 25%;
  height: 25px;
  outline: none;
  border-radius: 5px;
  white-space: nowrap;
  margin: 0 10px;
  font-size: 0.8rem;
}
</style>

最終,我們擁有了這個美妙的全功能應用程序:

在打包之前,最後要做的事是把它的尺寸縮小到窗口大小。如果我們查看一下 src/main/index.js 文件,可以找到它的設置選項:

mainWindow = new BrowserWindow({
    height: 563,
    useContentSize: true,
    width: 1000
})

我們把寬度改爲 450,高度改爲 250。

打 包 

你可以把你的應用程序構建爲 web 應用程序了!如果運行 build:web 任務,可以在 dist 文件夾中找到構建 web 應用程序。

但是,讓我們回到我們的桌面應用程序並運行構建任務。結果,你在構建文件夾中會有一個文件夾,該文件夾的名字是根據你的平臺命名的(對我而言是 mac),裏面有一個應用程序文件。它的大小是 133Mb!

對於這麼小的應用程序來說,這文件太大了。另外,如果運行一下,你就會注意到,它的啓動比 Vuido 支持的應用程序慢。

最終的樣子:

結  論

優點:

  • 容易上手;
  • 出色的文檔;
  • 提供 web 應用程序構建;
  • 可以通過 CSS 樣式自定義。

缺點:

  • 打包後的文件超大;
  • 比用本機 GUI 組件構建的應用程序速度慢;
  • 如果你的應用程序需要獨特的外觀,並且你不在乎;
  • 打包後的文件大小和性能,那麼,Electron-vue 是個不錯的選擇。

更新

如果你的 web 應用程序是用 Vue CLI 3 構建的,則可以用 Vue CLI 插件 Electron Builder 把它簡化成桌面應用程序。你只需在項目根文件夾中運行以下命令:

vue add electron-builder

運行結束後,你將會擁有兩個額外的 npm 任務:serve:electron 和 build:electron,與桌面應用程序一起工作。

原文鏈接:https://www.jianshu.com/p/419...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章