electron-vue 創建桌面應用


electron-vue 創建桌面應用

為了學習 vue 並創建桌面應用,

我使用了 electron-vue 來進行搭建,

它集成了很多 vue 的工具,用來學習 vue 非常方便;

這里我用 IT Tools 這個項目來講解一下,

整個項目目前提供了四個模塊,分別是

  • “正則表達式”
  • “時間戳轉化”
  • “顏色盒子”
  • “Json轉化”

在這幾個模塊中,可以發現使用組件化的好處,處理多個組件之間各種數據變化非常方便!

這里我就以 “正則表達式” 頁面來說明:

創建 Electron-Vue 項目

克隆項目,從electron-vue 克隆項目,然后開始編寫代碼;

https://github.com/SimulatedGREG/electron-vue.git

通過"正則表達式"這個模塊,來了解 Vue 組件通信;

electron-vue 一開始已經為你生成一些文件頁面,我們可以按照他的方法創建我們自己的頁面;

創建路由:

src/renderer/router/index.js 文件中添加路由:

export default new Router({ routes: [ { path: '/', name: 'landing-page', component: require('@/components/LandingPage').default }, { path: '/regex-page', name: 'regex-page', component: require('@/components/RegexPage').default } ] });

這里我們的 url 為 /regex-page,並且require 了RegexPage組件,這個組件要放置在components 目錄下,所以我創建了文件:src/renderer/components/RegexPage.vue

 

編寫組件:

可以通過復制 LandingPage.vue 組件,將它改成新組件即可:

要實現這個頁面,頭部兩個輸入框,輸入后都能與下面的textarea 內容進行比較處理,得出結論;

這個用 組件化 vue 比純粹用js jquery 的 dom 操作要方便太多了;

通過 template 包裹寫成vue組件:

<template>
  <div id="regex-page">

    <div class="regex-inner" v-show="currentTab === 'Home'">
    <div class="regex-top">
      <div class="regex-top-label">
        <label>Your regular expression:</label>
      </div>
      <div class="regex-top-fields">
        <div class="regex-diagonal">/</div>
        <div class="regex-diagnoal-input">
          <input type="text" name="regex-exp" @input='execRegex' :value='regexExp' />
        </div>

 
         

        <div class="regex-diagonal">/</div>
        <div>
          <input type="text" name="regex-opt" @input="execRegex" :value="regexOpt" />
        </div>
      </div>

     </div>

 
         

     <div class="regex-bottom">
      <div class="regex-content">
        <label>Your test string: </label>
        <textarea class="regex-textarea" name="regex-content" @input="execRegex" :value='regexCont'></textarea>
      </div>

 
         

      <div class="result-content result-init" v-if="regexResult['status'] == 0">
        {{ regexResult['content'] }}
      </div>

 
         


      <div class="result-content result-match" v-if="regexResult['status'] == 1">
        <div>
          <div class="regex-match-btn">
            <label>Match Result:</label>
            <a href="javascript:void(0)" class="clean-fields" @click="cleanAllFields">Clean Fields</a>
          </div>
          <div class="result-item">
            <span v-for="(cont, indx) in regexResult['matchedContext']" :class="indx%2 !== 0 ? 'match' : null">{{ cont }}</span>
          </div>
        </div>
        <ul v-if="regexResult['content'].length > 0">
          <label>Match Groups:</label>
          <div class="match-groups">
            <li v-for="(itemGroup, index) in regexResult['content']">
              <div class="group-item">
              <label>Match Group {{ index + 1 }}:</label>
              <ul>
                <li v-if="i !== 0" v-for="(item, i) in itemGroup">{{ i }}: {{ item }}</li>
              </ul>
              </div>
            </li>
          </div>
        </ul>
        </div>

 
         

        <div class="result-content result-not-match" v-if="regexResult['status'] == -1">
          {{ regexResult['content'] }}
        </div>
      </div>
    </div>

</div>
</template>

<script>
import { mapState, mapActions } from 'vuex'

export default {
  name: 'regex-page',
  computed: {
    ...mapState('Regex', {
      regexExp: state => state.regexExp,
      regexOpt: state => state.regexOpt,
      regexCont: state => state.regexCont,
      regexResult: state => state.regexResult})
  },

    methods: {
    ...mapActions('Regex', [
      'setNav',
      'cleanFields',
      'regexMatch'
    ]),
    cleanAllFields () {
      this.cleanFields()
    },
    execRegex (event) {
      this.regexMatch(event)
    },
    updateNav (title, index) {
      this.setNav({ title: title, index: index })
    }

  }

}
</script>
<style lang="scss" scoped>

* {

}

</style>

 至於,輸入框之間的交互,我使用 vuex 來實現他們之間數據的傳遞;

 

 

