第二章 建議學習時間8小時 總項目預計10章
學習方式:詳細閱讀,並手動實現相關代碼(如果沒有node和vue基礎,請學習前面的vue和node基礎博客【共10章】
演示地址:後臺:demoback.lalalaweb.com 前臺:demo.lalalaweb.com
演示過程中可能會發現bug,希望即時留言反饋,謝謝
源碼下載:https://github.com/sutianbinde/classweb //不是全部的代碼,每次更新博客才更新代碼
學習目標:此教程將教會大家 如何一步一步實現一個完整的課程學習系統(包括課程管理後臺/Node服務器/學習門戶三個模塊)。
上次node基礎課程博客大家反響很好,時隔3個月,才更新項目部分,預計2~3天更新一章,我儘量20天更新完畢,學完這個項目Nodejs和vue就基本熟悉了,如發現教程有誤的地方,請及時留言反饋
視頻教程地址:www.lalalaweb.com,後期會上傳教學視頻,大家可前往視頻學習(暫時還沒有視頻)
首頁導航 路由配置
上一篇博客中,我們已經實現了登錄功能,那麼接着我就需要寫登錄完成後跳轉的頁面
我們先把項目運行起來 Node端 npm start ,vue端npm run dev
首先我們需要使用一個字體圖標庫 fontawesome,如果沒有用過的自行百度啊,這裏就不扯其他知識了
下載地址:http://fontawesome.dashgame.com/ 或者 到github下載的本項目中對應路徑去找也可以
下載好以後把css和font放到static中,然後我們在index.html中引入
<link rel="stylesheet" type="text/css" href="../static/css/font-awesome.min.css"/>
注:1。我沒有找到可以通過import引入的fontawesome包,所以就直接引入文件了,(網上有 vue-awesome,但貌似不好用,就沒有用)
這裏爲什麼是 ../static 這樣去找static,而不是 ./ ,因爲當進入二級路由以後,在路由內部index和static就不在被認爲是同一級,就找不到了,所以就通過 ../往上再找了一級。
我們要設置一些統一的全局樣式,我們就直接寫在 index.html中,這裏本來不是一次就寫完這些樣式,但爲了避免以後再回來添加樣式,這裏就一起寫了,首先清楚了全局的margin等,然後定義了 .btn按鈕樣式 .myinput輸入框樣式,以後再使用
<style>
*{
margin: 0;
padding: 0;
}
body{
font-size: 14px;
font-family: arial "microsoft yahei";
background: #f0f2f5;
}
ul,li{
list-style: none;
}
/*按鈕*/
.btn{
border:1px solid #4187db;
color: #4187db;
background: #fff;
padding: 6px 14px 7px;
border-radius: 3px;
transition: all 0.5s ease;
outline: none;
margin-top: 14px;
cursor: pointer;
}
.btn i{
margin-right: 4px;
}
.btn:hover{
background: #4187db;
color: #fff;
}
/*輸入框*/
.myinput{
width: 65%;
border: 1px solid #cad3de;
height: 35px;
line-height: 35px;
margin: 5px 0 10px;
border-radius: 3px;
padding: 0 10px;
outline: none;
box-sizing: border-box;
}
.myinput:focus{
border: 1px solid #4289dc;
}
</style>
在assets文件夾中創建 images文件夾,放入我們backIndex.vue中需要的圖片 (圖片請到github下載的項目中對應路徑去找)
然後我們去修改 路由文件 index.js的路由,在其中添加後臺首頁框架的路由,如下圖
並且在components中創建 backIndex.vue組件
在backIndex.vue組件中寫入後面代碼
基本功能如下圖,左側導航,頂部搜索欄和個人頭像 退出等操作
代碼解釋:中間大部分是Html+css代碼,代碼中註釋已經可以幫助大家理解
這裏着重說一下路由部分:router-link表示點擊的時候url需要跳轉的地址,這些地址對應的路由文件還沒有寫,這裏先寫上,下下步就配置這個,頁面不多,我們就完成 首頁 用戶/學員管理 課程列表/課程編輯 幾個頁面,這樣就可以算是一個基礎版的後臺管理系統了。
當點擊對應的link的時候,vue內部會自動添加router-link-active 類,我們css中對這個類做了樣式設置。
<template>
<div class="backlogin">
<div class="header">
<div class="search_box" :class="{search_box_fouce:search_box_fouce}">
<i class="fa fa-search" aria-hidden="true"></i>
<input @focus="focusFn" @blur="blurFn" type="text" name="" id="" value="" placeholder="搜索 . . . " />
</div>
<div class="handler">
<div class="more" @click="toggleSlide">
<i class="fa fa-bars" aria-hidden="true"></i>
<ul :class="{showul:showExit}">
<li><a href="javascript:;" @click="logout"><i class="fa fa-sign-out" aria-hidden="true"></i>退出</a></li>
<li><a href="javascript:;" @click="">修改密碼</a></li>
<li><a href="javascript:;">意見反饋</a></li>
</ul>
</div>
<img src="../assets/images/teacherimg01.png" alt="" />
</div>
</div>
<!--側面導航-->
<div class="sidenav_box">
<img class="logo" src="../assets/images/logo03.png" alt="" />
<ul class="sidenav">
<li class="now">
<router-link to="/backIndex/indexContent">
<i class="fa fa-home" aria-hidden="true"></i>
<span>網站首頁</span>
</router-link>
</li>
<li>
<router-link to="/backIndex/adminList">
<i class="fa fa-user-o" aria-hidden="true"></i>
<span>後臺人員</span>
</router-link>
</li>
<li>
<router-link to="/backIndex/studentList">
<i class="fa fa-user-circle-o" aria-hidden="true"></i>
<span>學員管理</span>
</router-link>
</li>
<li>
<router-link to="/backIndex/courseList">
<i class="fa fa-book" aria-hidden="true"></i>
<span>課程管理</span>
</router-link>
</li>
</ul>
</div>
<div class="content">
<ul class="breadcrumb">
<li><a href="#/backIndex/">首頁</a></li>
<li>{{pageTitle}}</li>
</ul>
<router-view></router-view>
</div>
</div>
</template>
<script>
var pageTitleObj = {
indexContent:"網站首頁",
adminList:"後臺人員",
studentList:"學員管理",
courseList:"課程管理",
courseEdit:"課程編輯"
};
export default {
name: 'backlogin',
data () {
return {
search_box_fouce:false,
showExit:false,
pageTitle: pageTitleObj[ this.$route.path.substr( this.$route.path.lastIndexOf("/")+1 ) ] || "網站首頁"
}
},
methods:{
focusFn(){ //搜索框獲取焦點,添加class
this.search_box_fouce = true;
},
blurFn(){ //搜索框失去焦點,去掉class
this.search_box_fouce = false;
},
toggleSlide(){ //這個是用來顯示和隱藏頭像旁的退出下拉框
this.showExit = !this.showExit
},
logout(){ //退出系統
}
},
watch:{ //監控路徑變化 當路徑發送變化的時候,改變麪包屑導航的顯示
$route: {
handler: function (val, oldVal) {
var path = val.path;
this.pageTitle = pageTitleObj[ path.substr( path.lastIndexOf("/")+1 ) ] || "網站首頁";
}
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
ul, li{
list-style: none;
}
.header{
height: 60px;
box-shadow: 0 1px 5px rgba(13,62,73,0.2) ;
background: #fff;
margin-left: 80px;
min-width: 740px;
}
.sidenav_box{
width: 80px;
box-shadow: 0 1px 5px rgba(13,62,73,0.2) ;
position: fixed;
left: 0;
top: 0;
bottom: 0;
background: #fff;
z-index: 99;
}
.sidenav_box .logo{
width: 46px;
margin: 20px 0 0 17px;
}
.sidenav{
margin-top: 30px;
}
.sidenav li{
margin-bottom: 20px;
}
.sidenav a{
display: block;
width: 56px;
height: 56px;
margin: 0 auto;
position: relative;
cursor: pointer;
opacity: 0.6;
transition:all 0.5s ease;
text-decoration: none;
}
.sidenav a i{
font-size: 20px;
line-height: 56px;
text-align: center;
display: block;
color: #566a80;
}
.sidenav a:hover{
background: #f0f2f5;
opacity: 1;
}
.sidenav a span{
position: absolute;
left: 55px;
top: 22px;
background: #000;
color: #fff;
width: 0px;
padding: 5px 0;
border-radius: 3px;
font-size: 12px;
opacity: 0;
}
.sidenav a:hover span{
opacity: 1;
left: 65px;
width: 60px;
padding: 5px 20px;
transition:none 0.5s ease-out;
transition-property: opacity,left;
}
.sidenav a span:after{
content: "";
position: absolute;
top: 8px;
left: -10px;
border:5px solid transparent;
border-right-color: #000;
}
.sidenav .router-link-active:after{
content: "";
position: absolute;
left: -16px;
top: 8px;
height: 40px;
width: 8px;
border-radius: 3px;
background: #566a80;
}
.sidenav .router-link-active{
opacity: 1;
background: #f0f2f5;
}
/*頂部欄*/
.search_box{
color: #979fa8;
padding-top: 20px;
float: left;
}
.search_box i{
margin: 0 12px 0 70px;
transition: all 0.5s ease;
}
.search_box input{
border:none;
outline: none;
}
.search_box_fouce i{
margin-left: 55px;
color: #2C3D50;
}
.handler > *{
float: right;
margin-right: 20px;
cursor: pointer;
}
.handler .more{
font-size: 20px;
color: #566A80;
margin: 15px 30px 0 0;
position: relative;
}
.handler .more:hover{
color: #2C3D50;
}
.handler .more ul{
font-size: 14px;
position: absolute;
right: 0;
top: 55px;
width: 120px;
box-shadow: 0 1px 5px rgba(13,62,73,0.2);
transition: all 0.3s ease-out;
height: 0;
opacity: 0;
overflow: hidden;
text-align: center;
}
.handler .more .showul{
height: auto;
top: 45px;
opacity: 1;
border-top: 1px solid #979FA8;
}
.handler .more a{
display: block;
padding: 8px 10px;
background: #fff;
color: #566A80;
text-decoration: none;
}
.handler .more a:hover{
background: #f8f9fb;
}
.handler > img{
width: 50px;
border-radius: 50%;
margin-top: 5px;
margin-right: 30px;
}
.content{
margin: 20px 30px 0px 100px;
min-height: 300px;
min-width: 700px;
}
.breadcrumb{
border-radius: 4px;
padding: 10px 15px;
background: #fff;
}
.breadcrumb > li{
display: inline-block;
color: #777777;
}
.breadcrumb > li+li:before{
padding: 0 5px;
color: #ccc;
content: "/\00a0";
}
.breadcrumb > li > a{
color: #32475f;
text-decoration: none;
}
.main{
border-radius: 4px;
background: #fff;
margin-top: 10px;
}
</style>
然後在地址欄輸入 http://localhost:8080/#/backIndex 就可以看到首頁框架的效果了。 (這時候內部頁面還沒有,所以點擊左側導航會找不到頁面,先不要點)
常見錯誤: 如果前面的圖片路徑沒放對,就會出現這個錯誤
然後我們繼續將所有的路由配置其他頁面的路由
一共有 課程列表 / 編輯課程 / 首頁統計 / 後臺用戶 / 學員用戶 這些二級頁面,我們都加入到 路由文件 index.js中
按 Ctrl+C 複製代碼
按 Ctrl+C 複製代碼
添加這些路由後的需要建立對應的 vue 組件文件,在componets中建立上面路由對應的空vue文件
這些新建的vue文件中需要先放入一個空的template標籤,以免報錯
<template>
</template>
再刷新頁面的時候,左側導航就可以點擊了(這些router-link對應的路徑和路由對應的path一致),可以看到麪包屑導航對應的名字就修改了(這個修改的邏輯在backIndex.vue的97行左右的 watch方法中)。
首頁統計頁面
然後我們爲 indexContent.vue 添加中間顯示的統計圖表,代碼在後面
代碼如下:由於前臺頁面的統計還沒開始寫,當下我們就只放一個靜態頁面在此,
canvas繪製提標使用的是原生js寫的,具體的原理步驟請查看我以前的博客 http://www.cnblogs.com/chengduxiaoc/p/7678967.html
按 Ctrl+C 複製代碼
按 Ctrl+C 複製代碼
然後我們可以看到,首頁的效果就出來啦
登錄功能完善:
當登錄請求完成以後,如果出錯,就彈出錯誤(我們本項目沒有封裝模態框,就直接用alert吧),如果正確,就跳轉到首頁
修改後的 login.vue中的 ajax請求代碼如下:
按 Ctrl+C 複製代碼
按 Ctrl+C 複製代碼
注:我們通過 router.push去修改url,作用和原生js的 window.location.href基本一致。
退出系統
功能點:點擊退出,實現退出功能
在backIndex.vue中我們有一個退出登錄的空方法,我們在裏面寫退出登錄的請求的代碼,退出成功後跳轉到根目錄(以就算登錄頁面)
logout(){ //退出系統
var _this = this;
this.$reqs.post("/users/logout",{
}).then(function(result){
//成功
_this.$router.push({path:'/'});
}).catch(function (error) {
//失敗
console.log(error)
});
}
然後在後臺寫接口,在user.js中 登錄的方法後面寫(修改完成後需要重啓node服務)
注:這裏直接清除登錄中設置的 session 就可以了,(我們後面會對所有的請求設置攔截,如果session中的用戶信息沒有,再提示用戶未登錄,跳轉到登錄頁面就可以了)
//退出
router.post('/logout', function(req, res, next) {
req.session.username = ""; //清除session
req.session.password = "";
res.end('{"success":"true"}');
});
到此,我們就實現了登錄,顯示首頁,退出的基本功能
好啦,今天就講到這裏。下一篇將講解 用戶添加/修改/刪除,表格分頁