Quasar 學習筆記 Ep 03 - Quasar 的 MainLayout 元件

 Quasar 的 MainLayout 元件

當我們以 Quasar CLI 建立一個標準的 MPA 如下,這個網頁分成幾個部分,首先是左邊會有一個選單,這個選單的開關就在上方的 [三] 按鈕,上方藍色的部分是 Toolbar,顯示網站的名稱以及 Quasar 的版本。


控制這些介面的核心,就在於 MainLayout 元件。今天我將會分享以下的主題:
  1. MainLayout 元件
  2. 使用 Layout Biulder
  3. 將 Home / About / News 加入 Drawer (Mobile App Style)
  4. 將 Home / About / News 加入 Tab (Web Style)

MainLayout 元件

首先我們看一下 MainLayout.vue 裡面的 <template> 段。

<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>

為了方便解釋,我們先看網頁所呈現的樣貌是如何在 MainLayout 裡面定義的,整個網頁內容是包在 <template></template> 中,<q-layout> </q-layout> 定義網頁的樣貌,包含三個部分,上方藍色的 Header,左邊的 Drawer,以及中間的 Page。

<template>
  <q-layout>
    <q-header>
      <q-toolbar>
        <q-btn/>
        <q-toolbar-title> XXX </q-toolbar-title>
      </q-toolbar>
    </q-header>

    <q-drawer>
      <q-list>
        <q-item-label> XXX </q-item-label>
      </q-list>
    </q-drawer>

    <q-page-container>
      <router-view />
    </q-page-container>
  </q-layout>
</template>

Header 定義在 <q-header> </q-header> 中,裡面放了一個 Toolbar,<q-toolbar> </q-toolbar>裡面又放了兩樣東西,分別是 <q-btn/> 按鈕用來控制左邊的 Drawer 開合,<q-toolbar-title> 則顯示標題文字。

Drawer 選單裡面的選項,則是定義在 <q-list> </q-list> 裡面,實際渲染方式我們後面再談。

最後是網頁(Page),定義在 <q-page-container> 中,實際渲染的內容則是由 Router 控制,故只需要加入 <router-view/>。

Layout Builder

Quasar 的 Layout 可以利用 Layout Builder 來製作,可以省去寫程式的時間,請在瀏覽器輸入網址:https://quasar.dev/layout-builder,即可進入。


第一步,我們可以選取這五個項目,來決定網頁基本的格局。如果要重現 helloquasar 的網頁 Layout,請取消 QFooter,Right-Side QDrawer,以及Navigation Bar。


為了讓自己看得更清楚,你可以全部選取來做測試,按下 Continue 進入下一頁。


我只用兩句話來說明:
  1. 四邊 上(h / H)下(f / F)左(l / L)右(r / R):大寫代表 Page 捲動時,固定在網頁上不動;小寫代表跟著捲動。
  2. 四角 左上(l / h) 右上(r / h) 左下(l / f) 右下(r / f):選擇哪個要在上面。
完成之後,按下 Export Layout 就會產生程式碼,我們複製之後貼在 MainLayout.vue 裡面即可。其中 <q-layout view="lHh Lpr lFf"> 就是九宮格裡面上中下三個字串。

Drawer 的選項內容

      <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>

裡面只有一個 Quasar 標籤命令,就是 <q-list>,裡面定義了 Label 跟內容,所有的內容,都是由 EssentialLink 元件來處理,傳入元件的參數,使用了 v-for="link in essentialLinks" ,所以我們要來找一下 essentialLinks 這個陣列,它放在 <script> 中:

<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>

這裡使用了 Vue Composition API 的程式寫法,以 setup() 包裝了資料跟方法,我們先不深究,不過馬上就可以看到 essentialLinks: linksList ,所以馬上在看 linksList 的內容,在 <script> 上面,每一個 item 都依照下面的方式來定義。

  {
    title: 'Docs',
    caption: 'quasar.dev',
    icon: 'school',
    link: 'https://quasar.dev'
  },

當這個陣列以 v-for 傳入 EssentialLink 元件之後,所有 items 就會一一渲染出來。

EssentialLink.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>

將 Home / About / News 網頁放入 Drawer 選單

原本範例程式中的選單,都是一些連結,點選時就會開啟一個新的網頁,然後連結到另一個 Quasar 相關的網站。現在我們就來實作將 Home/About/News放在前三個選項裡面。

先確定你已經依照 Ep 02 的步驟,對程式做了修改,並且可以用 http://localhost:8080/about 以及 http://localhost:8080/news 能夠看見網頁內容,接著我們就來修改 MainLayout.vue。

const linksList = [
  {
    title: '首頁',
    caption: '本網站的首頁',
    icon: 'school',
    link: ''
  },
  {
    title: '關於',
    caption: '關於本網站的說明',
    icon: 'code',
    link: 'about'
  },
  {
    title: '最新消息',
    caption: '宣布本網站的最新動態',
    icon: 'chat',
    link: 'news'
  },

然後我希望點選之後,能夠在原本的網頁裡面顯示,而不要新開一個網頁,所以再開啟 EssentialLink.vue,將 target="_blank" 改為 target="_self"

<template>
  <q-item
    clickable
    tag="a"
    target="_self"
    :href="link"
  >

執行結果。


如果想改變 icon,可以進入 https://fonts.google.com/icons?selected=Material+Icons 網站,找到想要的 icon 名稱,修改程式中 icon 字串。

  {
    title: '首頁',
    caption: '本網站的首頁',
    icon: 'home',
    link: ''
  },
  {
    title: '關於',
    caption: '關於本網站的說明',
    icon: 'lightbulb',
    link: 'about'
  },
  {
    title: '最新消息',
    caption: '宣布本網站的最新動態',
    icon: 'newspaper',
    link: 'news'
  },

App Style vs. Web Style

目前 helloquasar 的執行結果,其實比較像是手機App 的風格,如果手機跟電腦是連接通一個無線網域,我們就可以在手機裡面看到執行結果:

 

而過去在網頁上的風格通常子網頁的按鈕會在 Header 上面。


如果想要做成 Tab 的形式,如果不想自己寫程式,可以利用 Layout Builder,選擇 Navigation Tabs,然後就會得到下面的程式碼:

<q-tabs align="left"> <q-route-tab to="/page1" label="Page One" /> <q-route-tab to="/page2" label="Page Two" /> <q-route-tab to="/page3" label="Page Three" /> </q-tabs>

加入到 MainLayout.vue 的 </q-toolbar> 與 </q-header> 之間,並調整程式碼,如下圖:

    <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-tabs align="left">
        <q-route-tab to="/" label="首頁" />
        <q-route-tab to="/about" label="關於本站" />
        <q-route-tab to="/news" label="最新消息" />
      </q-tabs>
    </q-header>

執行結果如下:


這種 Style 我稱為 Web Style,如果手機 App 也要加,我建議加在 Footer 裡面會比較好。完整程式碼如下:

<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-footer>    
        <q-tabs align="left">
        <q-route-tab to="/" label="首頁" />
        <q-route-tab to="/about" label="關於本站" />
        <q-route-tab to="/news" label="最新消息" />
      </q-tabs>
    </q-footer>
  </q-layout>
</template>

手機展示結果:


各位覺得呢?

留言

這個網誌中的熱門文章

Python可以這樣玩(16):共陰/共陽七段顯示器

Python可以這樣玩(11):數學繪圖

Python可以這樣玩(15):蜂鳴器與音樂