全棧體驗——搭建屬於本身的我的網站

前言

最近終於把我的網站正式上線了,先放成果!
www.ssevenk.comcss

這是個人我的博客,主要記錄本身的前端學習心得
項目先後端都是一我的本身運做起來的
腳手架:Vuecli
服務端:node的express
數據庫:mongodb
第三方插件:element-ui,simpleMDE等等html

本文會從構思,開發,上線,備案全流程記錄一下網站的搭建過程
超長文預警!!!前端

基本架構

整個項目實際上是一個單頁面應用,全部的頁面跳轉都是前端控制的 後端只是提供數據接口,來對數據庫進行增刪查改vue

而從功能上來講,主要分紅了四個板塊

  • 文章:個人原創文章
  • 雜談:與技術不太相關的我的雜談
  • 收藏:別人的優秀文章,作成收藏夾的形式,點擊直接跳轉至對應網站連接
  • 留言板:供瀏覽者留言

所以,這裏也就有四種數據表須要設計node

後端

Mongodb-數據定義與存放

我用的數據庫是mongodb
比較靈活,並且與node配合使用起來更爲簡潔,能夠直接用js操做
如上文所說,咱們須要四種數據表結構,因而能夠直接用js創建linux

新建一個curd.js文件
引入mongoose(第三方的API庫)並鏈接數據庫(第一次鏈接並無這個數據庫,會幫咱們自動建立)webpack

//curd.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/gblog')
複製代碼

在其中定義數據結構,好比定義一個文章的表結構git

const MonBlog = mongoose.model('monblog', {
    title: {
        type: String,
        required: true //表示這個屬性是必需的
    },
    content: {
        type: String,
        required: true
    },
    date: {
        type: String,
        required: true
    },
    zan: {
        type: Number,
        required: true
    },
    comments:[]
})
複製代碼

其餘三種表同理進行設計,而後將這四種數據模型導出給router.js,讓其進行增刪查改的數據接口設計github

//curd.js
module.exports = {
    MonBlog: MonBlog,
    MonEssay: MonEssay,
    MonArticle: MonArticle
    MonMessage: MonMessage
}
複製代碼

增刪查改

新建一個router.js引入curd.js導出的三種數據模型web

const express = require('express')
const curd = require('./curd')
var router = express.Router()

const MonBlog = curd.MonBlog
const MonEssay = curd.MonEssay
const MonArticle = curd.MonArticle
const MonMessage = curd.MonMessage
複製代碼

而後就能夠運用mongoose提供的API來進行增刪查改 好比咱們經過前端post的信息,來新增數據,能夠設計這麼一個接口

router.post('/data/createBlog', (req, res) => {
    new MonBlog(req.body).save((err) => {
        if (err) res.send(err)
    })
})
複製代碼

查詢接口

router.get('/data/blog', function (req, res) {
    MonBlog.find((err, data) => {
        if (err) {
            res.send(err)
            return
        }
        res.send(data)
    })
})
複製代碼

刪除接口

router.post('/data/deleteBlog',(req, res) => {
        MonEssay.findByIdAndDelete(req.params.id, function (err, data) {
            if (err) res.send(err)
        })
    }))
複製代碼

增刪查改的守護——token

很顯然,相似增刪改的接口,是不能讓遊客或者惡意攻擊者去調用的
爲了讓後端能認識我,知道是管理員在調用
咱們就要用到token
在前端設計一個登陸頁,我經過密碼登錄後,把後端發給個人token存進localStorage中,在調用一些高風險級別的接口時帶上這個token

這裏咱們先安裝兩個插件,express-jwt和jsonwebtoken
新建jwtAuth.js文件

const expressJwt = require("express-jwt");
const secretOrPrivateKey = "woshisiyao" 
const jwtAuth = expressJwt({
secret: secretOrPrivateKey
}).unless({
path: ['/data/blog',
    '/data/essay',
    '/data/article',
    '/data/message',
    /^\/data\/blog\/.*/,
    /^\/data\/essay\/.*/,
    /^\/data\/article\/.*/,
    '/data/password'
   ] });

