V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
TsaiKoga
V2EX  ›  分享创造

用 Electron-Vue 开发的协助程序员的开发工具 IT-Tools

  •  1
     
  •   TsaiKoga · 2019-03-27 09:40:16 +08:00 · 2563 次点击
    这是一个创建于 1855 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这是由 Electron & Vue.js 编写的,为程序员服务的编程工具

    目前提供了四个版块:

    • 正则表达式
    • 时间戳转化
    • 颜色盒子
    • Json 转化

    在这几个模块中,可以发现使用组件化的好处,处理多个组件之间各种数据变化非常方便!

    IT-Tools

    项目地址:

    Github 地址:https://github.com/TsaiKoga/it-tools

    求 Star

    感兴趣的朋友可以 star 或 fork,或是给我你的宝贵意见,互相学习一下


    下面介绍一下我写 正则表达式内容,写的不好,望见谅...

    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' />
    

    生成桌面应用

    运行命令:

    npm run build:mas # 生成 mac 应用
    npm run build:linux # 生成 linux 应用
    npm run build:win32 # 生成 windows 应用
    

    可以在 /build 目录中看到生成的应用目录

    9 条回复    2019-04-05 16:33:54 +08:00
    oldarm
        1
    oldarm  
       2019-03-27 09:52:48 +08:00
    不错
    jevonszmx
        2
    jevonszmx  
       2019-03-27 09:56:25 +08:00
    哈哈,我也用 Electron+vue 写了一个自己用,https://github.com/jevonszmx/webtool,UI 是使用的 bootstrap,不过目前支持的功能比你多。


    ![截图]( )

    ![截图]( )

    ![截图]( )

    ![截图]( )

    希望有人继续一起完善。
    jevonszmx
        3
    jevonszmx  
       2019-03-27 09:57:38 +08:00
    额,V2 解析链接出错了,把后面的,UI 也加上了,实际地址是: https://github.com/jevonszmx/webtool
    TsaiKoga
        4
    TsaiKoga  
    OP
       2019-03-27 10:40:30 +08:00
    @jevonszmx 额,我的转化都是自己写的,提示比较多
    azh7138m
        5
    azh7138m  
       2019-03-27 15:27:19 +08:00
    @jevonszmx md5 加密很厉害啊,那怎么解密呢?
    kosmosr
        6
    kosmosr  
       2019-03-27 18:39:18 +08:00 via Android
    有个工具叫 uTools 也很好用也是集成了很多小插件,推荐一波 https://u.tools
    TsaiKoga
        7
    TsaiKoga  
    OP
       2019-03-28 09:35:35 +08:00
    大家不要光顾着收藏,麻烦 star 一个: https://github.com/TsaiKoga/it-tools
    Chingim
        8
    Chingim  
       2019-03-28 19:32:57 +08:00 via Android
    纯粹是页面展示的功能,为什么非得打包一个 electron ?
    TsaiKoga
        9
    TsaiKoga  
    OP
       2019-04-05 16:33:54 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3246 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 11:54 · PVG 19:54 · LAX 04:54 · JFK 07:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.