一探全棧專案真面目

彭芃芃發表於2020-03-01

一探全棧專案真面目


一.前言


文章主要以巨集觀的形式來聊一個全棧開發專案,非常適合初級階段學習前端的小白,適當的全棧開發是前端學習在初級階段所必須要有的技能。大多數人都知道的是,一個全棧開發專案是大多是由:電商系統+社交系統+部落格系統 構成。但我們不知道的是其中的種種原理和方法。而我今天要講解的專案就是以部落格的形式為例子,幫助大家解開疑惑。

說在前面

還未安裝vue?這裡有vue的安裝教程,很詳細噢!當然如果你vue基礎不是很好的話,這裡也有幫助你提升vue專案的視訊。技術胖vue視訊教程

這是一篇基於vue & mongodb 為主的專案,如果還未安裝mongodb,可以參考mongodb安裝教程,操作簡單,容易上手,想要弄懂全棧專案用vue如何構建全棧專案?就快快花幾分鐘時間瀏覽這篇文章吧!


二. 問題提出:部落格(blog)


  • 思路
  1. 在整棧專案中,我們需要建立前端(web)和後端(server)分離的框架。除此之外,還需要有在後臺(admin)開發的思想。或許很多人被我這麼一說繞暈了,那麼我就和你說說它們之間的區別。

前端後端後臺的區別 後臺:提供給系統管理者能夠看到的頁面,而遊客、使用者看不到的頁面;前端:程式設計師在進行程式設計的時候的程式碼;後端:對應前端而言的,編寫程式碼基本上是提供給前端呼叫,是不需要處理UI的內容.比如:邏輯層。

  1. 前端我們需要進行的頁面操作,後端資料庫的連線,後臺的管理到底如何去執行?

前端(web)我們需要使用vue建立一個新的前端專案,相對來說:vue使用者體驗好,並且相對react來說更容易上手,且vue為單頁應用。而後端(server)主要用於對部落格文章的增刪改查,提供api。後臺(admin)則是幫助管理員處理事物,本文章暫不涉及後臺的內容。因此我們全棧開發的大致思路就搭建好啦!


三.具體講解

  • 專案的建立過程:在vue目錄下新建blog資料夾,在blog資料夾下新建server資料夾和admin資料夾。

後端server

1.首先我們要將server檔案進行初始化 npm init -y.之後,我們需要在server資料夾上新建資料夾db,在db資料夾中新建檔案db.js,建立該檔案的目的是連線本地的資料庫。localhost:27017是mongodb預設的地址,這是一個常考點。連線本地資料庫之後,在mongodb中可以使用use myblog切換進blog系統。程式碼如下:

// 資料庫層的分離 向外提供
module.exports = app => {
   // mongodb 的驅動
   const mongoose = require('mongoose');
   mongoose.connect('mongodb://localhost:27017/myblog', {
     useNewUrlParser: true // 屬性設定為true來避免"不建議使用當前URL字串解析器"警告,相容moogoose的新的URL連線的機制。
   })
 }
複製程式碼

2. 接下來,我們要做的事情就是建立資料庫的連線。我們在server資料夾下新建index.js檔案。程式碼裡有引入express腳手架,我們可以通過yarn add express來新增express腳手架。如果對express有疑問的大佬們,這裡也有關於express腳手架的講解。程式碼如下:

const express = require('express');
const app = express();
// 將db.js 引入
// import  es6 模組化   es5 require
// require('./db/db')(app); //資料庫的連線

複製程式碼

使用node index.js執行專案,沒有報錯則代表資料庫連線成功。

3. 現在我們就要開始建表,將表設計都分成獨立的模組來建立。可以去想想要做blog,我們需要建哪幾張表呢?首先我們必須要建的表是文章表:Article.js。在mongodb中,我們建的表都叫做collection(集合)。程式碼如下:

// 建表  collection  
// 1. Schema  表設計
// 2. 模型物件 返回 
const mongoose = require('mongoose')

const schema = new mongoose.Schema({
  uid: {
    type: mongoose.SchemaTypes.ObjectId,
    ref: 'User'
  },
  title: { type: String },
  isTop: { type: Boolean}, //是否置頂
  summary: { type: String }, // 列表裡的介紹
  body: { type: String },
  categories:[{ type: mongoose.SchemaTypes.ObjectId, ref:'Category'}]
}) // ref:category 外來鍵關係,一個文章可以有多個類別。

//類 表  articles
module.exports = mongoose.model('Article', schema, 'articles'); 

複製程式碼

在文章表中值得一提的是裡面有一個新增mongoose,Mongoose是MongoDB的一個物件模型工具,是基於node-mongodb-native開發的MongoDB nodejs驅動,可以在非同步的環境下執行。同時它也是針對MongoDB操作的一個物件模型庫,封裝了MongoDB對文件的的一些增刪改查等常用方法,讓NodeJS操作Mongodb資料庫變得更加靈活簡單。我們依舊可以通過yarn add mongoose來新增mongoose。

4. 使用者表User.js程式碼如下:

 // blog 分類的Schema
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const schema = mongoose.Schema({
  username: {
    type: String
  },
  password: {
    type: String,
    // 獲取使用者資料的時候, 不要把密碼取出去
    select: false, // select 查詢
    set(val) { 
      return bcrypt.hashSync(val, 10) // 不會存明文密碼
    }
  },
  // 使用者和文章的關係 ? 
})
// model -> mongodb 儲存到底做了什麼事情? mongoose
module.exports = mongoose.model('User', schema, 'users')

