打通先後端全棧開發node+vue進階【課程學習系統項目實戰詳細講解】(1):建立項目,完成登陸功能

第一章 建議學習時間8小時·分兩次學習      總項目預計10章javascript

 

學習方式:詳細閱讀,並手動實現相關代碼(若是沒有node和vue基礎,請學習前面的vue和node基礎博客【共10章】html

演示地址:後臺:demoback.lalalaweb.com  前臺:demo.lalalaweb.com
前端

演示過程當中可能會發現bug,但願即時留言反饋,謝謝vue

源碼下載:https://github.com/sutianbinde/classweb               //不是所有的代碼,每次更新博客才更新代碼java

學習目標:此教程將教會你們 如何一步一步實現一個完整的課程學習系統(包括課程管理後臺/Node服務器/學習門戶三個模塊)。node

上次node基礎課程博客你們反響很好,時隔3個月,才更新項目部分,預計2~3天更新一章,我儘可能20天更新完畢,學完這個項目Nodejs和vue就基本熟悉了,如發現教程有誤的地方,請及時留言反饋webpack

視頻教程地址:www.lalalaweb.com,後期會上傳教學視頻,你們可前往視頻學習(暫時尚未視頻)ios

 

express項目構建  vue-cli項目構建git


 咱們首先給項目取一個名字  「在線課堂」 好啦,英文名 classwebgithub

先在本身喜歡的位置 建立項目目錄文件夾  classweb

 

建立node項目(這個項目咱們採起先後端分離的模式,因此須要分別建立node和vue項目,但都放在classweb中)

進入目錄,運行  express server 生成服務器端項目(server是咱們服務端項目的名字)   (這裏注意,得提早安裝node express-generator,學習過前面node基礎的同窗這些應該的安裝了的,沒安裝的先學前面的課程)

打開命令行的簡單方法:在文件夾中按住 shift 鼠標右鍵 點擊「在此處打開命令行」 / "在此處打開powershell窗口"

先安裝 cnpm 鏡像(它是npm的國內代理,可使下載速度加快,若是以及安裝了的就不用安裝了),使用以下代碼,安裝完成後測試一下 cnpm -v

npm install -g cnpm --registry=https://registry.npm.taobao.org

 

進入項目,安裝依賴,運行測試一下

 

這樣就運行起來了,在瀏覽器輸入http://localhost:3000/  訪問

上面 Node項目就建好了

 

建立 vue項目

先全局安裝vue-cli

npm install --global vue-cli

這裏注意,咱們最好是另外開一個命令行 來執行,由於開發時前面的Node項目和vue項目要同時運行

 

而後在建立vue項目,使用 vue init webpack vueclient

注意:ESLint選項要選擇no(否則代碼一點不規範就報錯) ,若是選錯了,把vueclient文件夾刪了從新建立一遍便可。

 

 進入項目,安裝依賴,運行

 

 這時候瀏覽器中就自動代開網頁了

 

兩個項目的安裝和測試就完成了

安裝mongodb操做軟件 Robomongo

百度雲連接

連接:http://pan.baidu.com/s/1jHLSG78 密碼:6dhb

安裝方法參考:https://jingyan.baidu.com/article/9113f81b011ee72b3214c78d.html

 

 連接好之後,在nwe connection右鍵  create database   輸入建立 classweb數據庫

 

建立好之後,展開classweb,而後在cloolections右鍵,  create collection 建立一個user表(在彈出框中輸入user),用來放後臺登陸的用戶

 

建立好之後就有user表了,雙擊就能打開user表,如今裏面沒有數據

 

 往裏面添加一條數據,便於之後登陸使用

user右鍵 insert document,而後輸入後面的數據 ,save, (數據用戶名 admin  密碼是 123456 加密後的字段 還有手機號)

 

{
    "name" : "admin",
    "phone" : "13388868886",
    "password" : "4QrcOUm6Wau+VuBX8g+IPg=="
}

 

 

 

而後表中就多了這麼一條數據了

 

實現登陸功能


 首先咱們把項目導入 編輯器,我這裏使用的Hbuilder,建議你們也使用這個,由於項目中nodemodules的文件太多,webstrom或sublimetex都會很卡

而後找到App.vue,去掉多餘示例樣式,只留圖中的部分,這是項目的入口頁面

注:每一個項目都有不少文件,你們暫時也不用明白他們都表示什麼意思,等用到的時候我會在用到的地方給你們講解的。

預警:第一次進入項目開發,確定會有不少報錯,你們必定仔細閱讀步驟,仔細實現代碼,若是報錯,有是英文的看不懂,你們能夠試着查一查百度/google,也能夠在下邊留言,我看到儘可能簡答,不要由於出錯了難以解決就放棄了,我開始學習的時候也遇到不少不知所措的錯誤,心中會有一萬隻草泥馬奔騰的感受。

 

 而後在componets文件夾中新建 login.vue 文件

 

在login.vue文件中寫入下面登陸頁面的代碼(實現了基本的登陸佈局,在js中定義就基本的變量和登陸的方法名)

<template>
  <div class="backlogin">
        <div class="login_box">
            <div class="title">後臺登陸</div>
            <div>
                <input class="myinput" type="text" placeholder="手機號/用戶名" v-model="username" />
            </div>
            <div>
                <input @keyup.13="login" class="myinput" type="password" placeholder="口令" v-model="password" />
            </div>
            <div class="login_other">
                <a href="javascript:;">找回密碼</a>
                <input type="checkbox" id="remenberme" /><label for="remenberme">記住我</label>
            </div>
            <button :disabled="disablebtn" class="login" @click="login">{{loginText}}</button>
        </div>
        
  </div>
</template>

<script>
    
    export default {
      name: 'backlogin',
      data () {
        return {
                username:"admin",/*TODO:先預存測試值,以避免手動輸入*/
                password:"123456",
                disablebtn:false,
                loginText:"登陸"
        }
      },
      methods:{
            login(){
                
            }
        }
    }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
    .header{
        height: 60px;
        box-shadow: 0 1px 5px rgba(13,62,73,0.2) ;
    }
    .header img{
        width: 170px;
        margin-top: 12px;
        margin-left: 15px;
        float: left;
    }
    .header span{
        float: left;
        color: #566a80;
        margin: 21px 0 0 20px;
    }
    .login_box{
        width: 320px;
        margin: 50px auto;
    }
    .login_box .myinput{
        width: 100%;
        border: 1px solid #cad3de;
        height: 40px;
        line-height: 40px;
        margin: 5px 0 10px;
        border-radius: 3px;
        padding: 0 10px;
        outline: none;
        box-sizing: border-box;
    }
    .login_box .myinput:focus{
        border: 1px solid #4289dc;
    }
    .login_other{
        overflow: hidden;
    }
    
    .login_other a{
        float: right;
        color: #727f8f;
    }
    .login_other a:hover{
        color: #273444;
    }
    .login_other input, .login_other label{
        float: left;
        color: #727f8f;
    }
    .login_other input{
        margin: 4px 5px 0 0;
    }
    .login{
        box-sizing: border-box;
        border: none 0;
        height: 44px;
        line-height: 44px;
        width: 100%;
        background:#4187db;
        font-size: 16px;
        border-radius: 3px;
        margin-right: 40px;
        transition: all 0.5s ease;
        cursor: pointer;
        outline: none;
        color: #fff;
        margin-top: 15px;
    }
    .login:hover{
        background: #2668b5;
    }
    .login[disabled]{
        opacity: 0.8;
    }
    .login[disabled]:hover{
        background:#4187db;
    }
    .title{
        color: #273444;
        font-size: 1.5em;
        text-align: center;
        margin: 0 0 20px 0;
    }
    
    @media only screen and (max-width: 768px) {
        .login_box{
            width: 280px;
            margin: 50px auto;
        }
    }
</style>

 

 而後修改router文件夾下的index.js文件來配置首頁訪問的組件是login.vue   (這裏獲取組件的時候  @表示src文件夾路徑  全部vue文件的引入都不須要vue後綴,import後的賦值最好統一給大寫)。

 

 這樣咱們會發現剛打開的vue項目自動刷新了,展現效果以下圖(若是沒有刷新請查看命令行窗口有無報錯,有報錯就須要修改代碼,修改正確再重啓 npm run dev)

 

ajax請求


 

vue中請求數據,這裏咱們使用第三方庫axios,這也是vue做者推薦的,比自帶的http好用不少。

先安裝axios

把原來的服務ctrl+c兩次停掉,而後 運行 cnpm install axios --save 安裝,安裝完成再從新啓動服務。

注:這裏爲何要用 --save呢,由於使用save的話,這個包就會集成到package.json中的,咱們上線的時候就能經過npm install去直接安裝了。

 

安裝完成後你們打開package.json,就能夠看到裏面多了 axios:版本號

 

 

 而後咱們在main.js中添加以下代碼 引入axios,並配置基礎路徑(由於是跨域請求node端,因此全部請求前面都須要添加node端的基礎地址,之後打包上線的時候須要合併的時候再把這個地址刪掉),文件位置和修改後的代碼以下圖

因爲是跨域請求,咱們須要配置withCredentials爲true,這樣避免每次都被識別爲新的請求。

說明:在vue中,可使用代理去實現跨域,可是每次新地址都須要配置,仍是比較麻煩,這裏咱們採用直接配置跨域,一次配置就能夠一勞永逸。

import axios from 'axios';//引入axios組件
axios.defaults.withCredentials=true;  //跨域保存session有用
axios.defaults.baseURL = "http://localhost:3000"; //打包的時候直接刪掉,默認基礎路徑在這裏配置
//將 axios 賦值給 Vue,方便在子組件裏面使用
Vue.prototype.$reqs = axios;

 

 

 而後在Login.vue中寫登陸的具體方法  將以下登陸請求代碼寫在 login方法中,登陸的地址爲 「/users/login」 ,這個接口咱們一下子在node中去寫。

                var _this = this;
                this.disablebtn = true;
                this.loginText = "登陸中...";
                //this.$reqs就訪問到了main.js中綁定的axios
                this.$reqs.post("/users/login",{
                        username:this.username,
                        password:this.password
                }).then(function(result){ 
                    //成功
                    console.log(result)
                    _this.disablebtn = false;
                    _this.loginText = "登陸";
                    
                }).catch(function (error) {
                    //失敗
                    _this.disablebtn = false;
                    _this.loginText = "登陸"
                });
                

 

 

而後咱們轉到node端

先在routes中建立dbhandler.js文件,寫入下面咱們封裝好的mongodb操做方法。增刪改查的具體操做咱們在前面的node基礎教程中已經詳細講解了,這是這些方法的封裝,代碼和之前講的封裝有些許差別,你們直接用下面的代碼,不要用之前的。

這些方法這裏直接貢獻給你們,你們就能夠不用本身寫了,直接複製就Ok,空了能夠好好研究研究

 

var mongo=require("mongodb");
var MongoClient = mongo.MongoClient;
var assert = require('assert');
var url = require('url');
var host="localhost";
var port="27017";
var Urls = 'mongodb://localhost:27017/classweb';
// classweb  ===> 自動建立一個


//add一條數據 
var add = function(db,collections,selector,fn){
  var collection = db.collection(collections);
  collection.insertMany([selector],function(err,result){
    try{
        assert.equal(err,null)
        }catch(e){
      console.log(e);
      result = [];
    };
    
    fn(result);
    db.close();
  });
}
//delete
var deletes = function(db,collections,selector,fn){
  var collection = db.collection(collections);
  collection.deleteOne(selector,function(err,result){
    try{
        assert.equal(err,null);
        assert.notStrictEqual(0,result.result.n);
        }catch(e){
      console.log(e);
      result.result = "";
    };
    
    fn( result.result ? [result.result] : []); //若是沒報錯且返回數據不是0,那麼表示操做成功。
    db.close;
  });
};
//find
var find = function(db,collections,selector,fn){
  //collections="hashtable";
  var collection = db.collection(collections);
  
    collection.find(selector).toArray(function(err,result){
      //console.log(docs);
      try{
        assert.equal(err,null);
      }catch(e){
        console.log(e);
        result = [];
      }
      
      fn(result);
      db.close();
    });

}


//update
var updates = function(db,collections,selector,fn){
  var collection = db.collection(collections);
  
  collection.updateOne(selector[0],selector[1],function(err,result){
      try{
        assert.equal(err,null);
        assert.notStrictEqual(0,result.result.n);
        }catch(e){
      console.log(e);
      result.result = "";
    };
    
    fn( result.result ? [result.result] : []); //若是沒報錯且返回數據不是0,那麼表示操做成功。
    db.close();
  });

}
var methodType = {
    // 項目所需
  login:find,
  //   type ---> 不放在服務器上面
  //  放入到服務器
  //  請求---> 根據傳入進來的請求 數據庫操做
  //  req.query    req.body
  show:find, //後臺部分
  add:add,
  update:updates,
  delete:deletes,
  updatePwd:updates,
  //portal部分
  showCourse:find,
  register:add
};
//主邏輯    服務器  , 請求    --》 
// req.route.path ==》 防止前端的請求 直接操做你的數據庫
module.exports = function(req,res,collections,selector,fn){
  MongoClient.connect(Urls, function(err, db) {
    assert.equal(null, err);
    console.log("Connected correctly to server");
    // 根據 請求的地址來肯定是什麼操做  (爲了安全,避免前端直接經過請求url操做數據庫)
    methodType[req.route.path.substr(1)](db,collections,selector,fn);
    
    db.close();
  });

};

 

 而後修改自動生成的 users.js  爲以下代碼

代碼解釋:

引入了express框架,路由router,而且引入了上面封裝的 dbhandler。

crypto是加密包,對傳輸過來的密碼進行加密

post請求使用  post方法接收

handler()調用的是dbhander中的方法,傳入的參數依次 ( req:請求詳細, res:響應信息,  「user」操做的表的名稱, 傳入的查詢數據, 回掉函數)

在dbhander.js中配置了login對應的操做是查詢,返回數據放到數組中。若是數組空,就表示沒查到數據,若是非空,比較密碼是否一致,若是都正確,就返回登陸成功。

最後的module.exports = router是ES6的模塊暴露,前面基礎博客中已經講了,這裏就不贅述了

var express = require('express');
var router = express.Router();
var handler = require('./dbhandler.js');
var crypto = require('crypto');

/* POST users listing. */
//登陸
router.post('/login', function(req, res, next) {
    var md5 = crypto.createHash('md5');
    var password = md5.update(req.body.password).digest('base64');

    handler(req, res, "user", {name: req.body.username},function(data){
        if(data.length===0){
            res.end('{"err":"抱歉,系統中並沒有該用戶,若有須要,請向管理員申請"}');
        }else if(data[0].password !== password){
            res.end('{"err":"密碼不正確"}');
        }else if(data.length!==0&&data[0].password===password){
            
            req.session.username = req.body.username; //存session
            req.session.password = password;
            
            res.end('{"success":"true"}');
        }
        
    });
    
});

module.exports = router;

 

這樣請求的代碼就寫完了,可是跨域請求 須要在node中也做配置才能夠請求到

修改app.js,在11行左右找到 var app= express(),在其後面添加以下代碼

第二段代碼是服務器端存session的,直接使用express-session模塊(後面會帶着你們安裝),而後添加配置項便可(配置項的說明在備註中)

//跨域  後期刪
app.all('*', function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "http://localhost:8080"); //爲了跨域保持session,因此指定地址,不能用*
    res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    res.header('Access-Control-Allow-Credentials', true); 
    next();
});
//session
var session=require('express-session');
app.use(session({
    secret:'classweb531234',               //設置 session 簽名
    name:'classweb',
    cookie:{maxAge:60*1000*60*24}, // 儲存的時間 24小時
    resave:false,             // 每次請求都從新設置session
    saveUninitialized:true
}));

 

 

 中止Node端服務,安裝mongodb

cnpm install mongodb@2.2.33 --save

 

安裝 express-session

cnpm install express-session --save

 

 重啓服務

 

刷新vue的登陸頁面,點擊登陸

你會發現,控制檯打印出了返回的登陸成功信息,這樣咱們的登陸功能就編寫完成了 (常見出錯緣由在後面附錄)

 

 附錄:常見報錯


 

 1. 數據庫鏈接失敗 :

  ①可能mongo未自動啓動,請按基礎教程中的介紹正確啓動mongo (Net start MongoDB) 

   ②數據庫名沒寫對  檢查dbhandler.js中的下圖名字是否和數據庫名稱同樣。

  ③表名稱沒給對 ,檢查user.js 中的表名是否和數據庫中的一致。

 

2.根本連接不到地址,在網頁控制檯打印紅色的連接失敗

  ①請求地址沒寫對,覈對login.vue中的地址和 node端routes/index.js中的地址是否對上

 

  ②跨域配置不對,請按上面的步驟把 vue部分和node部分都好好再覈對着寫一遍

 

 

 

 

好啦,今天就講到這裏。下一篇將講解 首頁路由配置,導航,首頁統計信息,用戶添加/修改/刪除,表格組件封裝。

 

關注公衆號,博客更新便可收到推送

相關文章
相關標籤/搜索