Note : บันทึก Workshop สร้าง Website ด้วย Node.js + Vue.js #Part 3

Artdvp
6 min readAug 14, 2018

--

Step 6— Introduce Vuetify

Vuetify เบื้องต้น

Vuetify คือ Material Design Component Framework สำหรับ Vue.js เพื่อใช้ในการจัดการแต่งหน้าเว็บ User Interface (UI) ให้สวยงามดูดีขึ้น

ซึ่งตัวที่ใช้จัดการ UI สำหรับ Vue.js นั้นมีหลายตัวสามารถหาดูได้จาก

ในที่นี้จะใช้ vuetify ในการตกแต่ง UI หน้าเว็บ

เริ่มจากการติดตั้งกันก่อน จะใช้ใน Project Nuxt.js ที่ทำไว้ก่อนหน้านี้ ให้เปิด Terminal ขึ้นมาใน Project แล้วพิมพ์คำสั่งติดตั้ง

$ npm install vuetify --save
# or
$ yarn add vuetify (กรณีติดตั้ง yarn ไว้แล้ว)

หลังจากติดตั้งแล้วไปดูที่ไฟล์ package.json จะมี dependencies vuetify เพิ่มมา

ต่อมาใน Document บอกว่าให้นำโค๊ดไปใส่ใน index.js หรือ main.js ของ Project Vue.js แต่กรณีนี้เราใช้ Nuxt.js จึงต้องไปสร้างที่ Plugins แทน

ให้สร้างไฟล์ชื่ออะไรก็ได้ในที่นี้ ตั้งชื่อว่า vuetify.js ในโฟลเดอร์ plugins แล้ว copy โค๊ดมาวาง

import Vue from 'vue'
import Vuetify from 'vuetify'

Vue.use(Vuetify)

จากนั้นต้องไปเพิ่มชื่อ plugins ในไฟล์ nuxt.config.js

plugins ก็คือชื่อของ ไฟล์ที่เราสร้างในโฟลเดอร์ plugins ในที่นี้คือ vuetify

ส่วน ~/plugins/vuetify ตัว ~ เป็นสัญลักษณ์พิเศษของ nuxt.js เพื่อบอกว่าอยู่โฟลเดอร์นอกสุด

vendor ก็คือชื่อของ package ที่เราติดตั้งไปในที่คือ vuetify

ถัดมาต้อง import style sheet ของ vuetify เข้ามาในโปรเจคด้วย ให้ไปที่ plugins/vuetify.js และเพิ่มโค๊ดด้านล่างลงไป

import 'vuetify/dist/vuetify.min.css'

ต่อจากนั้นให้ติดตั้ง font ชื่อว่า material-design-icons-iconfont ใช้ npm หรือ yarn ติดตั้ง package

$ npm install material-design-icons-iconfont
# or
$ yarn add material-design-icons-iconfont (กรณีติดตั้ง yarn ไว้แล้ว)

หลังจากติดตั้งเรียบร้อยแล้วให้เพิ่มโค๊ด import css เข้ามาในโปรเจคที่ไฟล์ plugins/vuetify.js

import 'material-design-icons-iconfont/dist/material-design-icons.css'

ต่อมาก็ให้สร้างไฟล์ main.styl ที่โฟลเดอร์ assets และใส่โค๊ดลงไปเพื่อตั้งค่าสีพื้นฐานของ vuetify

@require '~vuetify/src/stylus/settings/_colors'$theme := {
primary: $red.darken-2
accent: $red.accent-2
secondary: $grey.lighten-1
info: $blue.lighten-1
warning: $amber.darken-2
error: $red.accent-4
success: $green.lighten-2
}
// Import Vuetify styling
@require '~vuetify/src/stylus/main'

หลังจากนั้นต้องติดตั้ง package สำหรับ stylus ซึ่งเป็นไฟล์ style sheet ประเภทหนึ่งตามที่ได้สร้างไว้ด้านบน

$ npm install stylus stylus-loader

เมื่อติดตั้งเสร็จแล้วให้ไปตั้งค่าที่ nuxt.config.js อีกทีเพื่อใส่ google font และ import ไฟล์ main.styl มาในส่วน css

link: [
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' }
],
css: ['~/assets/main.styl']

จากนั้นสั่ง run โปรเจคและไปเช็คที่หน้าเว็บดู

npm run dev

ไปที่หน้าที่มี ปุ่ม button ตัวอย่างเช่น หน้า

http://localhost:3000/vue-ability/04-methods

จะพบว่า textbox และ button โดน style ของ vuetify ทำให้มองแทบไม่เห็นเลยทีเดียว

จากนั้นไปดูที่หน้าเว็บของ vuetify ในหน้า Button และเปิดโค๊ดดูตัวอย่างที่จะไปใช้

แล้วกลับมาที่ไฟล์ 04-methods.vue แล้วแก้ไขปุ่มเป็น code ของ vuetify ซึ่งต้องการปุ่มสีเขียวก็ใส่ color=”success”

