從零到部署:用 Vue 和 Express 實現迷你全棧電商應用(一)

Vue 是尤雨溪[1]在 2014 年建立的一個前端框架,目前 Github[2] Star 數高達 150K,是 Star 數最高的前端項目,而且 Vue 有着極爲活躍的社區生態以及專職團隊進行維護以確保項目能夠健康長久地發展。css

目前中國不少互聯網公司前端程序員的招聘要求都要求程序員掌握 Vue,像滴滴、美團、餓了麼等大廠也在重度使用 Vue 進行開發,而且有着像 Element[3] 、mpvue[4]iView[5] 這樣優秀的基於 Vue 開源項目存在,因此學習 Vue 是一個不錯的投資,當你學會 Vue,就能夠快速開發項目,這樣不只能夠接外包掙外快,並且當有了必定的項目經驗,還能夠在一線互聯網大廠找到一份不錯的工做。html

看到這裏你心動了嘛?心動不如行動!而最幸運的是,本教程將會一步一步帶你以實戰的方式實現一個迷你全棧電商網站。並在實戰的過程當中,瞭解 Vue 的全貌,如今就打開電腦,跟隨個人腳步,完全掌握 Vue 開發!本系列教程的規劃以下:前端

1.第一部分(也就是這篇教程):用 Vue 搭建前端項目的骨架,實現基於嵌套、動態路由的多頁面跳轉。2.第二部分(✍️寫做中):用 Express 實現後端 REST API,並使用 MongoDB 進行數據存儲。3.第三部分(✍寫做中):經過 Vue 的雙向數據綁定和模板語法實現數據添加,並用 Vuex 實現前端的狀態管理。4.第四部分(✍寫做中):用 Element UI 組件庫讓界面更加專業美觀,而且用 Docker 和 Docker Compose 部署咱們的全棧項目。vue

若是您以爲咱們的教程寫得還不錯,請記得給咱們點個 在看 哦!鼓勵咱們更快更好地寫完剩下的教程!你也能夠在公衆號後臺給咱們留言,告訴咱們想要實現什麼功能,咱們必定會仔細考慮的哦!node

快速入門

代碼

你能夠在 Github 查看本教程最終的源碼:源碼地址[6]webpack

項目準備

安裝依賴

安裝 Node.js,你能夠去 Node.js[7] 官網下載安裝包,經過安裝包安裝會同時安裝 Node.js 包管理工具 Npm,用於便捷的管理項目依賴和下載第三方包。git

打開終端,輸入以下命令測試是否安裝成功:程序員

node -v # v10.16.0npm -v # 6.9.0

若是在你的終端有如上輸出,那麼表明你安裝成功。github

提示web

經過上面安裝包安裝,你會安裝最新的 Node 穩定版本,這可能和個人機器上的 Node 版本不一致,可是不用擔憂,本教程使用到的代碼語法適用於絕大多數新的或更老的 Node。

安裝 vue-cli,在絕大多數場景下,咱們使用 vue-cli 來初始化咱們的 vue 項目,本教程也不例外,在終端運行以下命令來安裝:

npm install -g vue-cli

打開終端,輸入以下命令測試是否安裝成功:

vue --version # 2.9.6

提示

雖然 Vue 3.x 已經正式推出,可是這篇教程用的是主流、穩定的 Vue 2.x 版本。因爲 Vue 的總體思想基本沒有改變,因此不影響咱們的學習。在接下來的教程中,咱們會遷移到 Vue 3.x,並經過講解新老 Vue 版本的差別讓你更好地理解 Vue 的演變。

上面兩個安裝步驟已經足夠完成咱們的教程的學習,可是我想額外推薦你一款編輯器,VSCode,你能夠經過訪問 VSCode[8] 官網安裝。

在 VSCode 裏面找到 Vue 插件,能夠得到代碼語法高亮以及自動格式化[9]很是便捷的功能,而且 VSCode 自然對 JavaScript 的支持,會大大提升咱們的開發效率,本教程所涉及項目的開發都是使用 VSCode 完成的。

初始化項目

打開終端輸入以下命令初始化咱們的 Vue 項目:

vue init webpack vue-online-shop-frontend

命令行接着會顯示一些列選項讓你選擇,具體咱們的選擇以下圖:

提示