使用 Vuex 管理狀態:
一、創建 store 目錄,並創建 modules 目錄用來管理不同的命名空間的State, Actions, Mutations 
創建src/renderer/store/modules/Regex.js 文件:
const state = {
  regexExp: '',
  regexOpt: '',
  regexCont: '',
  regexResult: { status: 0, content: "Here's result." }
}

const mutations = {
  REGEX_MATCH (state, target) {
    if (target.name === 'regex-exp') {
      state.regexExp = target.value
    }
    if (target.name === 'regex-opt') {
      state.regexOpt = target.value
    }
    if (target.name === 'regex-content') {
      state.regexCont = target.value
    }
    ...
}


const actions = {
  cleanFields ({ commit }) {
    commit('CLEAN_FIELDS')
  },
  regexMatch ({ commit }, payload) {
    commit('REGEX_MATCH', payload.target)
  }
}


export default {
  state,
  mutations,
  actions
}

state 給默認狀態;

mutations 更改對應 state;

actions 用於寫異步來改變狀態或提交 mutations 的更改;

 

state 的方法被我寫在computed,這樣組件中可以使用;

在methods 方法中使用 mapActions,並定義其他方法來調用這些action;

 

 

二、main.js 加入 store 容器

import App from './App'
import router from './router'
import store from './store'

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

new Vue({
  components: { App },
  router,
  store,
  template: '<App/>'
}).$mount('#app')

 

 

 

三、組件中通過 computed 或 data 使用 State,通過 methods 觸發 Actions 方法

  
import { mapState, mapActions } from 'vuex'

export default {
  name: 'regex-page',
  computed: {
    ...mapState('Regex', {
      regexExp: state => state.regexExp,
      regexOpt: state => state.regexOpt,
      regexCont: state => state.regexCont,
      regexResult: state => state.regexResult})
    },

    methods: {
    ...mapActions('Regex', [
      'setNav',
      'cleanFields',
      'regexMatch'
    ]),
    cleanAllFields () {
      this.cleanFields()
    },
    execRegex (event) {
      this.regexMatch(event)
    },
    updateNav (title, index) {
      this.setNav({ title: title, index: index })
    }

  }
}

在組件文件中引用了

mapState, mapActions

方法,他可以獲取這個 store 里的 state 和 action 方法,

不過要注意命名空間的使用,此處使用了Regex作為命名空間,所以要在mapState 和 mapActions 中加 命名空間;

 

命名空間定義文件在:src/renderer/store/modules/index.js 文件;

const files = require.context('.', false, /\.js$/)
const modules = {} files.keys().forEach(key => { if (key === './index.js') return modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default modules[key.replace(/(\.\/|\.js)/g, '')]['namespaced'] = true }) export default modules

但是直接 (‘Regex’, [regexExp: state => state.regexExp]) 是無法使用的,必須在 module 中聲明 namespaced: true 才可以;

…mapActions() 是將里面的對象 扁平化 到 外面的對象中;

直接 mapActions  只是打開了方法,還未執行:

刪除 createSharedMutations() 的方法后,action 生效;

 

綁定到組件上

<input type="text" name="regex-exp" @input='execRegex' value='regexExp' />

  

 

大體上就是這樣,剩余就是處理方法的邏輯,在  Mutation 的方法中實現;

 

Vue 生命周期問題:

這里我要提一下另一個頁面模塊:“JSON 轉化”;
我在做 “Json 轉化” 的時候 ,由於轉化后的 json 對象構造成 html 后要用 v-html 顯示;
但是這些 html 標簽中有的要綁定事件,直接在 component 中寫 methods,發現事件無法被觸發; 

為了讓 v-html 中的事件生效,我查閱了 vue 組件的生命周期;

  v-html 在組件 mounted 之后,也就是 state 變化之后渲染,所以我們必須在 updated 之后綁定事件

但是又有問題,因為 state 不變化,就不會 updated 局部組件,而我們點擊其他頁面后,回到當前頁面,在去觸發事件,發現事件沒了?
嘗試添加 mounted 來綁定事件,成功觸發事件;  【當點擊其他頁面,然后返回時,state 的不變,不會再次調用 updated 方法,但是重新執行了掛載方法 mounted】

生成桌面應用

運行命令:
npm run build:mas # 生成mac應用
npm run build:linux # 生成linux 應用
npm run build:win32 # 生成windows應用

可以在 /build 目錄中看到生成的應用目錄

 

對mac 應用進行打包:

將生成的應用放入新建的目錄,命名為 IT-Tools,再復制“應用程序”的軟鏈 到 IT-Tools目錄中;

cmd+空格:打開文件搜索 disk ,打開磁盤管理,點擊文件-新建映像-來自文件夾的映像;

 
感謝大家閱讀, 如果您對 it-tools 此項目感興趣,歡迎關注或者給我問題; 

 

 
        


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM