基於vue2,eggjs,mysql的我的博客(正在更新)

簡單作個博客。
功能點:
註冊、登陸、cookie、權限控制、文章列表、文章詳情、文章目錄、點贊、評論、分頁加載css

前端

使用vue-cli3建立項目

npm install -g @vue/cli
vue create hello-world

爲了避開煩人的 eslint,選擇了手動選擇特性:
image.png
同時沒有選擇 Linter/Formatter,使用 vscode 中的插件 prettier 和 vetur 配合格式化代碼。
image.pnghtml

使用axios封裝http請求方法

參考了vue中Axios的封裝和API接口的管理,對網絡請求進行了發封裝。
image.png
網絡請求統一放在/src/request中,config.js中是基本配置信息:
image.png
http.js中封裝請求攔截、響應攔截、錯誤統一處理。
api.js中是網站全部接口,將其導出後,掛載到 vue.prototype.$api 上,這樣全局可使用 this.$api.xxx 使用接口:
image.png
而後在main.js引入並掛載:
image.png前端

cookie/session

博客採用cookie/session的方式來記錄會話狀態,在app.vuecreated生命週期函數中經過checkLogin()接口查詢用戶登陸狀態,具體的邏輯爲:
噹噹網流程圖3.pngvue

首頁分頁加載

let documentEle = document.documentElement
  let needLoadMore =
    documentEle.scrollTop + documentEle.clientHeight + 50 > documentEle.scrollHeight;
  if (needLoadMore && !this.nomore) {
    this.loadingMore = true;
    //暫時不能再滾動加載數據
    this.nomore = true;
    this.loadMoreArticle();
  }

document.documentElement.scrollTop:文檔滾動的距離
document.documentElement.clientHeight:文檔在可視範圍內的高度
document.documentElement.scrollHeight:文檔總高度java

判斷思路是:視口的高度 + 文檔的滾動距離 >= 文檔總高度,能夠預留50的距離作預加載。前端每一次判斷觸底後,會向後端請求下一頁數據,並返回 nomore 字段,表示是否還有未加載文章。這裏有個細節是:每一次觸底後手動將 nomore 設爲 true,後端返回 nomore 後再修改其值,這樣作的目的是防止在請求返回前再次發送請求。
參考:搞清clientHeight、offsetHeight、scrollHeight、offsetTop、scrollTopmysql

如何展現博文

沒有實際作博客以前,覺得每一篇博文都是經過單獨寫html標籤的方式排版的...而後經過別人的項目,發現了正確的作法是:
使用markdown/富文本編輯器編輯文章,生成html片斷,在vue中使用v-html語法插入該html片斷,文章便以html標籤的形式渲染出來可。博客中使用的markdown編輯器是mavonEditor,另外使用highlightjs高亮代碼。linux

<div v-html="articleInfo.contentHtml" class="article-container" ref="content"></div>

提取目錄

extractCatalog() {
      let contentElementRef = Array.from(
        this.$refs.content.querySelectorAll("h1,h2,h3,h4,h5,h6")
      );
      contentElementRef.forEach((item, index) => {
        item.id = item.localName + "-" + index;
        this.catalogList.push({
          tagName: item.localName,
          href: `#${item.localName}-${index}`,
          text: item.innerText
        });
      });
    }

上一小節中,將文章的html片斷渲染到了div容器元素中,接下來可使用querySelectorAll("h1,h2,h3,h4,h5,h6")函數來找出文中全部的標題Dom節點,querySelectorAll()的好處在於它會按照傳入參數的順序進行查找,因此不用擔憂亂序。獲取到目錄後對各級目錄編號,以便生成錨點進行跳轉。ios

判斷對應節是否出現

watchPageScrollFunc() {
      let contentElementRef = Array.from(
        this.$refs.content.querySelectorAll("h1,h2,h3,h4,h5,h6")
      );
      for (let index = 0; index < contentElementRef.length; index++) {
        const viewPortHeight =
          window.innerHeight ||
          document.documentElement.clientHeight ||
          document.body.clientHeight;
        const elementHeight = contentElementRef[index].clientHeight;
        const el = contentElementRef[index];
        const top =
          el.getBoundingClientRect() &&
          el.getBoundingClientRect().top + elementHeight;
        if (top <= viewPortHeight && top > 0) {
          this.firstVisibleElemetHref = this.catalogList[index].href;
          break;
        }
      }
    }
    
    window.addEventListener("scroll", this.watchPageScrollFunc);

判斷方法:元素上邊到視口上邊的距離 + 元素自身高度 <= 視口高度 && 元素上邊到視口上邊的距離 + 元素自身高度 > 0
其中,獲取元素到視口上邊的距離用到:getBoundingClientRect(),某個元素相對於視窗的位置集合。集合中有top, right, bottom, left等屬性:nginx

rectObject = object.getBoundingClientRect();

rectObject.top // 元素上邊到視窗上邊的距離;

rectObject.right // 元素右邊到視窗左邊的距離;

rectObject.bottom // 元素下邊到視窗上邊的距離;

rectObject.left // 元素左邊到視窗左邊的距離;

在整個文章的Dom結構中,使用querySelectorAll("h1,h2,h3,h4,h5,h6")去搜索全部標題類的Dom節點,每一次滾動都去依次動態檢查這些標題元素距離視口上方的距離,找到第一個出如今視口中的Dom元素就返回。另外加上節流函數可優化性能。git

參考:如何判斷元素是否在可視區域ViewPort

評論的實現

評論數據採用的數據結構以下,這裏只作到了二級評論,數據結構定下來,具體的實現仍是比較簡單的。

let comments = [
  {
    author: "admin",
    content: "留言1",
    articleId: "9",
    time: "2020-04-12 10:59",
    id: "0",
    replyList: [
      {
        author: "ghm",
        content: "回覆留言1",
        articleId: "9",
        replyTo: "admin",
        time: "2020-04-12 10:59",
        id: "0-0"
      }
    ]
  },
  {
    author: "admin",
    content: "留言2",
    articleId: "9",
    time: "2020-04-12 10:59",
    id: "1",
    replyList: [
      {
        author: "ghm",
        content: "回覆留言2",
        articleId: "9",
        replyTo: "admin",
        time: "2020-04-12 11:00",
        id: "1-0"
      }
    ]
  }
];

可添加表情的輸入框

初版的實現方式:在<input>中直接插入emojiunicode,展現效果以下所示:
image.png
這樣作的問題在於:展現效果沒有圖片好,而且在不一樣的瀏覽器中會展示出不一樣的效果。果斷換用圖片形式展現表情,可是<input>是不能插入<img>標籤的,因而參考了掘金的實現方式,使用contenteditable這個css屬性將普通Dom元素變爲可編輯的Dom元素,這樣就可使用appendChild()的方式將<img>插入,最終的顯示效果也是明顯優於直接使用emoji的。

<div
    class="textarea"
    ref="inputContent"
    contenteditable="true"
    autocomplete="off"
    :placeholder="placeholder"
    draggable="false"
    spellcheck="false"
  ></div>

image.png

後端

數據庫表的設計

上線

配置服務器環境

1.一臺linux服務器
做者買的阿里雲最便宜的ECS雲服務器,配置爲1核2G,1M帶寬,做爲學習使用徹底夠了,操做系統選擇的CentOS。而後參照阿里雲給出的教程在服務器上部署NodeJs環境部署mysql
2.購買域名
在阿里雲上購買域名後,按照新手引導設置域名解析,同時設置 www 和 @,網站即可經過 www.xxx.com 和 xxx.com 訪問。同時,想要使用域名訪問網站,還須要對域名進行備案。
3.本地數據庫遷移到雲服務器
做者使用的數據庫可視化工具是navicat,在navicat中對選中的數據庫作轉儲SQL文件處理,再在雲服務器的mysql中新建數據庫,運行此SQL文件,便完成了數據庫的遷移。
image.png

上傳文件

1.下載文件傳輸工具 Xftp
2.部署前端代碼

npm run build

打包好後,使用 Xftp 將 dist 文件夾上傳到服務器中
3.部署後端代碼
將後端代碼 git clone 到服務器中

npm i
npm start

配置nginx

1.安裝nginx

yum install nginx

安裝好的 nginx 會在 /etc/nginx
2.使用 Xftp 修改 nginx 配置
找到/etc/nginx目錄下的 nginx.conf文件,使用記事本打開編輯:

user  root;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
  include       mime.types;
  default_type  application/octet-stream;

  sendfile        on;
  keepalive_timeout  65;

  server {
    listen       80;
    server_name  localhost;
    root  /root/project/dt_blog/frontend/dist/;
    index  index.html;
    add_header Access-Control-Allow-Origin *;
      
    location /api {
      proxy_pass  http://127.0.0.1:7001;
      proxy_set_header  HOST $host;
    }
        
    location / {
      try_files $uri $uri/ @router;
      index index.html;
    }

    location @router {
      rewrite ^.*$ /index.html last;
    }
  }
}

其中這兩個配置很重要:

location / {
  try_files $uri $uri/ @router;
  index index.html;
}

location @router {
  rewrite ^.*$ /index.html last;
}

網站部署好後,能夠正常訪問,可是打開二級頁面後再刷新,就會404,緣由是:v-router設置的路徑並非真實存在的路由,工程中的路由跳轉都是經過 js 實現的,而將前端打包好的 dist 目錄部署在服務器後,在瀏覽器中訪問根路徑會默認打到 index.html 中,可是直接訪問其餘路徑,就沒有一個真實的路徑與其對應。(參考:https://www.cnblogs.com/kevingrace/p/6126762.html

作好以上配置後,就能夠經過 服務器ip:80 來訪問部署好的網站了,可是一直經過 ip 地址訪問網站不太合理,那麼就須要給網站配置域名。

配置域名

相關文章
相關標籤/搜索