其中 Author 字段你能夠填本身的暱稱,而後咱們在選擇了安裝 vue-router 以後,其餘的都選擇了 no,由於本篇教程是面向初學者的實戰教程,若是引入了過多和 Vue 核心無關的概念,就會引發不少困惑,因此這裏咱們不配置它們

當項目初始化成功以後,接下來經過以下命令開啓項目:

# code vue-online-shop-frontend # 若是你使用了 VSCode 編輯器,能夠用這行命令打開項目cd vue-online-shop-frontend && npm start

接着打開瀏覽器,訪問 http://localhost:8080/ 查看咱們初始好的項目效果。

注意

若是你使用 VSCode 編輯器打開項目進行開發,在運行 code project-name 以前須要安裝 code 腳本,具體我找了一篇教程:戳我訪問[10]

初探腳手架代碼

經過 vue-cli 初始化的腳手架代碼中,咱們在整個教程中須要瞭解的就是如下五個文件:

src/main.jsindex.htmlsrc/App.vuesrc/router/index.jssrc/components/HelloWorld.vue

src/main.js

首先咱們來看一下 src/main.js,這個是 Vue 應用的入口。咱們經過導入 Vue 類、App 組件、router 路由,再加上 el ,將這些參數傳給 Vue 類,生成一個 Vue 實例。

// The Vue build version to load with the `import` command// (runtime-only or standalone) has been set in webpack.base.conf with an alias.import Vue from 'vue';import App from './App';import router from './router';
Vue.config.productionTip = false;
/* eslint-disable no-new */new Vue({ el: '#app', router, components: { App }, template: '<App/>',});

index.html

接着咱們來看一下 index.html 文件,它的代碼是這樣的:

<!DOCTYPE html><html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>vue-online-shop</title> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> </body></html>

當咱們開啓項目以後,Vue 所使用的構建工具 Webpack[11] 將會:

根據入口文件 src/main.js 裏面聲明的 el 屬性(#app),找到 index.html 中 id 爲app 的 DOM 節點把編譯好的視圖模板代碼掛載到這個 DOM 節點下面將項目涉及的 JavaScript 和 CSS 代碼以 script 和 link 的方式插入到 index.html 中開啓開發服務器,打開瀏覽器,進而瀏覽器將 index.html 渲染,咱們就能夠看到寫好的 Vue 頁面效果。

src/App.vue

src/App.vue 就是 Vue 爲咱們提供的組件文件,使得咱們能夠以組件的形式來組織代碼,並經過組件的組合來構建任意規模的項目,代碼以下:

<template> <div id="app"> <img src="./assets/logo.png"> <router-view/> </div></template>
<script>export default { name: 'App',};</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>

能夠看到, App 組件包含了三個部分的代碼:

templatescriptstyle

其實就是對應了傳統 Web "三劍客",HTMLJavaScriptCSS

這裏在 template 部分展現了一張 Vue 的 logo 圖片,而後顯示此刻渲染的路由組件:<router-view />。咱們將在後面繼續講解路由,這裏不懂也沒有關係哦。script 部分,主要是導出了一個名爲 App 的組件。style 部分就是咱們熟悉的 CSS 代碼了。

提示

上面所講的是比較小的組件的寫法,當組件中涉及的代碼較多時,咱們須要把 script 和 style 抽成獨立的 .js 和 .css 文件。就像下面這樣:

<!-- ./src/App.vue --><template> <div id="app"> <img src="./assets/hello.png"> </div></template><script src="./app.js"></script><style src="./app.css"></style>

Vue 組件和模板語法是 Vue 的核心概念,咱們在後面會以實戰的形式重點講解這些內容。

src/router/index.js

src/router/index.js 文件是 Vue 爲咱們提供的路由文件,代碼以下:

import Vue from 'vue';import Router from 'vue-router';import HelloWorld from '@/components/HelloWorld';
Vue.use(Router);
export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld, }, ],});

首先咱們導出了 Vue 類,以及 Router 類,以及咱們的 HelloWorld 組件。

接着咱們使用 Vue.use(Router) 告訴 Vue,咱們應用接入了路由。

在導出的路由實例中,咱們經過 routes 數組定義了項目全部的頁面,每一個頁面是一個相似 { path, name, component } 的對象。