複製程式碼

在這裡有一個bcrypt加密解密演算法,需要通過yarn add bcrypt新增方法,代表對使用者輸入的密碼進行加密解密。

5. 文章分類表Category.js。

// blog 分類的Schema
const mongoose = require('mongoose');

const schema = mongoose.Schema({
  title: { type: String }
})
// model -> mongodb 儲存到底做了什麼事情? mongoose
module.exports = mongoose.model('Category', schema, 'categories')

複製程式碼

接下來就是前端部分的講解。

  1. 首先我們要掌握vue-router的兩種模式的區別: 眾所周知,vue-router有兩種模式,hash模式和history模式,這裡來談談兩者的區別。
  • hash模式: hash模式背後的原理是onhashchange事件,可以在window物件上監聽這個事件: 上面的程式碼可以通過改變hash來改變頁面字型顏色,雖然沒什麼用,但是一定程度上說明了原理。更關鍵的一點是,因為hash發生變化的url都會被瀏覽器記錄下來,從而你會發現瀏覽器的前進後退都可以用了,同時點選後退時,頁面字型顏色也會發生變化。這樣一來,儘管瀏覽器沒有請求伺服器,但是頁面狀態和url一一關聯起來,後來人們給它起了一個霸氣的名字叫前端路由,成為了單頁應用標配。
  • history路由: 隨著history api的到來,前端路由開始進化了,前面的hashchange,你只能改變#後面的url片段,而history、api則給了前端完全的自由,history,api可以分為兩大部分,切換和修改切換歷史狀態包括back,forward,go三個方法,對應瀏覽器的前進,後退,跳轉操作,有同學說了,(谷歌)瀏覽器只有前進和後退,沒有跳轉,嗯,在前進後退上長按滑鼠,會出來所有當前視窗的歷史記錄,從而可以跳轉(也許叫跳更合適):
history.go(-2);//後退兩次
 
history.go(2);//前進兩次
 
history.back(); //後退
 
hsitory.forward(); //前進
複製程式碼

修改歷史狀態 包括了pushState,replaceState兩個方法,這兩個方法接收三個引數:stateObj,title,url

history.pushState({color:'red'}, 'red', 'red'})
 
window.onpopstate = function(event){
    console.log(event.state)
    if(event.state && event.state.color === 'red'){
        document.body.style.color = 'red';
    }
}
history.back();
history.forward();
複製程式碼

通過pushstate把頁面的狀態儲存在state物件中,當頁面的url再變回這個url時,可以通過event.state取到這個state物件,從而可以對頁面狀態進行還原,這裡的頁面狀態就是頁面字型顏色,其實滾動條的位置,閱讀進度,元件的開關的這些頁面狀態都可以儲存到state的裡面。

history模式怕啥: 通過history api,我們丟掉了醜陋的#,但是它也有個毛病: 不怕前進,不怕後退,就怕重新整理,f5,(如果後端沒有準備的話),因為重新整理是實實在在地去請求伺服器的,不玩虛的。

  1. 在Vue中,我們需要在router資料夾下的index.js新增路由,目的就是為了引入建立的vue專案。程式碼如下:
// 引入vue專案 新增專案的路徑
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Main from '../views/Main.vue'
import Article from '../views/Article.vue'
import Tag from '../views/Tag.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  },
  //列表頁
  {
    path: '/main',
    name: 'main',
    component: Main
  },
  // 文章
  {
    path: '/article/:id',
    name: 'article',
    component: Article
  },
  //每個分類下有多少文章
  {
    path: '/tag',
    name: 'tag',
    component: Tag
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

複製程式碼

建立文章頁面的時候,它的路徑是這樣的:path: '/article/:id',裡面的id代表動態路由,根據id的不同檢視不同的文章。

  1. 既然我們引入了vue頁面,就必須去建立相應的檔案。因此,我views目錄下新建main.vue,article.vue,tag.vue檔案。
  • 檔案的專案目錄
    一探全棧專案真面目
  1. 最後,我們在components目錄下新建元件檔案:如頭部元件,腳部元件,載入元件,評論元件以及文章專案元件,而這些都是blog會複用的元件。

一探全棧專案真面目

執行結果

  • localhost:8081埠
    一探全棧專案真面目
  • localhost:3001埠
    一探全棧專案真面目

文章看到現在,相信讀者朋友們是知道了router + views + components功能分別是什麼啦!

打包上線

  1. 使用npm run build命令,將web檔案打包成dist,打包後將檔案放至server目錄下,之後將檔名改成web。進行專案上線,在後端進行上線。
  2. 回到後端server目錄下,新增程式碼:
app.use('/', express.static(__dirname + '/web'))

app.listen('3001', async(req, res) => {
  console.log('http://localhost:3001');
})
複製程式碼

在此處,express,static是express提供的靜態資源,之後在將打包中的內容展示出來,後端就等著你把vue打包好的靜態資源給你一個包,後端把包放進伺服器中,啟動根路由,交給web目錄,之後網路端訪問即可。

總結專案執行順序

  • vue 寫完後,npm run build 生成一包靜態檔案。
  • 靜態檔案包放到伺服器目錄下。
  • 在把vue釋出出去。
  • 最後在3001埠驅動(上線)

結束

文章看到現在也結束啦,第一次寫文章,如果有錯誤的話就麻煩大家給我指出來吧!如果覺得不錯的話別忘了點個贊?再走噢!

最後附上Github地址

  • 原始碼地址:blog

相關文章