แก้ไขแล้วกดเซฟ และไปดูที่หน้าเว็บซึ่งจะพบว่าปุ่มกลายเป็นสีขาวไม่ใช่สีเขียว (อ่าวเห้ย) แถมตัวหนังสือยังหายไปอีกด้วย (ไม่รู้เป็นอันใด)

แต่หลังจากไปแก้ไข เอา color=”success” ออกปุ่มดันแสดงตัวหนังสือเฉย (งงครับ)

จากนั้นลองใส่ icons ให้ปุ่มดู โอเคใช้ได้

ต่อมาโครงสร้างของ Web Application ในโค๊ดด้านล่างจะส่วนของ Layout ของ Vuetify จะถูกครอบด้วย <v-app>

<v-app>
<v-navigation-drawer app></v-navigation-drawer> <!--ส่วน Navbar ด้านซ้าย -->
<v-toolbar app></v-toolbar> <!-- ส่วน Toolbar ด้านบน -->
<v-content> <!-- ส่วนของ Content -->
<v-container fluid>
<router-view></router-view>
</v-container>
</v-content>
<v-footer app></v-footer>
</v-app>

Layouts ใน Nuxt.js จะอยู่ในส่วนของโฟลเดอร์ layouts/default.vue ซึ่งจะเป็นส่วนที่แสดงผลในทุกๆหน้าของ Web Application ตัวอย่างเช่น ถ้าแก้ไขไฟล์ layouts/default.vue ตามภาพจะแสดงข้อความด้านบนและให้ไปที่หน้า Main ของvue-ability

ลองกดที่ Home และสลับหน้าดูก็จะแสดงผลด้านบนเหมือนเดิมในทุกๆหน้า เนื่องจาก layouts default ของทุกหน้าจะใช้ code ที่ไฟล์ layouts/default.vue นั่นเอง

จากนั้นจะนำโค๊ดของ vuetify มาใส่ที่ไฟล์ default.vue แล้วเซฟดูผลลัพธ์หน้าจอ

<v-app>
<v-navigation-drawer app></v-navigation-drawer>
<v-toolbar app></v-toolbar>
<v-content>
<v-container fluid>
<nuxt/> <!-- แก้ไข <router-view></router-view> ใช้ nuxt แทน -->
</v-container>
</v-content>
<v-footer app></v-footer>
</v-app>

จากภาพหน้าจอจะทำให้ style ของ vuetify ใช้งานได้ แต่สีของเมนูจะมองไม่เห็นอีกแล้ว ให้ไปที่หน้าเว็บ vuetify เมนู Application layout > Predefined layouts ในที่นี้จะลองใช้ Dark layout

แล้วกดไปดู source code copy ทั้งหมดมามาวาง จะเห็น@click=”” ให้ลบออกไปเพราะจะ error ส่วนของ tag ข้างใน <v-content> ให้ลบออกแล้วใส่ <nuxt/> เข้าไปแทน จะได้ตามภาพโดยสามารถกดปุ่มด้านบนเพื่อเปิดปิดเมนูได้

จบ vuetify แบบพื้นฐาน…

พื้นฐาน SSR (Server Side Rendering) และ SPA (Single Page Application)

  1. SSR (Server Side Rendering)

คือหน้าเว็บที่ถูก Render มาจากโค๊ดฝั่ง Server มาเป็นก้อน html ตั้งแต่เริ่มต้น

อย่างเช่น ถ้าเราสร้างหน้าเว็บด้วย PHP โค๊ดที่ทำการสร้าง tag html ตามตัวอย่าง

<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
</head>
<body>
<?php
echo "<h1> Hi, I'm a PHP script!</h1>";
?>
</body>
</html>

ซึ่ง เมื่อเราเปิดหน้าเว็บ tag html จะถูก Render มาเสร็จเรียบร้อยแล้วจึงทำให้ Browser สามารถมองเห็น content ครบตั้งแต่แรก Search Engine จะสามารถเก็บข้อมูลไปทำ index search ได้ง่ายจึงมีผลกับ SEO (Search Engine Optimization)

ซึ่ง JavaScript Node.js ก็สามารถทำ SSR ได้เช่นกัน

2. SPA (Single Page Application)

คือ เว็บที่ถูก Render หน้าจอในฝั่ง client side ด้วย JavaScript หน้าจอจะไม่มีการ Refresh

ตัวอย่างเว็บแบบ SPA ซึ่งถ้าดูผ่านหน้าเว็บจะมีหลายหน้าก็จริง แต่หาก view source code ดูใน tag body จะมีแค่ tag div กับ tag script ตัว content หน้าจอทั้งหมดจะถูก Render ผ่านทาง javaScript ที่เขียนไว้นั่นเอง ทำให้เว็บแบบนี้เรียกว่า Single Page Application

