
前端路上的新長征
- 前言
從歷史的角度來說,盡管幾十年過去了,前端(即運行在瀏覽器里的程序)的基本結(jié)構(gòu)還是以HTML(CSS)+Javascript為主,變化不大,曾經(jīng)有一些腳本語言比如微軟的VBS試圖挑戰(zhàn)過這個架構(gòu),均以失敗告終(甚至連曇花一現(xiàn)都談不上)。后端(服務(wù)器)方面則是百花齊放,方案眾多,像是Java、PHP、GO、Python以及Javascript本身的一個分支Node.JS等等。
由于WEB技術(shù)的發(fā)展速度非??欤虼薍TML與Javascript也在高速迭代,于是產(chǎn)生了 “框架” 這個概念,所謂框架就是一堆前人已經(jīng)編寫好的成體系的代碼,其主要目的是不重復(fù)造輪子,加速開發(fā)效率。
前端框架大致上分為兩個大類,側(cè)重于HTML的CSS框架與側(cè)重于Javascript的JS框架。
主流的Javascript框架:React、Angular、Vue
主流的CSS框架:Bootstrap、Element、Vuetifylk
像React、Vue這一類框架關(guān)注點是Javascript本身,更多的是屬于處理邏輯層面的事務(wù)。而Bootstrap和Vuetify這一類CSS框架則著重關(guān)注HTML界面,頁面布局,排版等視覺方面的事情。
在沒有框架之前,所有前端開發(fā)者都采用原生HTML和原生Javascript,工作量極大。當(dāng)然,你如果問:我們一定需要框架嗎?答案卻是否定的,國外就確實有一股勢力是反對采用框架編程的,自詡為 "JS反框架聯(lián)盟",為了不引戰(zhàn),此話題咱們不做深入探討,見仁見智吧。
- PS: 本文以Vue + Vuetify為基礎(chǔ)。
Vuetify 篇:
- Vuetify 號稱是 Vue.js 的頭號組件庫,筆者使用過Bootstrap,因為年代久遠(yuǎn)已經(jīng)忘得差不多了,具體特點也不做評價。外賣雙雄之一的餓了嗎也搞了CSS庫,名字叫Element,感覺上手很容易,但限制比較多,UI的炫酷程度也比較一般。Vuetify 要比前兩者誕生的時間晚,但是它的可定制性很強,速度快,而且預(yù)設(shè)UI非常新潮,漂亮,值得嘗試!
由于Vuetify是專門提供給Vue使用的(從其名字也大概猜到了),所以在使用Vuetify之前我們還必須先安裝Vue。
-
裝Vue之前還得先裝Node.JS
Node.JS本質(zhì)上用于服務(wù)器后端,它將原本只能用在前端的Javascript變得可以運行在服務(wù)器后端,它對標(biāo)的是Java、PHP這一類東西。但此處安裝Node.js并不是要用到它的后端功能,主要是需要他的一個附屬工具:“npm” 包管理工具。
- 下載新版Node.js: https://nodejs.org/en/
- 下載完畢之后,安裝基本是無腦下一步即可。
-
回到Windows cmd命令行界面,開始準(zhǔn)備安裝vue-cli:
vue-cli是vue框架的“腳手架”,它的作用是快速為你搭建一個空的框架,然后立刻可以工作,省去了一大堆調(diào)試安裝的事情。當(dāng)然如果你不采用vue腳手架,用傳統(tǒng)的方式引用一個vue.js也是可以的。這樣做的優(yōu)點是更加簡潔高效,但是由于缺少npm包管理這個工具,調(diào)試和鏈接各種組件的難度將陡增,在此我還是建議從腳手架開始吧,等以后有閑了可以再去深入。
-
輸入以下命令:
npm install -g @vue/cli -
vue-cli安裝好之后,vue命令就能使用了,用它創(chuàng)建一個項目,名稱隨意(此處為mini):
vue create mini //創(chuàng)建mini項目 cd mini vue add vuetify //添加vuetify組件- 項目將會自動創(chuàng)建完成,并且自動生成以下目錄結(jié)構(gòu):

-
問題是,如何運行一個vue程序? 很簡單,在cmd命令行輸入以下命令:
npm run serve- 然后打開瀏覽器,輸入網(wǎng)址:http://localhost:8080 即可。
一個最基礎(chǔ)的APP界面如下:

