美文网首页
Electron+Vue3+TypeScript+Vite桌面应

Electron+Vue3+TypeScript+Vite桌面应

作者: web秀 | 来源:发表于2022-05-13 16:56 被阅读0次

    原文地址:https://www.webxiu.com.cn/post/10005242

    前言

    [图片上传失败...(image-1988c9-1652432201196)]

    上一章节《Electron+Vue3+TypeScript+Vite桌面应用程序项目初始化》完成后,我们的桌面应用程序如上图,这次我们先美化一下界面,形成初步的UI框架。

    从这里开始需要书写css,我们选择SCSS工具,先安装:

    npm install sass -save-dev
    

    新建assets/scss/globalVariable.scss

    // 这里书写全局的css样式,或者方法等
    

    修改 vite.config.ts

    ...
    css: {
      //css预处理
      preprocessorOptions: {
        scss: {
          /*
          引入.scss全局预定义变量
          */
          additionalData: '@import "./src/assets/scss/globalVariable.scss";@import "./src/assets/scss/iconfont.scss";'
        }
      }
    }
    

    窗口优化

    由上图可以看到,默认的菜单栏、最小化最大化关闭按钮都不是很美观,所以我们来自定义一下。

    掉标题栏和边框

    修改electron-main/index.ts

    ...
    mainWindow = new BrowserWindow({
      ...
      frame: false, // 标题栏和边框一并隐藏
    });
    ...
    

    自定义标题栏

    新建组件components/c-header.vue,利用 flex布局 两端对齐,左侧程序名称,右侧最小化、最大化和关闭按钮

    <template>
      <div class="header flex">
        <div class="header-title flex1 flex-align-center">Todo List</div>
        <div class="header-btns" v-if="showBtn">
          <component :is="components.get(compName)" type="min" title="最小化" content="icon-jianhao"></component>
          <component :is="components.get(compName)" type="max" title="最大化" content="icon-fangxingweixuanzhong"></component>
          <component :is="components.get(compName)" type="close" title="关闭" content="icon-guanbi1"></component>
        </div>
      </div>
    </template>
    
    <script setup lang="ts">
    import { defineAsyncComponent, ref } from 'vue'
    
    // 判断是node还是浏览器环境
    // 浏览器环境就不用显示最小化、最大化、关闭按钮
    // 根据环境动态加载组件
    // 如果不这样处理,浏览器会报错 require undefault
    let showBtn = typeof global!='undefined'
    const components = ref(new Map<string, any>())
    if(showBtn){
      components.value.set(
        'headerBtn',
        defineAsyncComponent(() => import('./c-header-btn.vue'))
      )
    }
    const compName = ref('headerBtn')
    
    </script>
    
    <style lang="scss" scoped>
    .header{
      -webkit-app-region: drag;
      padding: 15px 15px;
      &-title{
        font-weight: 600;
      }
      &-btns{
        &>div{
          &:last-child{
            padding-right: 0;
          }
        }
      }
    }
    </style>
    

    上面的 flex 默认选择器在全局的scss里面以书写

    // assets/scss/globalVariable.scss
    .flex {
      display: flex;
      .flex1{
        flex: 1;
      }
    }
    
    .flex-align-center {
      @extend .flex;
      align-items: center;
    }
    
    .flex-space {
      @extend .flex;
      justify-content: space-between;
    }
    
    .flex-space-center {
      @extend .flex;
      align-items: center;
      justify-content: space-between;
    }
    
    .flex-center-center {
      @extend .flex;
      align-items: center;
      justify-content: center;
    }
    
    .flex-row {
      flex-direction: row;
    }
    
    .flex-col {
      flex-direction: column;
    }
    
    .flex-wrap {
      flex-wrap: wrap;
    }
    

    新建components/c-header-btn.vue

    <template>
      <div 
        class="c-header-btn" 
        v-on:click="click">
        <i class="iconfont" :class="content"></i>
      </div>
    </template>
    
    <script lang="ts">
    import electron from 'electron';
    
    export default {
      name: 'c-header-btn',
      props: {
        type: [String],
        content: [String],
      },
      data(){
      },
      methods: {
        click: function () {
          if(this.type && typeof global!='undefined'){
            // 向主进程发送异步消息,下面在electron-main/index.ts接收
            electron.ipcRenderer.send(this.type);
          }
        }
      }
    }
    </script>
        
    <style lang="scss" scoped>
    .c-header-btn {
      position: relative;
      padding-right: 15px;
      -webkit-app-region: no-drag;
      color: #2798f7;
      cursor: pointer;
      display: inline-block;
      &:hover i{
        color: #ED5A5A;
      }
    }
    </style>
    

    electron-main/index.ts监听按钮事件

    // electron-main/index.ts
    import { ..., ipcMain } from 'electron';
    ...
    let mainWindow : any;
    
    const createWindow = () => {
      mainWindow = new BrowserWindow({
        ...
      });
    }
    
    // 监听自定义按钮事件,并作出相应动作
    // 最小化应用程序
    ipcMain.on('min', e => mainWindow.minimize())
    // 最大化应用程序
    ipcMain.on('max', e => {
      if (mainWindow.isMaximized()) {
        mainWindow.unmaximize()
      } else {
        mainWindow.maximize()
      }
    })
    // 关闭应用程序
    ipcMain.on('close', e => mainWindow.close())
    

    App.vue 导入 c-header.vue 组件

    <script setup lang="ts">
    // This starter template is using Vue 3 <script setup> SFCs
    // Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
    import cHeader from './components/c-header.vue'
    </script>
    
    <template>
      <div class="layout flex flex-col">
        <c-header/>
      </div>
    </template>
    
    
    <style lang="scss" scoped>
    .layout {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      color: #2c3e50;
      height: 100%;
    }
    </style>
    

    [图片上传失败...(image-84c3e6-1652432201196)]

    todo list 事项面板UI

    新建components/c-main.vue

    <script setup lang="ts">
    
    </script>
    
    <template>
      <div class="main">
        <div class="group">待处理</div>
        <div class="group">进行中</div>
        <div class="group">待发布</div>
        <div class="group">已发布</div>
        <div class="group">已完成</div>
        <div class="group">待观察</div>
      </div>
    </template>
    
    <style lang="scss" scoped>
    .main{
      overflow-x: auto;
      white-space: nowrap;
      padding: 0 15px;
      .group{
        display: inline-block;
        width: 200px;
        height: 100%;
        margin-right: 10px;
        // 随机背景色,用来看清布局
        @for $i from 1 through 30 {
        &:nth-child(#{$i}) {
            background: rgba(random(255), random(255), random(255), 0.8);
          }
        }
      }
      
    }
    </style>
    

    事项分组group可能有N个,所以这里css样式让group一直向右排列,overflow-x: auto; white-space: nowrap;

    App.vue 导入 c-main.vue 组件

    <script setup lang="ts">
    ...
    import cMain from './components/c-main.vue'
    </script>
    
    <template>
      <div class="layout flex flex-col">
        <c-header/>
        <c-main class="flex1"/>
      </div>
    </template>
    

    [图片上传失败...(image-987bd8-1652432201196)]

    结语

    到这里,项目的UI框架基本结束,下一章节将集成 Vue.Draggable 拖拽任务。

    本项目将持续更新,希望你也持续关注。

    项目地址

    相关文章

      网友评论

          本文标题:Electron+Vue3+TypeScript+Vite桌面应

          本文链接:https://www.haomeiwen.com/subject/emkuurtx.html