Electron+Vue3 MAC 版日历开发记录(18)——Vue-Router 使用

2,253 阅读3分钟

这是我参与更文挑战的第18天,活动详情查看: 更文挑战

在开发之初,我把 Vue Router 这个给弱化了,本意想着这个项目是配合着 Electron 使用的,最好是一个“页面”呈现,避免一些路由的跳转,所以我只想了一个 Main 页面,把其它 route 都删除了:

import {createRouter, createWebHashHistory} from 'vue-router';
import Home from '/@/components/FullCalendarMain.vue';

const routes = [
  {path: '/', name: 'Home', component: Home},
  {path: '/about', name: 'About', component: () => import('/@/components/About.vue')}, // Lazy load route component
];

export default createRouter({
  routes,
  history: createWebHashHistory(),
});

但我参考了其他有关 Electron-Vue 写的开源代码,也都会很好的利用 Vue Router

所以,今天结合 Naive UI 重构「专注页面」的同时,把 Vue Router 用起来。

Vue Router

Vue RouterVue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举,就如同上面的代码所使用得那样,其实在项目里我们已经安装了:

"vue-router": "^4.0.6",

下面增加一个「专注」route

{path: '/focus', name: 'FocusViewSub', component: () => import('/@/components/FocusViewSub.vue')}, // Lazy load route component

这就是简单的介绍和使用 Vue Router。下面开始接着重构之旅。

重构 Focus View

因为改用了 Vue Router 模式,所以第一步就要把之前 Sidebar 组件移除:

// FocusViewSub.vue
<template>
  <Sidebar
    v-model:visible="sidebarVisible"
    class="p-grid nested-grid"
    :base-z-index="1000"
    position="full"
    @click="hideFocus"
  >
    <h1>专注模式</h1>
    <Vue3CountdownClock />
  </Sidebar>
</template>

直接变成了:

// FocusViewSub.vue
<h1>专注模式</h1>
<Vue3CountdownClock />

这样,也就把之前引用的 PrimeVue 组件移除了,还有包括其他参数。具体也可以看提交到 Github 上的代码。

<template>
  <h1>专注模式</h1>
  <Vue3CountdownClock />
</template>

<script lang="ts">
import { defineComponent, ref, provide, computed } from 'vue';
import Vue3CountdownClock from 'vue3-clock-countdown';
import Moment from 'moment';
import { useStore } from '/@/store';

export default defineComponent({
  name: 'FocusViewSub',
  components: {
    Vue3CountdownClock,
  },
  provide() {
    return {
      deadline: computed(() => Moment().add(this.store.state.focusTime, 'minute').format()),
    };
  },
  setup () {
    const Title = ref('进入倒计时');
    provide('title', Title);

    const timerStyle = ref({
      'text-align': 'center',
      'font-family': 'sans-serif',
      'font-weight': 100,
    });
    provide('timerStyle', timerStyle);

    const h1Style = ref({
      color: '#396',
      'font-weight': 100,
      'font-size': '40px',
      margin: '40px 0px 20px',
    });
    provide('h1Style', h1Style);

    const clockdiv = ref({
      'font-family': 'sans-serif',
      color: '#fff',
      display: 'inline-block',
      'font-weight': 100,
      'text-align': 'center',
      'font-size': '30px',
    });
    provide('clockdiv', clockdiv);

    const clockdivDiv = ref({
      padding: '10px',
      'border-radius': '3px',
      background: '#00BF96',
      display: 'inline-block',
      margin: '1px',
    });
    provide('clockdivDiv', clockdivDiv);

    const clockdivDivSpan = ref({
      padding: '15px',
      'border-radius': '3px',
      background: '#00816A',
      display: 'inline-block',
    });
    provide('clockdivDivSpan', clockdivDivSpan);

    const styleEndTime = ref({
      color: '#fff',
    });
    provide('styleEndTime', styleEndTime);

    const smalltext = ref({
      'padding-top': '5px',
      'font-size': '16px',
    });
    provide('smalltext', smalltext);

    const titleDays = ref('Days');
    provide('titleDays', titleDays);

    const titleHours = ref('Hours');
    provide('titleHours', titleHours);

    const titleMinutes = ref('Minutes');
    provide('titleMinutes', titleMinutes);

    const titleSeconds = ref('Seconds');
    provide('titleSeconds', titleSeconds);

    const titleEndTime = ref('End Time!');
    provide('titleEndTime', titleEndTime);

    const store = useStore();
    provide('store', store);
    return {
      store,
    };
  },
  methods: {
    hideFocus() {
      // this.$emit('update:visibleFocusView', this.sidebarVisible);
      window.electron.ipcRenderer.send('hide-focus-window');
    },
  },
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
@import "~/styles/default.scss";
</style>

Main 页面改为 route 跳转:

// FullCalendarMain.vue
// 修改之前
focusClick() {
  this.visibleFullSetting = false;
  this.visibleFocusView = true;
},

// 修改之后
focusClick() {
  this.visibleFullSetting = false;
  this.$router.push({ path: '/fucus' })
},

顺便把 FocusView 组件从 FullCalendarMain移除。

好了我们看看执行情况:

整个页面全屏展示了,很简洁,但是我们没有回退或者返回 Main 页面的操作按钮了。

增加「退出」逻辑。

「退出」逻辑

这里主要有两点来思考,第一个就是专注时间还没到时,是怎么退出的,另一个就是时间到了。

时间到了这个好处理,就做一个成功提示,然后直接回退回主界面。

那时间没到时的处理,我们需要增加一个特不显眼的「关闭」按钮,触发时,退出专注。

这里,需要借助 Naive UI固钉 Affix组件,把按钮钉在左上角:

<n-affix
:trigger-top="24"
style="margin-left: 24px;"
position="absolute"
>
<n-button
  text
  style="font-size: 24px;"
  @click="hideFocus"
>
  <n-icon>
    <times-circle-regular-icon />
  </n-icon>
</n-button>
</n-affix>

...

hideFocus() {
  this.$router.back();
  window.electron.ipcRenderer.send('hide-focus-window');
},

路由直接使用 back 返回。

关于图标按钮的使用可看:

还可以增加一个 Dialog 增加退出的“难度”,尽可能留在「专注」页面,达到专注的目标,之后再完善。

刚才说的第二种情况,等到倒计时结束后,直接执行方法 hideFocus 退出。但我看了看第三方组件 Vue3CountdownClock 并没有提供倒计时到了的提示反馈逻辑,所以我将准备着手制作一个倒计时组件,供自己或者大家使用,可以小小期待下~

小结

今天主要是记录开始使用 Vue Router 功能,并把专注页面从 Main 组件剥离出来,以及重构专注页面,以及为后续的自定义倒计时组件埋下伏笔。

未完待续!

代码已同步到 github 上了:github.com/fanly/fanly…