如圖所示,這是一個最簡單的APP框架,包括
- 兩個狀態(tài)欄:v-app-bar(頂部)、v-footer(底部)
- 側(cè)邊功能導(dǎo)航欄:v-navigation-drawer
- 主視圖區(qū):v-content
最基礎(chǔ)的主頁代碼,UI由<template>部分組成,JS代碼包裹在<script>里:
<template>
<v-app id="inspire">
<v-navigation-drawer
v-model="drawer"
app
clipped>
<!-- vmodel: 顯示開關(guān),設(shè)為null的時候屏蔽導(dǎo)航欄
app : 是app = 'true'的簡化語法,表示這個導(dǎo)航欄屬于app的一部分
clipped: 等于clipped = 'true',表示導(dǎo)航欄采用壓縮布局
-->
<v-list dense>
<v-list-item link>
<v-list-item-action>
<v-icon>mdi-home</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>選項1</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item link>
<v-list-item-action>
<v-icon>mdi-email</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>選項2</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-navigation-drawer>
<v-app-bar
app
clipped-left
color="cyan"
dense
>
<v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
<v-toolbar-title>Application</v-toolbar-title>
</v-app-bar>
<v-main>
<v-container
class="fill-height"
fluid
>
<h1>Hello World!</h1>
</v-container>
</v-main>
<v-footer
color="cyan"
app
>
<v-spacer></v-spacer>
<span class="white--text">© {{ new Date().getFullYear() }}</span>
</v-footer>
</v-app>
</template>
<script>
export default {
name: 'SimpleDemo',
props: {
source: String,
},
data: () => ({
drawer: null,
}),
}
</script>
上面是最簡單的基礎(chǔ)用法,接下來我們稍微復(fù)雜一點:
- 用數(shù)組的方法為導(dǎo)航欄(v-navigation-drawer) 添加連接
- 結(jié)合vue-router動態(tài)渲染主視圖區(qū)
-
首先回到cmd命令行狀態(tài),輸入以下命令安裝vue-router:
npm install vue-router -
然后在main.js里添加:
import VueRouter from 'vue-router' Vue.use(VueRouter) //啟用vue-router插件 import router from './router' //引入我們自己的路由定義表 new Vue({ vuetify:vuetify, router:router, //這行也可以簡寫為: router, render: function (h) { return h(App) } }).$mount('#app') -
在與main.js平級的目錄中創(chuàng)建一個router.js文件:
import VueRouter from "vue-router"; import hello from './components/hello' const originalPush = VueRouter.prototype.push; VueRouter.prototype.push = function push(location) { return originalPush.call(this, location).catch(err => err) } //以上三行是為了解決相同路由報錯的問題,不用深究,照原樣放在此就行了 export default new VueRouter({ mode: 'history', routes: [ {path: '/', component: hello}, {path: '/msg/:msg', name: 'sayhi', component: hello}, ] }) /*以上代碼創(chuàng)建了兩個路由,“/” 根路由和“/msg” 大白話解釋根路由就是當(dāng)我們在瀏覽器地址欄什么參數(shù)都不帶,直接輸入網(wǎng)址比如qq.com,頁面應(yīng)該跳到哪, 第二個路由/msg,就是說當(dāng)我們在網(wǎng)址后面加一個/msg,比如qq.com/msg,頁面應(yīng)該跳到哪,所謂路由就是這個意思。*/ -
在 src/components 目錄中創(chuàng)建一個hello.vue文件:
<template> <h1>Hello {{ $route.params.msg}}</h1> <!-- 此處的$route.params.msg表示從路由/msg傳遞過來的參數(shù) --> </template> <script> export default { name: 'hello', data: () => ({ }), } /* 以上就是一個最簡單的vue組件,它由template和script兩部分組成,template部分表示HTML代碼, 很簡單,就是顯示一個H1級別的文字:Hello + 路由傳過來的參數(shù), JS部分其實并沒有任何實質(zhì)性內(nèi)容,是一個空框架。 */ </script> -
修改app.vue文件,清空舊的內(nèi)容,將以下內(nèi)容全部復(fù)制粘貼進(jìn)去:
<template> <v-app id="inspire"> <v-navigation-drawer v-model="drawer" app clipped> <v-list dense> <v-subheader class="mt-4 grey--text text--darken-1">操作選項</v-subheader> <!-- v-subheader 是組的標(biāo)題 --> <v-list-item v-for="item in items" :key="item.text" @click="test(item.path)" link> <!-- v-for 是 vue的標(biāo)準(zhǔn)語法,item in items的 items 是一個數(shù)組,:key 表示唯一值 --> <v-list-item-action> <v-icon>{{ item.icon }}</v-icon> </v-list-item-action> <v-list-item-content> <v-list-item-title> {{ item.text }} </v-list-item-title> </v-list-item-content> <!-- v-list-item-action 是選項圖標(biāo) v-list-item-content 是選項的內(nèi)容區(qū) v-list-item-title 是選項的文字 --> </v-list-item> <v-subheader class="mt-4 grey--text text--darken-1">用戶選項</v-subheader> <v-list> <v-list-item v-for="item in items2" :key="item.text" @click="test(item.path)" link> <v-list-item-avatar> <!-- https://randomuser.me 是一個隨機產(chǎn)生用戶頭像的趣味網(wǎng)站,此處從該網(wǎng)站獲取頭像圖片 --> <img :src="`https://randomuser.me/api/portraits/men/${item.picture}.jpg`" alt=""> </v-list-item-avatar> <v-list-item-title v-text="item.text"></v-list-item-title> </v-list-item> </v-list> <!-- 以下兩個選項并沒有用到數(shù)組,一般用于一些非動態(tài)的固定欄目 --> <v-list-item class="mt-4" link> <v-list-item-action> <v-icon color="grey darken-1">mdi-plus-circle-outline</v-icon> </v-list-item-action> <v-list-item-title class="grey--text text--darken-1">附加選項1</v-list-item-title> </v-list-item> <v-list-item link> <v-list-item-action> <v-icon color="grey darken-1">mdi-cog</v-icon> </v-list-item-action> <v-list-item-title class="grey--text text--darken-1">附加選項2</v-list-item-title> </v-list-item> </v-list> </v-navigation-drawer> <!-- v-app-bar 是頂部欄,一般放一些操作類的按鈕、搜索功能等 --> <v-app-bar app clipped-left color="cyan" dense> <v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon> <!-- 此處通過修改drawer變量來決定導(dǎo)航欄是否隱藏,PS:當(dāng)寬度被壓縮的時候?qū)Ш綑谧詣与[藏(比如手機) --> <v-toolbar-title>我的第一個APP</v-toolbar-title> </v-app-bar> <v-main> <!-- v-main是主試圖,一般指與用戶交互信息最頻繁的區(qū)域,尺寸也最大 --> <v-container class="fill-height" fluid> <router-view></router-view> <!-- router-view 是路由視圖,APP的所有點擊變化都在此反映,一般來說路由視圖約等于主視圖--> </v-container> </v-main> <v-footer color="cyan" app> <!-- v-footer是最底部的頁腳欄,一般用于放置版權(quán)信息之類雜項 --> <v-spacer></v-spacer> <span class="white--text">© {{ new Date().getFullYear() }}</span> </v-footer> </v-app> </template> <script> export default { name: 'sayhi', props: { source: String, }, data: () => ({ drawer: null, items: [ {icon: 'mdi-trending-up', text: '世界', path: 'Wolrd'}, {icon: 'mdi-youtube-subscription', text: '太陽', path: 'Sun'}, {icon: 'mdi-history', text: '月亮', path: 'Moon'}, {icon: 'mdi-playlist-play', text: '星星', path: 'Star'}, {icon: 'mdi-clock', text: '地球', path: 'Earth'}, ], items2: [ {picture: 28, text: 'Joseph',path:"約瑟夫"}, {picture: 38, text: 'Apple',path:"蘋果"}, {picture: 48, text: 'Xbox',path:"叉博克斯"}, {picture: 58, text: 'Nokia',path:"諾基亞"}, {picture: 78, text: 'MKBHD',path:"愛慕凱碧愛趣帝"}, ], }), methods: { test: function (path) { this.$router.push({name: "sayhi", params: {msg: path}}) } } } </script> 在命令行輸入: npm run serve
運行結(jié)果如下,點擊導(dǎo)航欄不同的菜單選項,觸發(fā)vue-router產(chǎn)生不同的參數(shù),主視圖也會跟著一起改變:

- 后記
本文純粹屬于拋磚引玉,對文中所涉及的概念并沒有進(jìn)行深入的探討,不過萬事開頭難,希望我這個簡單的框架能帶你快速進(jìn)入角色,開啟你的前端探秘之旅。下面提供幾個鏈接供大家做深入學(xué)習(xí)之用: -
https://vuetifyjs.com/zh-Hans/
(Vuetify官網(wǎng),文檔非常詳盡,而且有簡體中文版) -
http://www.itdecent.cn/p/4c5c99abb864
(一篇很不錯的vue-router教程) -
http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
(阮一峰老師的布局教程) - http://www.ruanyifeng.com/blog/2014/05/restful_api.html
-
http://www.ruanyifeng.com/blog/2011/09/restful.html
(阮一峰老師關(guān)于Restful風(fēng)格編程的兩篇指南,Restful是現(xiàn)在WEB編程的主選方案)