module.exports = jwtAuth;
複製代碼

上面的secretOrPrivateKey自定義了一個私鑰,這是安全性的保障
用它來給咱們的token加上尾部簽名

最後一步簽名的過程,其實是對頭部以及載荷內容進行簽名。通常而言,加密算法對於不一樣的輸入產生的輸出老是不同的。
因此,若是有人對頭部以及載荷的內容解碼以後進行修改,再進行編碼的話,若是不知道服務器加密的時候用的密鑰的話,得出來的簽名也必定會是不同的。
若是服務器應用對頭部和載荷再次以一樣方法簽名以後發現,本身計算出來的簽名和接受到的簽名不同,那麼就說明這個Token的內容被別人動過的,就會拒絕這個Token,返回一個HTTP 401 Unauthorized響應。

在項目中,並非全部的接口都是須要被保護的,好比獲取數據的接口,以及特定文章內容的接口都是須要向遊客開放的
上面的unless就是用來告訴後端,哪些接口不用token驗證
其中,/data/blog/:id,這種形式的url是不行的,須要用正則表達式來寫 /^\/data\/blog\/.*/

而後在router.js中,引入jwtAuth文件和jsonwebtoken插件
設計密碼登錄的接口

router.post('/data/password', (req, res) => {
if (req.body.password == '123456') {
    res.json({
        result: 'succeed',
        token: jwt.sign({
            name: "ssevenk"
        }, secretOrPrivateKey, {
                expiresIn: 60 * 60 * 24
            })
    })
}
else {
    res.send('驗證失敗')
}
})
複製代碼

若是密碼正確,就向前端發送token,其中expiresln能夠設置token的時效

前端收到token,存進localStorage中,好比

localstorage.setItem('token',token)

而後在發送請求的時候,須要寫在headers中

headers: {
      Authorization: `Bearer ${localStorage.getItem("token")}`,
    }
複製代碼

若是沒有成功,後端會報401 Unauthorized的錯誤

相關知識能夠參考這幾篇文章
juejin.im/post/5ac6fc…
blog.leapoahead.com/2015/09/06/…
www.ruanyifeng.com/blog/2018/0…

後端結構

最終的後端結構,就分爲四個文件

其中入口文件是app.js,用它來引入其餘文件,並安裝中間件

//app.js
const express=require('express')
const bodyParser=require('body-parser')

const router=require('./router')
const app=express()

app.use(bodyParser.urlencoded({extended:false}))

app.use(bodyParser.json())

app.use('/',router)
	
//劃分一個端口給後端,這裏監聽7000端口
app.listen(7000)
複製代碼

在命令行敲上node app.js,就成功啓動了咱們的後端

開發過程的跨域

能夠注意到,雖然開發過程,先後端都在我本身的電腦上
但後端監聽的是7000端口,而前臺頁面在8080端口訪問
因此爲了實現跨域請求 咱們須要對config文件夾中的index.js文件進行一些修改

proxyTable: {
  '/data': {
    target: 'http://localhost:7000',
    changeORIGIN: true
  }
},
複製代碼

給proxyTable添加一種跨域訪問規則,書寫api的時候也都以/data開頭 這樣全部的請求均可以跨域訪問到在7000端口的後端了

至此咱們便完成了項目中的這一塊部分

前端

後臺管理系統

後端已經配置好了,但如今數據庫裏沒有數據啊
因而須要有一個後臺管理系統,來可視化管理數據

界面中的那個表格基本就是element-ui的官方示例
參考官網作法,很快就能擼一個出來
element.eleme.cn/#/zh-CN/com…

惟一須要額外提兩句的,一個是右上角那個搜索
輸入後能夠即時顯示搜索的結果在數據表格裏
直接在el-table表格綁定的數據上進行操做

:data="((things.filter(data=>!search||data.title.toLowerCase().includes(search.toLowerCase())「
複製代碼

另一個是分頁,el-pagination

<el-pagination
        @current-change="handleCurrentChange"
        :page-size="pageSize"
        :current-page="currentPage"
        :total=" things.length"
        layout="total, prev, pager, next"
      ></el-pagination>
