Vue3 實用部分(I)

錢端工程師JW (Jinwei)
10 min readMar 27, 2021

本章節主要是給稍微了解vue,或是有寫過其他框架,會跑基本迴圈與判斷v-if , v-for等概念的人,可以進一步了解vue的特殊實用部分。主要會介紹

  1. Vue 3 CreateApp: 了解vue是如何產生並附著在html的基本概念
  2. Vue App註冊component
  3. Vue children: <slot>
  4. 特殊tag <keep-alive> <teleport>

Vue 3 CreateApp()

使用框架或套件,我們常常看了教學影片或文章,套用的過程中發現有畫面、資料就直接開發下去了。團隊中通常也有人已經把開發環境建好,我們只要直接開發即可。也因此我們忽略了框架的原則原理,沒有基本的原理認知,很多時候畫面出不來時debug自然時間就會拖很長。今天主要介紹vue app是如何讓web運作的

不可或缺的兩個檔案

  • public/index.html : vue在渲染html的入口檔案
  • src/main.js: 透過main.js 找到渲染的節點並渲染App

PS: 左邊是使用vue cli的預設結構,右邊是精簡化的檔案結構

Vue Cli 檔案結構

實作createApp

使用vue cli 產出檔案後把檔案刪成剩下右邊模樣,只剩

/node_modules
/public
index.html
/src
main.js 空的檔案
  1. 新增入口App

在src中新增App.vue

app.vue 建立資料

2. createApp

/src/App.vueimport { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
mountApp 後出現畫面

我們也可以把createApp與mount分開寫

/src/App.vueimport { createApp } from 'vue'import App from './App.vue'const app = createApp(App);app.mount('#app')

3. 加入 component

app.component(<模組名稱>) 可直接在App中加入模組

import { createApp } from 'vue'import App from './App.vue'import ActiveUser from './components/ActiveUser.vue'
const app = createApp(App);
app.component(ActiveUser);
// 也可使用 app.component('active-user', ActiveUser);app.mount('#app')
新增components

在App.vue裡面使用active-user

直接使用active-user

PS: 這邊也可以採取另一種做法,直接在App.vue import ,就不需要在main.js 中app.component了

然而,看到這邊你可能會有一個疑問。

那就是如果有100個模組是否就要在main.js裡面加入?

如果加了100個,所有頁面都能直接使用非常方便,但卻犧牲了效能。可能某些模組只被使用過一次,但其他不相干的頁面卻需要將這些模組初始化。

因此需要釐清global 與local 模組的概念

註冊在main.js中的global components

Global & Local component!

Global: 全域,意味著所有其他子模組都可以使用

Local: 區域,表示只在特定檔案檔案才使用到該模組。

將global 改成local: 1. 引入=> 2. 註冊=> 3. 使用

其中components的寫法有非常多種,挑一種適合自己的。推薦指數由高到低(上到下),大家看下方程式碼就知道為什麼了。

components: {

UserInfo,
// UserInfo: UserInfo // "user-info": UserInfo, => 這種寫法在使用上只能用<user-info> 不能用大駝峰UserInfo (React寫法)
}
App.vue 使用模組

後續在main.js就可以把該模組拿掉了

main.js
scope限制CSS影響範圍

Slot

寫過react的人可以直接把slot想成是react的children。當模組要調用父層所包的html tag時。

//React <ChildComponent>
{props.children}
</ChildComponent>
//Vue<ChildComponent>
<slots></slots>
</ChildComponent>

接著我們來看實際使用起來的程式碼

App.vue (加入slot前)

新增一個BaseCard.vue 的模組

BaseCard.vue模組 (注意slot的位置)

後續把slot引入並包在BaseCard裡面

App.vue
BaseCard.vue 對照

此時可以看到user-info被夾在BaseCard的slots裡面了。

Multiple Slots

// Parenetcomponent
<ChildComponent>
<template v-slot:{slot名稱}></template> {其他地方會進入default slot中 (可不寫(包)template)}</ChildComponent>// ChildComponent<template> <slot name="slot名稱"></slot> <slot></slot> // 預設的slot 可不給名稱</template>
App.vue
BaseCard.vue

$slots => 在mounted的時候可以查看接收到的slot


mounted(){
console.log(this.$slots.<slotname>);
}

Scope Slots

使用情境:需要child component的資料,但需要父層客製化template

概念圖

// ChildCompo<template>    <ul>
<li v-for="goal in goals" : key="goal">
<slot :item="goal"></slot>
</li>
</ul>
</template><script>
export default{

}
</script>
// ParentCompo
<ChildCompo> <template #default="slotProps"> <h1> {{ slotProps.item }}</h1>
<p> {{ slotProps['another-prop'] }}</p>
</template></ChildCompo>

動態模組(Dynamic Components)

當切換不同模組可以使用v-if 並根據目前狀態來判斷要產生哪種狀態。

概念如下

App.vue
<button @click="setAliveCompo('a-component')">show a-compo</button>
<button @click="setAliveCompo('b-component')">show b-compo</button>
<a-component v-if="aliveComponent === 'a-component' "></a-component>
<b-component v-if="aliveComponent === 'b-component' "></b-component>
<script>
data(){ return{ aliveComponent: 'a-component';
};
}
methods:{ setAliveCompo(aliveCompo) { this.aliveComponent = aliveCompo
}
}
</script>

這種方式可以,不過太過冗長,Vue有提供Dynamic component 能夠支援切換不同的component

App.js
<a-component v-if="aliveComponent === 'a-component' "></a-component><b-component v-if="aliveComponent === 'b-component' "></b-component>----------------------- 上面這兩行修改成如下 ------------------------<component :is="aliveComponent"></component>

然而實際操作時,會發現component在切換時,會把原本的component 移除,因此如果不想要移除,可以再多加一<keep-alive>的tag。如此一來就不會被移除了。

<keep-alive>   <component :is="aliveComponent"></component></keep-alive>

將模組插入特定dom元素 <teleport to=”${dom}”>

開始寫vue才發現有這個神奇的功能。一般我們在使用popup window 時,基本上都會把window(modal)寫在<body>底下,不會寫在vue的app tag中。

但在vue app.vue的架構中,都一定會被包在<div id=”app”></div>裡面。而vue可以簡單幫我們達成這個需求。

<teleport to="body">   <modal-compo v-if="showModal"></modal-compo>  </teleport>

此時當modal-compo出現時就會被塞到<body> 中。

當然我們也可以讓to=”#app” 或是其他css的class中。有點類似jquery selector的方式。

以上就先介紹到這邊,基本上有了上述概念,在開發vue上會顯得更得心應手。之後的章節會再進一步介紹其他常用部分。

--

--

錢端工程師JW (Jinwei)

轉職前端變有錢! 從非本科系到外商前端工程師,熱愛分享學習知識及生活啟發。 關於我:https://www.instagram.com/richfront.jw 聯絡信箱: richfront.jw@gmail.com