[重构倒数第28天] - 关於拆分 Components 的学问

前言

该系列是为了让看过Vue官方文件或学过Vue但是却不知道怎麽下手去重构现在有的网站而去规画的系列文章,在这边整理了许多我自己使用Vue重构很多网站的经验分享给读者们。

我要怎麽下第一刀?

很多人都会问我说,在写 vue component 的时候,怎麽样判断这个东西要不要拆分成更细 component ? 或是当你接手人家的vue专案的时候,前人留下来的 component 有没有必要在拆分呢?
mike

大部分的同学都会抱持者在继续往下写点东西再来决定的心态,然後就会造成 script、template、style 越写越长,最後让你的 component 变成一发不可收拾的地步...

先说结论

我们先不要管说这个元件是否会共用,单凭你的 component 里面 script、template、style 加起来大约200 ~ 300行时,其实你就应该要先考虑切你的 component,再来谈其他的共用 component 之类的...

我的专案 component 几乎不会超过300行。

其原因有四:

  1. 当你的script、template、style加起来大约200 ~ 300行的时候,你的vue template语法以及你的script逻辑会绑再一起太多,而且加上控制画面的 style的资料以及 css的结构会太复杂,当要改动起来是一件很费力的事情,由其实第一次看到这个component的时候会看的很辛苦。
  2. vue template 语法以及你的script逻辑会绑再一起太多的时候,这时候要再来切component会有点麻烦,毕竟全部写在一起跟拆成component做资料传递上面,写的逻辑就有点不一样了。
  3. 可以减少动一发牵动全身的状况,当出现问题的时候可以更清楚找到问题点,对於资料传递的input、output也更加的明白。
  4. 很多时候我们在写程序很容易把众多逻辑跟写在一起,造成难以维护以及阅读的情况,适度的切component可以训练你对於逻辑的拆解能力,降低各个逻辑的耦合性,减少逻辑之间的量子纠缠。

Component也有类别?

Vue 里面我把 Component 分成三大类 Page components、Global components、UI components

  • Page components : 每个独立页面的 component,例如像是首页、关於我们、产品列表等,都是一个独立的页面 component。

  • Global components : 网页中你会有很多东西是在每个页面都会出现,例如弹出视窗,或是你的 Header 或 Footer 组件等等这类型的 components。

  • UI components : 这个囊括了一般我们做元件拆分出来的 component 以及拆分 global components 里面的内容,我都归类在 UI components,只是一般页面上用到的 component 不会被归类在 global 之中。

为了让大家更好理解,我们来看看以下设计稿
Vue3 Mike

我大概用以上三种分类的方式切分了一下component
Vue3 Mike

所以我们可以从这张图很简单的来清楚明了目前切的 component 是属於哪个类别的。

在我们了解 component 是属於哪个类别後我们就要对於专案之中 component 的摆放的资料夹开始去切分,我大概简单的分类一下

|-- src
        |-- App.vue
        |-- main.js
        |-- api
        |   |-- index.js
        |-- assets
        |   |-- images
        |       |-- load.gif
        |       |-- logo.png
        |-- components
        |   |-- Global
        |   |   |-- Alert
        |   |   |   |-- index.vue
        |   |   |-- Footer
        |   |   |   |-- index.vue
        |   |   |-- Header
        |   |   |   |-- index.vue
        |   |   |-- Login
        |   |       |-- index.vue
        |   |-- Loading
        |   |   |-- CardLoading.vue
        |   |   |-- PageLoading.vue
        |   |-- Product
        |       |-- Card.vue
        |       |-- CardItem.vue
        |-- router
        |   |-- index.js
        |-- store
        |   |-- index.js
        |-- view
            |-- About.vue
            |-- Home.vue
            |-- News.vue
            |-- Product.vue

我会把 Page components 放入 view 的资料夹中,然後把 Global components、UI components 放入 components 的资料夹,然後把页面自己的 component 放到该页面的资料夹里面再去做细分。

然後关於我们使用 component 这件事

我在载入的组件的时候会像这样子

<script>
import { ref } from "vue";
import Dynamic from "@/components/Dynamic.vue";
export default {
  components: {
    Dynamic,
  },
  setup() {
    const isShow = ref(false);
    const Open = () => (isShow.value = true);
    return { isShow, Open };
  },
};
</script>

<template>
  <button id="show_btn" @click="Open">click</button>
  <Dynamic v-if="isShow" />
</template>

透过 import 载入 Dynamic.vue