複製代碼

當點擊頁碼切換的時候,把頁碼更新

handleCurrentChange(currentPage) {
  this.currentPage = currentPage;
}
複製代碼

而後再一次對咱們以前的el-table標籤上的數據進行改進

:data="((things.filter(data=>!search||data.title.toLowerCase().includes(search.toLowerCase())).slice((currentPage-1)*pageSize,currentPage*pageSize)))"
複製代碼

這裏的邏輯前後要理清,是先對數據進行搜索的過濾再分頁

路由守衛

這裏大家應該也注意到了,管理的入口是出如今頁面上的tab選項卡里的
因此其實後臺管理也是單頁面應用的一部分,只是這個入口沒有對大家開放
爲了不遊客在地址欄直接輸入路由闖入管理系統,咱們要給須要保護的路由添加守衛

{
  path: '/Back',
  name: 'Back',
  component: () => import('../components/back.vue'),
  beforeEnter: (to, from, next) => {
      next({ path: '/Login' })
  }}
複製代碼

使用beforeEnter,把須要守衛的路由引入到登錄頁去
在登錄頁,輸入管理員密碼提交給後臺
前臺把後臺返回的token存進localStorage中,好比就叫作‘token’
那麼若是在路由的時候,從localStorage中能取到這個符號,那麼守衛就容許進行下一步跳轉
因此上面的守衛改爲

