2017/12/10
このエントリーは #kosen10s Advent Calendar 2017 11日目のエントリーです。前日の担当はNKMR6194 くんで、なぜpthread_mutexは機能するのか?というエントリーでした。
みんなkosen10sに全く関係無い記事を普通に書いているので自分も普通に今日勉強したことを書く。 もはやelectronとかvueのアドベントカレンダー向けのエントリになっている。
Webサイトを作成する感覚でデスクトップアプリを開発できます。Electron は JavaScript, HTML, CSS といったWeb技術を利用してネイティブアプリケーションを作成するためのフレームワークです。開発者はアプリの重要な部分の実装に集中して、面倒な部分はElectronにお任せください。 [https://electronjs.org/] より
だそうです。技術的にはchromiumを内包したアプリができます。中でNode.jsが動いています。
SlackやVisual Studio Codeを始め、がんがん採用実績が増えているフレームワークです。
npm install -g vue-cli vue init simulatedgreg/electron-vue electron-memo # 質問されるのでこんな感じで選択した > ? Application Name electron-memo > ? Project description An electron-vue project > ? Select which Vue plugins to install axios, vue-electron, vue-router, vuex > ? Use linting with ESLint? Yes > ? Which eslint config would you like to use? Standard > ? Setup unit testing with Karma + Mocha? Yes > ? Setup end-to-end testing with Spectron + Mocha? Yes > ? What build tool would you like to use? packager cd electron-memo npm install npm run dev
ESLintのstandard設定を選択したので生成される.eslintrc.jsを変更しないかぎりはそれに従わないとエラーが発生する。
ESLintに従ったコーディングをおすすめするが慣れない人は削った方がいい。
起動するとこんなWelcome画面。
Chromiumが動いていて、WebPackDevServerがサーバになっている。ちなみに http://localhost:9080/
にアクセスすると真っ白な画面になった。うまいこと隠してくれているみたい。
src/main/index.js
を見たところProdビルドではlocalhostURLではなくファイル参照になるようなので安心。
<template> <div class="grid-container"> <div class="sidebar"> <div class="memos-title">Memos</div> <div class="memos"> <div v-for="(memo, memoIndex) in memos" :key="memoIndex" @click="changeIndex(memoIndex)" :class="['memo', index === memoIndex ? 'active' : '']"> <!-- 保存していればファイル名、保存してなければテキストの1行目、テキストがなければEmptyを表示しておく --> {{ memo.filePath && memo.filePath.split('/').reverse()[0] || memo.text.split('\n')[0] || "Empty" }} </div> </div> </div> <div class="action"> <div class="action-title">Action</div> <div @click="addNew" class="action-item">Add New</div> <div @click="importMemo" class="action-item">Import</div> </div> <div class="editor"> <!-- keydown.meta.83でcommand+S, ctrl+83でctrl+sを使う。他にもっとうまいやりかたがありそう。 --> <textarea ref="editor" v-model="memos[index].text" placeholder="Input free memo." class="textarea" @keydown.meta.83="save" @keyup.ctrl.83="save" autofocus></textarea> </div> </div> </template> <script> // remoteを通じてメインプロセスのAPIを呼び出す const {dialog} = require('electron').remote const fs = require('fs') const emptyMemo = {'text': '', filePath: ''} export default { data: () => { return { memos: [{'text': 'sample memo.', filePath: ''}], index: 0 } }, methods: { addNew () { this.memos.push(Object.assign({}, emptyMemo)) this.changeIndex(this.memos.length - 1) }, changeIndex (index) { this.index = index this.$refs.editor.focus() }, importMemo () { // dialog.showOpenDialogでOSのファイル選択を呼び出す // 複数ファイルの選択も想定したAPIなので返り値はファイルパスの配列がかえる const filePath = dialog.showOpenDialog({ properties: ['openFile', 'createDirectory'] })[0] // ファイル読み込みはNode.jsのfsを使って普通に行うことができる fs.readFile(filePath, 'utf8', (error, text) => { if (error) { console.error('error: ', error) } else { this.memos.push({ text: text, filePath: filePath }) this.changeIndex(this.memos.length - 1) } }) }, save () { const memo = this.memos[this.index] if (!memo.filePath) { // showSaveDialogでは保存するファイルのパスを選択できる const filePath = dialog.showSaveDialog({title: 'Save as'}) memo.filePath = filePath } fs.writeFileSync(memo.filePath, memo.text) } } } </script> <style scoped> /* style scopedと書くことでこのファイル内のみで有効になる */ .grid-container { /* ブラウザはChromium限定なので新しいの使ってみようと思い 初めてgrid layoutを使って見たが非常に楽だった もうfloatは回り込みとかしたい時だけでよさそう */ display: grid; grid-template-columns: 220px 1fr; grid-template-rows: 1fr 100px; grid-template-areas: "sidebar editor" "action editor"; } .sidebar { grid-area: sidebar; background-color: #4863ad; color: #FFFFFF; max-height: calc(100vh - 100px); overflow: auto; } .action { grid-area: action; background-color: #4863ad; color: #FFFFFF; } .editor { grid-area: editor; height: 100vh; } // 長いので省略 </style>
自分的に学びのあった部分はコメントを入れた。
<template>
にHTMLを、<script>
にJSを、<style>
にCSSを書いていく。
さらに<script>
でexportしているdataにリアクティブにするデータを、methodsにクリックイベント等で呼ぶ関数を書いていく。
書くべき場所があるって素晴らしい。
routes: [ { path: '/', name: 'index', component: require('@/components/Index').default }, { path: '*', redirect: '/' } ]
src/renderer/App.vue
の<router-view>
にパスに対応したコンポーネントが表示される
ビルドもelectron-vueを使っているおかげでnpmコマンド1つで導入時に選択したelectron-packagerを使ってビルドしてくれているようになっている
npm run build ... ls build/ electron-memo-darwin-x64 electron-memo-linux-x64 electron-memo-mas-x64 icons
mac, linux用のバイナリが出力された
インストーラは出来なかったのでそのうちまた調査する
windowsはエラーが出てビルド出来なかったがwindows用のビルドにはwineが必要らしい
注意!!!ビルドは恐ろしくメモリを食い尽くすようでChromeが落ちる!ビルド前にはブログの途中書きとかがないか確認しよう!!!
明日の担当はtsudukamiで「教育のお話詰め合わせセット」です。