<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
<link rel="stylesheet" href="app.css">
</head>
<body>
<div id="app"></div>
<script src="app.js"></script>
</body>
</html>

สำหรับ Nuxt.js สามารถใช้ได้ทั้งสองโหมด คือ SSR และ SPA ซึ่ง Default จะเป็นโหมด Server Side Rendering (SSR)

ที่นี้ให้กลับไปที่ Browser แล้วไปเปิด Chrome Inspect (F12) ไปที่แท๊บ Network แล้วเข้าที่ Url > http://localhost:3000/vue-ability ตามภาพเพื่อดูรายละเอียดข้อมูลที่ Browser โหลดจากเว็บของเรา

กรอบสีแดงหมายเลข 1

vendor.js : เป็นไฟล์ที่รวม package หรือ library ที่เราไม่ได้เขียนเอง เช่นเราไป เอา vuetify มาใช้ โค๊ดของ vuetify ก็จะอยู่ใน vendor.js

app.js : เป็นไฟล์ของ Nuxt.js

กรอบสีแดงหมายเลข 2

เป็นไฟล์ชื่อเดียวกับหน้าที่เราสร้างขึ้นมา โดยใน template เริ่มต้นของ nuxt จะโหลดไฟล์ .js ของทุกหน้ามารอไว้ แล้วถ้าเรากดเปลี่ยนหน้าไปมาไฟล์ .js หน้านั้นก็จะถูกโหลดใหม่ทุกครั้ง (ซึ่งไม่ค่อยจะดีเท่าไหร)

การแก้ไขให้ไปที่ไฟล์ nuxt.config.js แล้วใส่โค๊ดลงไป เพื่อไม่ให้โหลดหน้าอื่นมารอในครั้งแรก กดเซฟและรอ Build ให้เสร็จก่อน

render: {
resourceHints: false,
},

จากนั้นกลับไปที่ Browser ไปที่หน้า http://localhost:3000/vue-ability กด F5 (Refresh) แล้วดูผลลัพธ์ จะพบว่าไม่มีการโหลดไฟล์ .js หน้าที่ยังไม่ได้เปิดมารอเหมือนตอนแรกแล้ว

ซึ่งถ้าเราคลิกเปลี่ยนหน้าไฟล์ .js ถึงจะถูกโหลดมา ถ้ากดย้อนกลับและกดมาที่หน้าเดิมก็จะไม่มีการโหลดซ้ำอีก

ต่อมา Nuxt.js ในโหมด SPA ต้องตั้งค่าเพิ่มที่ nuxt.config.js โดยใส่โค๊ด กดเซฟแล้วรอ Build

mode: 'spa',
router: {
mode: 'hash'
},

mode : ‘spa’ คือเปลี่ยนเว็บให้กลายเป็น Single Page Application

router : { mode : ‘hash’ } คือทำให้ url หลังกลายเป็น /#/ ตามภาพ

ที่นี้มาดูความแตกต่าง ของ 2 โหมด จาก View page source ดู

จะเห็นว่าในโหมด SSR ข้อความ Content ที่แสดงในหน้าเว็บก็จะปรากฏใน code html เช่นกัน

ส่วนโหมด SPA จะไม่มี content ใน code html เลยซึ่งพวก Content จะถูก Render มาจาก javascript นั้นเอง

โดยทั้งสองโหมดนั้นขึ้นอยู่กับการใช้งาน ก็เลือกตามที่ต้องการ

Nuxt.js Layouts

ตามปกติใน หน้าเพจแต่ล่ะหน้าของ Nuxt.js นั้น layout default จะอยู่ที่ไฟล์ layouts/default.vue ซึ่งจะทำให้ ไปปรากฏในทุกๆหน้า

แต่ถ้าหาก เราต้องการ layout แบบอื่นล่ะแบบที่ไม่ซ้ำกับ layout อันเดิมและต้องการใช้บางหน้าล่ะต้องทำอย่างไร

ตัวอย่าง ต้องการหน้า login ที่ใช้ layout ที่ไม่ซ้ำกับ layout default

ให้สร้าง authen.vue ในโฟลเดอร์ layouts แล้วใส่โค๊ดตัวอย่างลงไป

<template>
<div class="con-center">
<h1>Login</h1>
<nuxt/>
</div>
</template>
<style scoped>
.con-center {
text-align: center;
}
</style>

จากนั้นให้สร้างหน้าใหม่ชื่อ login.vue ใน โฟลเดอร์ pages ใส่โค๊ดตามภาพ

<template>
<div>
Login Form
</div>
</template>
<script>
export default {
layout: 'authen'
}
</script>

layout: ‘authen’ ก็คือชื่อไฟล์ authen.vue ที่เราสร้างไว้ในโฟลเดอร์ layout นั่นเองเป็นการบอกว่า ให้หน้านี้ไปเอา layout authen มาใช้นะ

จบ part 3 ครับ…

--

--