import Dynamic from "@/components/Dynamic.vue";

然後再 components 里面挂载 Dynamic 这个组件,然後放在 template,透过 v-if 来决定是否渲染出来,这样基本上没有什麽问题。

But...

就像上面这个范例一样,我们网页上面一开始的时候有些component是不想一开始就 show 出来的,所以会透过 v-if 来把它藏起来,不要让使用者在开发者工具上面找到,但是这样的载入方式会在网页一开始载入资源的时候会一起把这个一开始不需要出现的 component 给也打包进来,当你的网页越来越巨大的时候,这样子的 component 会造成网站的载入负担,那要怎麽解决这个问题呢?

我们可以透过 dynamic import 的方式来解决这个问题。

使用 dynamic import

<script>
import { defineAsyncComponent, ref } from "vue";
export default {
  components: {
    Dynamic: defineAsyncComponent(() => import("@/components/Dynamic.vue")),
  },
  setup() {
    const isShow = ref(false);
    const Open = () => (isShow.value = true);
    return { isShow, Open };
  },
};
</script>

<template>
  <button id="show_btn" @click="Open">click</button>
  <Dynamic v-if="isShow" />
</template>

我们可以透过import('@/components/Dynamic.vue')这样的语法来让我们的 component 变成动态载入的components,也就是说当我画面上的 isShow 变成 true 的时候,我的 < Dynamic /> 的组件被渲染到网页上面的时候,它才会载入这个资源,以减少一开始浏览器载入网页资源的效率。

在 Vue3里面如果你要使用 dynamic import来载入 component 的话,你要用defineAsyncComponent 这个函式才可以使用dynamic import喔。
参考官方连结: https://v3.vuejs.org/guide/component-dynamic-async.html#async-components

我们可以来比较一下两种载入方式的差异

.这是我们使用一般 import 的方式

Vue3 Mike

.这是我们使用 dynamic import 的方式

Vue3 mike

从这边你就可以知道说使用 dynamic import 可以让你在需要的时候在载入这个 component 就好了,不需要一开始的时候都载入,至於你要使用哪一种载入方式就依照你的页面上面的逻辑再来决定你的 import 方式吧!

好啦! 今天介绍如何拆分 component 就到这边啦,其实拆分 component 每个人的想法或许也都不太一下,我把过往工作上面拆分 component 的经验分享出来给大家参考一下,希望有帮助到对於拆 component 有障碍的同学,如果有其他的拆分 component 有不一样想法的朋友也欢迎底下留言一起讨论。

Mike Vue

那如果对於Vue3不够熟的话呢?

Ps. 购买的时候请登入或注册该平台的会员,然後再使用下面连结进入网站点击「立即购课」,这样才可以让我获得更多的课程分润,还可以帮助我完成更多丰富的内容给各位。

我有开设了一堂专门针对Vue3从零开始教学的课程,如果你觉得不错的话,可以购买我课程来学习
https://hiskio.com/bundles/9WwPNYRpz?s=tc

那如果对於JS基础不熟的朋友,我也有开设JS的入门课程,可以参考这个课程
https://hiskio.com/bundles/b9Rovqy7z?s=tc

订阅Mike的频道享受精彩的教学与分享

Mike 的 Youtube 频道
Mike的medium
MIke 的官方 line 帐号,好友搜寻 @mike_cheng


<<:  [Day03] CH02:告诉我你是谁——变数的宣告

>>:  Day 3:Kotlin 程序设计基础入门 (2)

【Day 16】- 做 Excel 输入数据到心累?消警告的服学输入很繁琐? 使用 openpyxl 来操作 Excel

前情提要 前一篇带各位实作了爬取币种汇率的爬虫。 开始之前 本篇将带各位在 Python 中操作 E...

6.unity建立C#脚本

今日目标:了解C# script (脚本) unity主要利用C#控制游戏,学好C#的物件导向写法就...

[Day 39] 心情随笔後台及前台(一) - 心情随笔列表

心情随笔後台及前台 今天我们终於要进行心情随笔的部分, 首先是要建後台画面及功能, 我们的心情随笔就...

Kotlin Android 第9天,从 0 到 ML - 介面与抽象类别 / 泛型 / 扩充

前言: 今天来看 介面与抽象类别 / 泛型 / 扩充 大纲: Interface 介面,像是一个SO...

Day 30. 要怎麽动

啊哈,所以理论上我的第一个菜单做好了,但是因为我做的是VR菜单,所以移动手臂要靠Tracked Po...