好比初始化時生成的 HelloWorld.vue 就是咱們的網站首頁 -- 也就是打開瀏覽器訪問到的第一個頁面,由於它的路徑(path)定義爲 / 。此外一個頁面定義還須要 name,它表明此頁面在 vue-router 中的標識符,component 則表明此頁面渲染時的所用到的組件。

提示

這裏咱們能夠看到導出 HelloWorld 組件時,咱們在路徑最前面加上了 "@",那是由於咱們在 webpack 配置中將會 "@" 映射成 resolve('src'),也就是咱們項目目錄下 src 文件夾的路徑,最後咱們的 '@/components/HelloWorld' 的實際上的效果至關於取到了項目目錄 src 文件夾裏面的 components/HelloWorld 組件。

src/components/HelloWorld.vue

最後是 src/components/HelloWorld.vue 文件,是腳手架代碼爲咱們提供的一個實例組件,代碼以下:

<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>Essential Links</h2> <!-- 省略其餘模板代碼 ... --> </div></template>
<script>export default { name: 'HelloWorld', data() { return { msg: 'Welcome to Your Vue.js App', }; },};</script>
<!-- Add "scoped" attribute to limit CSS to this component only --><style scoped>h1, h2 { font-weight: normal;}ul { list-style-type: none; padding: 0;}li { display: inline-block; margin: 0 10px;}a { color: #42b983;}</style>

能夠看到,其結構大體與 App.vue 相似。其中也有一些不一樣,好比 script 裏面的 data 字段,還有 template 中的 {{ }} 語法。這個咱們會在下一節進行講解。

當咱們打開瀏覽器時,地址爲:http://localhost:8080/ 此時路徑爲 /,激活 HelloWorld.vue 組件,因此最後咱們整個項目渲染 App.vue 的內容,顯示的結構即爲:

一張 Vue logo 圖咱們的 HelloWorld.vue 組件的內容

小結

經過一窺 vue-cli 爲咱們初始化的項目代碼,咱們能夠學到以下的知識:

Vue 經過組件來組織項目,單個組件就是咱們傳統的 Web "三劍客":HTML、JavaScript、CSS。Vue 經過路由來定義多個頁面,而且進行頁面之間的跳轉。一個頁面是一個組件,一個組件能夠由不少組件組成,經過這種組合式的思想,咱們能夠編寫任意複雜的項目。

編寫你的第一個 Vue 頁面

下面咱們來編寫電商應用的首頁。

編寫頁面組件

在 src/components 下面建立 Home.vue 文件,而後編寫以下代碼:

<template> <div> <div class="title"> <h1>{{msg}}</h1> </div> </div></template>
<script> export default { name: 'home', data () { return { msg: 'Welcome to Your Vue.js App' }; }, }</script>

在上面,咱們建立了一個名爲 Home.vue 的 Vue 組件,能夠看到它和咱們以前的 HelloWorld.vue 的內容大體相仿,可是也有一些不一樣的地方:

首先,咱們暫時沒有寫樣式(沒有 style 部分),而是先專一於基礎知識的講解。在後續教程中,咱們會使用 Element UI[12] 組件庫讓咱們的界面變得專業美觀。其次,咱們在 script 中引入了 data ,在 template 引入了插值語法 {{var}}。其中 data 是聲明此組件的初始化數據,而 {{var}} 插值語法是方便將數據渲染到視圖模板中;這裏咱們將在 script 中定義的 data 中的 msg 插值到視圖模板中,最終會渲染一個 h1 標籤,標籤內容就爲 msg 的內容。

接入路由

接着,咱們在 src/router/index.js 路由中將主頁路由 / 所綁定的組件從默認的 HelloWorld 修改成剛纔寫好的 Home 組件:

import Vue from 'vue';import Router from 'vue-router';import Home from '@/components/Home';
Vue.use(Router);
export default new Router({ routes: [ { path: '/', name: 'Home', component: Home, }, ],});

如今咱們保存代碼,打開瀏覽器,就會顯示剛纔在 Home.vue 裏面填寫的那個標題:

使用路由進行多頁面跳轉

一個經典的電商應用一般包括以下部分:

商品展現列表 (Home.vue商品詳情(Detail.vue購物車(Cart.vue

這裏由於咱們追求簡單,也將商品的後臺管理頁面 (Admin.vue)放入了項目中。

如今咱們先來實現商品展現列表、購物車和後臺管理頁面的模板內容。由於商品詳情頁後面將會使用組件進行復用,因此這裏咱們暫時先不建立。

添加首頁導航

首先修改 App.vue ,加入三個導航連接 router-link,方便讓用戶跳轉到到本身想看的頁面,代碼以下:

<template> <div id="app"> <nav> <div class="container"> <ul class="nav__left"> <li> <router-link to="/">Home</router-link> </li> <li> <router-link to="/admin">Admin</router-link> </li> <li> <router-link to="/cart">Cart</router-link> </li> </ul> </div> </nav>
<router-view/> </div></template>
<script>export default { name: 'App',};</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>

這裏咱們在頭部添加了三個 router-link 表明咱們的頭部導航。

router-link 和 a 標籤相似,只不過 Vue 爲它添加一些額外的優化邏輯。

建立後臺管理頁面

接着咱們編寫 Admin.vue 組件,但這裏稍微有點不一樣,即咱們在 src/pages 下建立 Admin.vue 組件,由於對於頁面級組件,咱們傾向於將其放到一個特殊 pages 文件夾,這樣方便組織項目。其代碼以下:

<template> <div> <div class="title"> <h1>{{msg}}</h1> </div> </div></template>
<script> export default { name: 'home', data () { return { msg: 'Welcome to the Admin Page' } } }</script>

能夠看到這個頁面內容和咱們以前的 Home.vue 內容類似。

建立購物車頁面

而後是咱們的購物車頁面 Cart.vue,代碼以下:

<template> <div> <div class="title"> <h1>{{msg}}</h1> </div> </div></template>
<script> export default { name: 'home', data () { return { msg: 'Welcome to the Cart Page' } } }</script>

能夠看到這個頁面內容和咱們以前的 Home.vue 內容類似。

將新頁面導入路由

最後,咱們把上一步中建立的 Home.vue 移到 src/pages 目錄中,並在路由文件 src/routes/index.js 中導入這三個頁面,代碼以下:

import Vue from 'vue';import Router from 'vue-router';import Home from '@/pages/Home';import Admin from '@/pages/Admin';import Cart from '@/pages/Cart';
Vue.use(Router);
export default new Router({ routes: [ { path: '/', name: 'Home', component: Home, }, { path: '/admin', name: 'Admin', component: Admin, }, { path: '/cart', name: 'Cart', component: Cart, }, ],});

保存代碼,而後打開瀏覽器,咱們能夠看到下面的效果:

你能夠點擊頭部的三個導航連接,下面的標題內容會隨着點擊的連接變化。恭喜你,你已經成功地實現了一個基於 Vue 的多頁面網站了!

使用嵌套路由和動態路由合理組織頁面

隨着頁面的增多,若是咱們把全部的頁面都塞到一個 routes 數組裏面會顯得很亂,你沒法肯定哪些頁面存在關係。還好 vue-router 提供了嵌套路由的功能,讓咱們能把相關聯的頁面組織在一塊兒。

升級路由

在咱們的商城項目中,後臺管理頁 Admin 涉及到不少操做頁面,好比:

/create 建立新的商品/edit 編輯商品信息

讓咱們經過嵌套路由的方式將它們組織在一塊兒。首先在路由文件 src/router/index.js 中聲明後臺管理全部用到的頁面組件(咱們立刻就會去實現它們):

import Vue from 'vue';import Router from 'vue-router';
import Home from '@/pages/Home';import Cart from '@/pages/Cart';
// Admin Componentsimport Index from '@/pages/admin/Index';import New from '@/pages/admin/New';import Products from '@/pages/admin/Products';import Edit from '@/pages/admin/Edit';
Vue.use(Router);
export default new Router({ routes: [ { path: '/', name: 'Home', component: Home, }, { path: '/admin', name: 'Admin', component: Index, children: [ { path: 'new', name: 'New', component: New, }, { path: '', name: 'Products', component: Products, }, { path: 'edit/:id', name: 'Edit', component: Edit, }, ] }, { path: '/cart', name: 'Cart', component: Cart, }, ],});

嵌套路由的用法就是給須要歸爲一類的頁面設置一個入口頁面,而後把這一類頁面都放到這個路由頁面路由定義的 children 字段數組中。

經過上面的代碼咱們能夠看到,Admin 類別下有四個組件,Index 是咱們 Admin 類別的入口組件,也是做爲 path = /admin 的渲染組件,而後其餘組件就放到 path = /admin 這個路由定義的 children 數組裏,其定義和其餘父級一致。

這樣的嵌套寫法帶來了兩個好處:

很清晰的組織了一類頁面,方便閱讀。在定義路由的 path 的時候,複用了父級的 path,即如今咱們的 New 這個路由,它在瀏覽器中訪問的路徑爲:'/admin' + 'new',若是咱們統一放到 routes 數組的第一級定義,那麼後面的 Products 和 Edit 的 path 都要帶上諸如 /admin 和 /admin/edit/:id 這樣長長的路徑,顯得特別複雜。

這裏還有一個改變就是,咱們發現 Edit 這個路由的 path 有點不太同樣,它有個特殊的標誌 edit/:id,這種寫法被稱爲動態路由,即 :id 會匹配任意字符串,因此用戶訪問 /admin/edit/<any-string> 都會激活 Edit 路由,從而渲染 Edit.vue 組件。

建立 Admin 的子頁面

首先建立 Index.vue 入口組件,代碼以下:

<template> <div> <div class="admin-new"> <div class="container"> <div class="col-lg-3 col-md-3 col-sm-12 col-xs-12"> <ul class="admin-menu"> <li> <router-link to="/admin">View Products</router-link> </li> <li> <router-link to="/admin/new">New Products</router-link> </li> </ul> </div> <router-view></router-view> </div> </div> </div></template>

能夠看到,它做爲嵌套路由的入口級組件,和咱們以前在 App.vue 裏面看到的樣子相似,在其中會有 router-link 導向更深層級的路由.

router-view 用於渲染子路由組件,好比咱們此時訪問 /admin/new 頁面,那麼 router-view 部分會被替換成 New.vue 組件的內容,由於咱們在以前的嵌套路由定義中 path 爲 new 的渲染組件爲 New.vue

建立 src/pages/admin/Edit.vue 組件,代碼以下:

<template> <div> <div class="title"> <h1>This is Admin/Edit/{{$route.params.id}}</h1> </div> </div></template>

能夠看到,當用戶訪問 /admin/edit/:id,會激活渲染 Edit.vue 組件,咱們能夠經過 $route.params.id 的方式獲取用戶輸入的路徑 :id 部分。好比咱們在瀏覽器中輸入 /admin/edit/52tuture,那麼瀏覽器將會以 h1 的形式打出 "This is Admin/Edit/52tuture"

提示

$route 這個變量是 Vue 在運行時爲咱們自動插入到全部組件屬性中的,全部咱們不用手動去管理它。

建立 src/pages/admin/New.vue,代碼以下:

<template> <div> <div class="title"> <h1>This is Admin/New</h1> </div> </div></template>

建立 src/pages/admin/Products.vue ,代碼以下:

<template> <div> <div class="title"> <h1>This is Admin</h1> </div> </div></template>

保存咱們編寫的內容,打開瀏覽器,咱們能夠看到以下內容:

至此,咱們的迷你全棧電商應用的第一部分就完成了,在接下來的教程中,咱們將用 Express 和 MongoDB 搭建這個電商應用的後端 API,不見不散哦~

想要學習更多精彩的實戰技術教程?來圖雀社區[13]逛逛吧。

References

[1] 尤雨溪: https://evanyou.me/
[2] Github: https://github.com/vuejs/vue
[3] Element: https://element.eleme.cn/#/zh-CN
[4] mpvue: http://mpvue.com/
[5] iView: http://iview.talkingdata.com/#/
[6] 源碼地址: https://github.com/pftom/vue-online-shop-frontend/tree/aca2bb64cbdaebb7e4a62e252bc00a439eede9a5
[7] Node.js: https://nodejs.org/en/
[8] VSCode: https://code.visualstudio.com/
[9] 代碼語法高亮以及自動格式化: https://marketplace.visualstudio.com/items?itemName=octref.vetur
[10] 戳我訪問: https://www.cnblogs.com/Zhangcsc/p/11362987.html
[11] Webpack: https://webpack.docschina.org/
[12] Element UI: https://element.eleme.cn/
[13] 圖雀社區: https://tuture.co?utm_source=juejin_zhuanlan

本文分享自微信公衆號 - 大前端技術沙龍(is_coder)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索