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}}°C
</div>
</div>
<div class="weather-result__details">
<p>Min: {{tempMin}}°C</p>
<p>Max: {{tempMax}}°C</p>
<p>Humidity: {{humidity}}%</p>
</div>
</section>
</main>
</template>
我們的應用程序視圖:
太棒了,我們能看到真實的天氣狀況了!但是,它看起來像是 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,與桌面應用程序一起工作。