Quasar 學習筆記 Ep 01 - Vue3 與 Quasar 程式架構比較
Vue3 與 Quasar 程式架構比較
坊間其實關於 Vue.js 的書籍很多,但是很多都是由 Vue 2.0 改版過來的,所以在學習的過程中,看到的範例都程式片段,很難把所有的東西連貫起來。這篇文章的目的,就是實際使用 Visual Studio Code 一步一步地建立出樣版程式,然後以實際的操作來說明 Vue 以及 Quasar 的整體程式架構。相信對於初學者會有一定的幫助。
- 使用 VSC 內的終端機建立一個標準的 Vue 3 Project
- Vue 3 Project 程式起始點說明與簡單的導覽
- 使用 VSC 內的終端機建立一個標準的 Quasar Project
- 比較兩者差異
- 執行展示
以 Visual Studio Code 建立 Vue Project
要建立一個樣板 Vue Project,請先開啟cmd視窗,在這裡我直接使用 VSC 裡面的 Command Prompt 終端機亦可。然後進入project 根目錄,然後輸入指令 vue create hellovue,然後就會出現下面的詢問畫面:
請按照指示,cd 到專案目錄,然後執行 npm run serve,就可以在網頁上看到結果。請 copy http://localhost:8080/ 然後貼到瀏覽器上,即可執行。下圖就是執行結果,顯示一個圖示並有一些說明與鏈結。
如果各位有寫網頁的經驗,通常網站的首頁為 index.html,這是網頁的進入點,是自動產生的,我們並不需要做修改,其中的註解已經有說明:<!-- built files will be auto injected -->
至於Vue 程式的進入點,則是 main.js,這跟 C 語言的起始點是 main() 很類似,程式內容如下:
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
主要只做兩件事情,import 根元件 App.vue 並建立 App 實體物件(Model),然後綁定到 #app 這個網頁節點(View)。也就是說,main.js 會負責將 "App" 這個元件所要顯示的內容,顯示在 index.html 裡面 <div id="app"></div> (對應到 '#app' 名稱) 這個節點裡面。main.js 也完全不需要更動程式碼,重點就在 App.vue 這個根元件之中。
<template>
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
既然 index.html main.js 都不需更動,請把重點放在 App.vue 元件上面,由於這是第一個元件,我把它定義為根元件,其他的子元件像是 HelloWorld 則是放在 components 目錄底下。
我的建議是,遵照樣板程式的架構與寫法來撰寫我們的程式,不要嫌麻煩,也就是說,不要把所有程式都寫在App.vue裡面,而要拆分成不同的子元件,實際程式內容都寫在子元件裡面。
元件檔 (.vue) 的結構分成三個部分,<template> 是要顯示在網頁裡面的 html 內容,<style> 是拆分出來的CSS,<script> 則是程式碼。
網頁顯示的 html 內容很單純,就是<img> 標籤顯示一個圖示,以及 <HelloWorld> </HelloWorld> 我們自定義的標籤。這種大駝峰的命名在 html 的標籤裡面並不標準,所以我們也可以用 <hello-world> </hello-world> 來代替。這裡很奇妙,物件定義的名稱是 HelloWorld,但我們在html 裡面寫 hello-world 是相容的。
至於 <hello-world> 標籤做什麼事情,則是寫在 <script> 裡面。這裡只做一件事情,就是去執行 HelloWorld.vue,我們看看 HelloWorld 的內容:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
謎底解開了,所有要顯示的內容都在這裡。
建立一個標準的 Quasar Project
同樣的,我們在projects 根目錄底下輸入指定 quasar create helloquasar 即可建立專案。
前面的問題,都可以使用 Default 值,直接按 Enter,只有問到 ? Continue to install project dependencies after the project has been created? 的時候要注意一下,像我是使用 npm,所以我會選擇 > Yes, use NPM。
Project 建立好之後,進入 helloquasar 目錄,輸入 quasar dev,便開始編譯並執行:
接下來,Quasar程式由哪裡執行?我們必須擺脫 Vue 的思維,因為 index.html 與 main.js 都不存在,我們就跳到第一個會執行的根元件 App.vue,這裡就是程式的起點。
<template>
<router-view />
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
name: 'App'
})
</script>
App.vue 裡面,定義了網頁實際要渲染的內容為 <router-view/>,以 vue 的架構而言,路由的定義會在 ./router 目錄中,當此目錄被執行時,第一個會被執行的檔案就是 index.js,所以,接下來,程式就會執行到 ./router/index.js。打開此檔案,你就會發現終於可以找到線索了,請看第三行。
import { route } from 'quasar/wrappers'
import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router'
import routes from './routes'
在 index.js 的第三行,又 import 了定義路由的程式 routes.js。以下是程式內容:
const routes = [
{
path: '/',
component: () => import('layouts/MainLayout.vue'),
children: [
{ path: '', component: () => import('pages/Index.vue') }
]
},
// Always leave this as last one,
// but you can also remove it
{
path: '/:catchAll(.*)*',
component: () => import('pages/Error404.vue')
}
]
export default routes
Router 的用法我們未來的章節在討論,想像你的網頁有一個組織架構圖,最頂層的 component 就是 MainLayout.vue,下面有好幾頁,而第一頁就是 Index.vue。
先看簡單的,開啟 Index.vue 首頁元件,內容很簡單,就是顯示 <q-page> </q-page> 裡面的內容:
<template>
<q-page class="flex flex-center">
<img
alt="Quasar logo"
src="~assets/quasar-logo-vertical.svg"
style="width: 200px; height: 200px"
>
</q-page>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
name: 'PageIndex'
})
</script>
重點會是在 MainLayout.vue,它在 layouts 目錄裡面,在這裡定義了路由的 Layout:
<template>
<q-layout view="lHh Lpr lFf">
<q-header elevated>
<q-toolbar>
<q-btn
flat
dense
round
icon="menu"
aria-label="Menu"
@click="toggleLeftDrawer"
/>
<q-toolbar-title>
Quasar App
</q-toolbar-title>
<div>Quasar v{{ $q.version }}</div>
</q-toolbar>
</q-header>
<q-drawer
v-model="leftDrawerOpen"
show-if-above
bordered
>
<q-list>
<q-item-label
header
>
Essential Links
</q-item-label>
<EssentialLink
v-for="link in essentialLinks"
:key="link.title"
v-bind="link"
/>
</q-list>
</q-drawer>
<q-page-container>
<router-view />
</q-page-container>
</q-layout>
</template>
<script>
import EssentialLink from 'components/EssentialLink.vue'
const linksList = [
{
title: 'Docs',
caption: 'quasar.dev',
icon: 'school',
link: 'https://quasar.dev'
},
{
title: 'Github',
caption: 'github.com/quasarframework',
icon: 'code',
link: 'https://github.com/quasarframework'
},
{
title: 'Discord Chat Channel',
caption: 'chat.quasar.dev',
icon: 'chat',
link: 'https://chat.quasar.dev'
},
{
title: 'Forum',
caption: 'forum.quasar.dev',
icon: 'record_voice_over',
link: 'https://forum.quasar.dev'
},
{
title: 'Twitter',
caption: '@quasarframework',
icon: 'rss_feed',
link: 'https://twitter.quasar.dev'
},
{
title: 'Facebook',
caption: '@QuasarFramework',
icon: 'public',
link: 'https://facebook.quasar.dev'
},
{
title: 'Quasar Awesome',
caption: 'Community Quasar projects',
icon: 'favorite',
link: 'https://awesome.quasar.dev'
}
];
import { defineComponent, ref } from 'vue'
export default defineComponent({
name: 'MainLayout',
components: {
EssentialLink
},
setup () {
const leftDrawerOpen = ref(false)
return {
essentialLinks: linksList,
leftDrawerOpen,
toggleLeftDrawer () {
leftDrawerOpen.value = !leftDrawerOpen.value
}
}
}
})
</script>
如何渲染出選單的項目呢?就定義在 EssentialLinks.vue 裡面。
<template>
<q-item
clickable
tag="a"
target="_blank"
:href="link"
>
<q-item-section
v-if="icon"
avatar
>
<q-icon :name="icon" />
</q-item-section>
<q-item-section>
<q-item-label>{{ title }}</q-item-label>
<q-item-label caption>
{{ caption }}
</q-item-label>
</q-item-section>
</q-item>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
name: 'EssentialLink',
props: {
title: {
type: String,
required: true
},
caption: {
type: String,
default: ''
},
link: {
type: String,
default: '#'
},
icon: {
type: String,
default: ''
}
}
})
</script>
結論
今天的筆記單純分享 Vue 與 Quasar 的程式架構,還沒有動到程式,至於要如何在這個標準框架下寫程式,我們日後再分享。
留言
張貼留言