{
  path: '/Back',
  name: 'Back',
  component: () => import('../components/back.vue'),
  beforeEnter: (to, from, next) => {
		if(localStorage.getItem('token') { next() }
		else {
      next({ path: '/Login' })}
  }}
複製代碼

這種方式是須要給每一個要守衛的路由都添加一遍beforeEnter
還有一種方法是進行全局守衛

router.beforeEnter: (to, from, next) => {
		if(to.meta&&!localStorage.getItem('token') { next({ path: '/Login' })} }
		else {
      next()
  }}
複製代碼

添加全局守衛後,給要守衛的路由添加一個meta屬性,值爲true就能夠了

markdown編輯器

管理系統最重要的功能就是寫文章和修改文章內容

我用的是simpleMDE來實現markdown編輯器
並添加了原本沒有的本地上傳圖片功能
能夠參見個人另外一篇文章
juejin.im/post/5d09d0…

前臺路由

來到了咱們的前端展現頁

頭部的header是不變的,因此直接封裝了個組件放在了App.vue中

<myHeader></myHeader>
 <router-view class="main"></router-view>
複製代碼

所謂的路由跳轉,其實只是在更新main這塊內容
能夠看一下前端的路由文件router.js

export default new Router({
routes: [
// 前臺頁面路由
{
  path: '/',
  redirect: '/Blogs'
},
{
  path: '/Blogs',
  name: 'Blogs',
  component: () => import('../components/ShowBlogs.vue')
},
{
  path: '/Essays',
  name: 'Essays',
  component: () => import('../components/ShowEssays.vue')
},
{
  path: '/Articles',
  name: 'Articles',
  component: () => import('../components/ShowArticles.vue')
},
{
  path: '/Message',
  name: 'Message',
  component: () => import('../components/ShowMessages.vue')
}]
複製代碼

四大功能的路由,其中首頁作了重定向,直接默認跳轉到文章頁面 而跳轉的實現都在擡頭的tab選項卡中

<router-link to="/Blogs">文章</router-link>
  <router-link to="/Essays">雜談</router-link>
  <router-link to="/Articles">收藏</router-link>
  <router-link to="/Message">留言板</router-link>
  <router-link v-if="admin" to="/Back">管理</router-link>
複製代碼

其實每個按鈕都是個router-link,其中若是能在localStorage中取到token,就把管理入口也暴露
選中的顏色樣式都是經過.router-link-active:nth-of-type(x)來設計的,相似於這樣

#myHeader-link .router-link-active:nth-of-type(1) {
border-bottom: solid rgb(255, 184, 126) 3px;}
複製代碼

列表頁數據過濾

在列表頁,咱們只須要知道id,標題和時間,並不須要獲取文章的具體內容(content)
爲了不沒必要要的數據傳輸浪費時間,咱們在後端要對數據進行一次過濾

//router.js
router.get('/data/blog', function (req, res) {
MonBlog.find((err, data) => {
    if (err) {
        res.send(err)
        return
    }
    var simpleData = data.map(item => {
        return {
            title: item.title,
            date: item.date,
            _id: item._id
        }
    })
    res.send(simpleData.reverse())
})
})
複製代碼

使用map映射,只把須要的東西傳過去

搜索功能

搜索功能有點和後臺管理不同
這一次我定義了一個show數組
點擊搜索以後,調用函數來進行搜索,把搜索出來的結果存放在show中
因此咱們展現的一直都是show數組

因爲有三個功能用到了搜索框
因此我把搜索框單獨作成了一個組件
並無註冊爲全局組件
由於咱們但願它是做爲ShowBlogs、ShowEssays、ShowArticles這三個組件的子組件存在的,方便調用父組件提供的方法

import mySearch from "./mySearch";
複製代碼

每一個父組件都引入一次
點擊搜索時,向父組件發射搜索框裏的內容,並調用父組件的方法

//mySearch.vue
 methods:{
      search() {
          this.$emit('search',this.content)
      }
  }
複製代碼

在父組件中

<mySearch @search="searchfor"></mySearch>

methods:{
searchfor(s) {
  this.show = (this.blogs.filter(item => {
    if (item.title.includes(s)) {
      return item;
    }
  }));
}}
複製代碼

針對每一個組件,搜索框的顏色不同 是經過$route.path來判斷,動態綁定樣式

computed: {
mySearch: function() {
  return {
    mySearch1: this.$route.path == "/Blogs",
    mySearch2: this.$route.path == "/Essays",
    mySearch3: this.$route.path == "/Articles"
  };
}
}
複製代碼

具體的文章內容

點進具體的文章或雜談時,把id傳進路由,頁面拿着id去請求後端的數據
而後調用simpleMDE的原型方法將拿到的字符串轉換爲html格式

this.contentMarkdown=SimpleMDE.prototype.markdown(this.theOne.content)
複製代碼

v-html展現出來

<div id='markdownArticle' v-html="contentMarkdown"></div>
複製代碼

markdown的樣式我用了少數派的一款css,你們也能夠本身去尋找中意的,或者本身寫

點贊&評論功能

點讚的動畫組件我用的是 vue-clap-button,一個第三方小組件 github.com/AJLoveChina…

<vue-clap-button v-if="flag" size="60" :clicked="isClicked" />
複製代碼

原組件缺乏一個綁定的屬性,來傳遞是否已經點過贊這個狀態
因此改了一下源碼,增長了一個clicked的屬性,寫在props裏面

props: {
  clicked: {
  type: Boolean,
  default: false
}
},
複製代碼

因爲個人網頁是沒有遊客登錄功能的,因此要判斷該遊客是否已經對這篇文章點過讚了,我用的是localStorage

//判斷是否已經點過贊
ifClicked() {
  var zanList = JSON.parse(localStorage.getItem("zanList"));
  if (!zanList) return;
  if (
    zanList.some(item => {
      return item == this.theOne._id;
    })
  )
    this.isClicked = true;
}
複製代碼

當點讚的時候,給用戶localStorage存一個數組,保存已經點過讚的文章的id
就能夠在頁面初始化的時候,經過判斷文章id是否在這個數組中,來告訴點贊按鈕呈現紅色仍是灰色狀態

評論功能
從功能上來講其實沒什麼好講的,不過因爲comments不是一個數據,只是文章數據身上的一個屬性
因此數據庫並不會給每條評論自動分配一個id
而爲了便於刪除之類的操做,咱們須要在遊客提交評論的時候,給它加上一個隨機的id

id:Math.random().toString(36).substr(2)
複製代碼

網站的總體風格就是簡潔,從評論的頭像來講,我也只是在用戶提交的時候,隨機給了一個整數

headIndex: Math.floor(Math.random() * 6)
複製代碼

用來分配一個匿名頭像

<img class="cmt-div-img" :src="require('../assets/img/head/'+item.headIndex+'.jpeg')" alt />
複製代碼

注意由於是動態引入,圖片須要用require的方法引入

收藏&留言功能

收藏其實就是一個個超連接,引向外部的網站
留言功能相似評論,這裏再也不贅述

響應式設計

網站只作了很是簡單的響應式設計,基本就是把列表頁的橫向佈局設置成了豎向佈局 而有一點須要注意,是原來若是豎着排會在最下面的搜索按鈕和公告跑到了最上面

這裏主要用的是order,能夠在flex佈局中改變元素的順序

@media screen and(max-width:500px) {
    .mySlider {
         order: -1;
  }
複製代碼

至此,本網站的開發過程到一段落,下面就要把它上線了!

上線

購買服務器及域名

我買的是阿里雲的服務器,學生黨100多一年還挺划算的
要記住購買時設置的用戶名和密碼
而後買了ssevenk.com這個域名(ssevenk是我經常使用的用戶名),原本想買真名的gaoyufeng.com,但已經被人買走了
而後咱們就要在服務器上配置咱們的環境了,至關於把本地的那一套搬到服務器上去

安裝node

首先安裝一個能夠遠程操縱服務器的軟件 我用的是puTTy

輸入服務器ip地址進行鏈接,而後輸入用戶名和密碼,就可登錄操做咱們的服務器

安裝node的方法看了不少網上的教程,我只能說不靠譜
各類複雜,一頓操做,最後還報錯

後來偶然發現阿里雲的官方手冊上就有安裝node的教程 按照阿里雲的步驟,簡單又有效

安裝mongodb

整個上線過程當中最使人蛋疼的一步! 踩坑無數,整整裝了一天才裝好

直接上圖

這其中,爲了保證數據庫的安全,咱們要把上圖配置中的 noauth改成 auth=true
而後設置文件夾權限

$ cd /usr/mongodb
 $ chmd 777 db
 $ chmod 777 log
複製代碼

啓動mongodb

$ cd ~
$ mongod -f /usr/mongodb/mongodb.conf
複製代碼

因爲mongodb默認使用的是27017端口,因此咱們登錄阿里雲,開放這個端口

點擊右上角,添加安全組規則便可

下面咱們要給數據庫增長權限 在mongodb已啓動的狀況下,命令行輸入

use admin
db.createUser(
	{
	   user:'root',
		 pwd:'root',
		 roles:[ { role: 'userAdminAnyDatebase',db:'admin' } ]
	}
複製代碼

建立超級用戶 不過mongodb有一點比較特殊,超級用戶並非在數據庫和子數據庫都是暢通無阻的

事實上,mongdb的用戶權限和數據庫是綁定的,也就是建立一個新的數據庫,要想在這個新的數據庫插入數據,是須要建立一個與之對應的用戶的

說的很繞,操做邏輯也很詭異(因此在這一步卡了好久) 在建立超級用戶後,正確的操做步驟是:

  1. use admin 進入admin數據庫
  2. db.auth('root','root') 超級用戶認證
  3. db.createUser({user:'gyf',pwd:'123456',roles:[{role:'readWrite',db:'gblog'}]}) 建立gyf用戶,併爲它指定新的數據庫gblog
  4. db.auth('gyf','123456')切換成gyf用戶
  5. use gblog 切換至gblog數據庫
  6. db.repo.insert({'name':'hhh'}) 這樣就能夠正確插入一條數據了

單單隻有一個超級用戶是不能操做其餘新建的數據庫的

使用mongodb compass(就是安裝時被捆綁下載的那個),能夠可視化的看到這個過程
目標數據庫的名字都是admin,可是root用戶能看到全部的數據庫,gyf用戶只能看到gblog數據庫

此時其實咱們已經能夠在本地鏈接遠端的那個數據庫了
在原來後端中鏈接數據庫的地方,改爲

mongoose.connect('mongodb://gyf:123456@0.0.0.0:27017/gblog?authSource=admin')
複製代碼

前面輸入用戶名和密碼,0.0.0.0的地方輸入ip地址,最後輸入要操做的數據庫和權限來源(都是admin給的權限)

部署服務器

環境已經配置好了,下面就要把咱們的後端代碼部署上去
上傳代碼我一開始用的是Xftp 6 這個軟件,後來發現vscode裏面有個sftp的插件
能夠直接右鍵上傳,更快捷
安裝完插件後,ctrl+shift+p,而後輸入sftp:congfig,進行配置,記得要把自動上傳關閉

{
"name": "My Server",
"host": "IP地址",
"protocol": "sftp",
"port": 22,
"username": "用戶名",
"password": "密碼",
"remotePath": "路徑",
"uploadOnSave": false
}
複製代碼

而後直接在左側文件目錄,右擊sync Local -> Remote把後端代碼上傳

在本機上咱們用的是node\ app.js來啓動後端的,不過在服務器上,爲了保證它能一直運行,同時提升cpu利用率,咱們要使用進程守護工具pm2來啓動
先安裝pm2

npm install pm2@latest -g
cd /home/blog 切換到項目目錄
ln -s /root/node-v10.2.0-linux-x64/bin/pm2 /user/local/bin/ 中間的路徑是node的安裝位置
複製代碼

而後啓動咱們的後端

pm2 start app.js --name 'app'
複製代碼

咱們的服務器就跑起來了!
上一句話後面若是再跟一個--watch\ ,就會在文件或者文件夾變動時自動重啓,我這裏由於有上傳圖片的功能,會改變文件夾,致使圖片傳到一半服務器就重啓了,所以沒有使用這個功能
最後把咱們的node服務加到進程,保證NodeJs一直在後臺運行,就算重啓也自動運行

pm2 startup centos #pm2 stratup ubuntu
pm2 save
複製代碼

網頁部署

在vuecli中,npm build一下,就能夠把咱們的工程打包成html文件
不過在這以前,要把build配置中的assetsPublicPath改爲「 ./ 」 原本是 」/「,以免圖片缺失

打包結束後,把整個dist文件夾丟到服務器上 而後如何實現訪問它呢,咱們就須要在後端中作一些修改 在後端路由中,監聽到首頁的」/「就把html文件發給客戶端

router.get('/', (req, res) => {
res.setHeader("Content-Type", "text/html;charset='utf-8'");

//讀文件
fs.readFile("./dist/index.html", "utf-8", function (err, data) {
    if (err) {
        console.log("index.html loading is failed :" + err);
    }
    else {
        //返回index.html頁面
        console.log(data)
        res.end(data);
    }
})
})
複製代碼

這裏用到了node的fs模塊,能夠讀取文件

還記得咱們後端監聽的是7000端口嗎,因此此時,若是你的ip地址爲1.2.3.4
那麼在地址欄輸入1.2.3.4:7000,就能訪問到這個網頁了(記得要去安全組開放7000端口)

DNS解析

不過沒有哪一個網站是直接讓別人去訪問ip地址的
這時就要把咱們買的域名,經過DNS解析綁定到咱們的ip地址上來了
這一步在阿里雲的官網就可操做,比較簡單

不過,咱們只能綁定到ip地址,而默認的網頁端口實際上是80端口
因此在後端,咱們把原來監聽的7000端口,改爲80端口(一樣記得安全組開放80端口)

//app.js
app.listen(80)
複製代碼

就能夠經過www.ssevenk.com訪問到了!!

首屏空白優化

服務器運行不比本地,網絡傳輸速度忽然就重要了起來
一開始,網頁剛部署上去,打開網址到完整看見內容,整整花了10s!!
那一刻才知道什麼叫天荒地老

後來進行了一下打包的優化,能夠看個人這篇文章
juejin.im/post/5d0730…

不過仍是存在首屏必定時間的空白
這時候,就有一個東西很重要:加載動畫
比起3s的純空白,遊客反而更能接受4s帶着加載動畫的空白
你得讓遊客知道,個人網站能夠打開的,你只要等一會就行

在index.html中(不是App.vue,由於等到加載App.vue已通過了一段時間了)添加

<div id="Loading">
    <div class="loader-inner ball-beat">
       <div></div>
       <div></div>
       <div></div>
     </div>
</div>
	
<style type="text/css">
#Loading {
  top: 50%;
  left: 50%;
  position: absolute;
  -webkit-transform: translateY(-50%) translateX(-50%);
  transform: translateY(-50%) translateX(-50%);
  z-index: 100;
}

@-webkit-keyframes ball-beat {
  50% {
    opacity: 0.2;
    -webkit-transform: scale(0.75);
    transform: scale(0.75);
  }

  100% {
    opacity: 1;
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}

@keyframes ball-beat {
  50% {
    opacity: 0.2;
    -webkit-transform: scale(0.75);
    transform: scale(0.75);
  }

  100% {
    opacity: 1;
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}

.ball-beat>div {
  background-color: rgb(255, 184, 126);
  width: 20px;
  height: 20px;
  border-radius: 100% !important;
  margin: 3px;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
  display: inline-block;
  -webkit-animation: ball-beat 0.7s 0s infinite linear;
  animation: ball-beat 0.7s 0s infinite linear;
}

.ball-beat>div:nth-child(2n-1) {
  -webkit-animation-delay: 0.35s !important;
  animation-delay: 0.35s !important;
}
</style>
複製代碼

而後在最早出來的文章列表組件中,在mounted生命週期移除這個加載

mounted() {
  document.body.removeChild(document.getElementById("Loading"));
},
複製代碼

備案

因爲我買的是國內的主機,因此還要去備案
而這,又是一部血淚史

ICP備案

首先進行的是ICP備案,直接在阿里雲上申請
強烈建議即使網站還沒作好,也先去把ICP備了
否則等你急着上線的時候,就知道什麼叫度日如年了

跟着阿里雲的流程走,只要符合規定就能經過
這裏有一點很坑
由於我是在上海上學,家鄉江蘇,可是我沒有上海居住證就沒法在上海備案
填江蘇省備案吧,個人江蘇手機卡又早就不用了,不能用上海手機號備案
兩難之下,只好又去買了張江蘇的電話卡

總之真的是很是繁瑣,還有幕布拍照什麼的,前先後後花了我20天
不過,沒想到麻煩還沒結束

公安備案

如今好像有新規定,ICP備案好了,還要在30天內進行公安備案
看網上回饋,好像這個會比ICP快不少,並且不繁瑣
但沒想到我又掉坑了

無內容???why???
發給別的朋友看,也均可以看到網站內容啊

IE兼容

苦思冥想,終於想到了一種可能
他們還在使用IE!
打開ie11,輸入ssevenk.com,果真,一片空白

因而,開始與這個老古董搏鬥
vuecli其實有與ie瀏覽器兼容的辦法,參考官網,利用polyfill cli.vuejs.org/zh/guide/br…

可是沒想到官網的例子怎麼也不能生效
我打開ie11永遠是一片空白
後來無奈,從vuecli3又用回了vuecli2 在webpack.base.conf中設置

entry: {
app: ['babel-polyfill', './src/main.js']
},
複製代碼

在index.html中設置

<meta http-equiv="X-UA-Compatible" content="IE=edge">
複製代碼

終於成功了!!!!!!!
記念一下

總結

網站的構思是在4月份,其實5月初網站雛形就作好了
後來增增改改,基本上6月份就基本完成了服務器部署
可是直到7月中旬,才正式合法地上線了

整個就是一血淚史,不過不得不說,只有實際操做了一下,才能更理解一個網站的創做流程
對於各類技能的使用,服務端客戶端的理解也會上一個臺階
其實中間有很多小細節都沒講,挑了主要的部分,不過也已是長篇大論了\

開發不易,不過最棒的仍是那份正式上線的成就感!!
www.ssevenk.com

碼字也不易,但願個人經歷對大家有所幫助

相關文章
相關標籤/搜索