一、Vue-router(路由)
1.1路由創建
官網:https://router.vuejs.org/zh/
用 Vue.js + Vue Router 創建單頁應用,是非常簡單的。使用 Vue.js ,我們已經可以通過組合組件來組成應用程序,當你要把 Vue Router 添加進來,我們需要做的是,將組件 (components) 映射到路由 (routes),然后告訴 Vue Router 在哪里渲染它們。
安裝vue路由:
npm install vue-router --save
在main.js使用vue路由:
import Vue from 'vue'; import App from './App.vue'; import VueRouter from 'vue-router'; Vue.use(VueRouter); //1、定義 (路由) 組件,引入路由頁面 import music from "./views/music/index.vue"; import movie from "./views/movie/index.vue"; //2、創建路由數組(路由表) const routes = [ { path: '/music', component: music }, { path: '/movie', component: movie }, //重定向路由(當路由地址不在路由數組中的時候,默認跳到music) { path: "*", redirect : "/music" } ] //3、創建router實例,然后傳routes配置(這里帶有路由的配置參數) const router = new VueRouter({ routes // 相當於 routes: routes }) new Vue({ el: "#app", router, //注入到全局,會被注入到每個組件中,可以利用$router進行一些信息的獲取 render: (h) => h(App) })
然后新建一個views視圖文件夾,放兩個路由頁面:
movie文件夾中的index.vue
<template> <div> <h1>電影首頁</h1> </div> </template>
通過注入路由器,我們可以在任何組件內通過 this.$router 訪問路由器,也可以通過 this.$route 訪問當前路由:
最后在App.vue中放路由標簽即可顯示所有路由表中的組件:
<template> <div> <router-view></router-view> </div> </template>
1.2路由的跳轉
添加兩個按鈕,做選項卡切換頁面:
<template> <div class="app"> <header> <ul> <li v-for="item in tabNav" :class="{cur:item.url == $route.path}" @click="routerGo(item.url)" > {{item.title}} </li> </ul> <span>{{$route}}</span> </header> <router-view></router-view> </div> </template> <script> export default { data(){ return { tabNav : [ {title:"電影", url:"/movie"}, {title:"音樂", url:"/music"}, ] } }, methods: { routerGo(url){ this.$router.push({path:url}) } } }; </script> <style scoped> ul{list-style:none;overflow: hidden;} ul li{width:50%;height:40px;line-height:40px;text-align:center;float: left;} ul li.cur{background: red;color:#fff;} </style>
$route是路由圓信息,里面包含了:路由名稱、頁面路徑、hash、params等。
1.3引入路由的方式
引用路由有3種方式:
第一種:在app.js中用import引入文件
import music from "./views/music/index.vue"; import movie from "./views/movie/index.vue"; // 創建一個路由表(數組) const routes = [ { path: '/music', name: "音樂", component: music }, { path: '/movie', name: "電影", component: movie }, //路由重定向(當路由地址不在路由數組的時候,默認跳轉music) { path: '*', redirect: '/music' } ]
第二種:不用import引包,用require,但require()不是ES6的語法,不推薦使用
const routes = [ { path: '/music', name: "音樂", component: require("./views/music/index.vue").default }, { path: '/movie', name: "電影", component: require("./views/movie/index.vue").default }, //路由重定向(當路由地址不存在的時候,默認跳轉music) { path: '*', redirect: '/music' } ]
第三種:
const routes = [ { path: '/music', name: "音樂", component(){ return System.import("./views/music/index.vue") } }, { path: '/movie', name: "電影", component(){ return System.import("./views/movie/index.vue") } }, //路由重定向(當路由地址不在路由數組的時候,默認跳轉music) { path: '*', redirect: '/music' } ]
1.4子母路由(嵌套路由)
在main.js的父路由下加一個children的數組,這個數組就是存放子路由:
注意:name屬性最好放在meta對象中,否則name出現重名會警告。
const routes = [ { path:'/music', meta:{ name:"音樂" }, component(){ return System.import("./views/music/index.vue") } }, { path:'/movie', meta:{name:"電影"}, component(){ return System.import("./views/movie/index.vue") }, children:[ { path:'/movie/oumei', meta:{name:"電影"}, component(){ return System.import("./views/movie/oumei/index.vue") } }, { path:'/movie/guochan', meta:{name:"電影"}, component(){ return System.import("./views/movie/guochan/index.vue") } } ] }, //重定向路由(當路由地址不在路由數組中的時候,默認跳到music) { path: "*", redirect : "/music" } ]
重點:給父親添加router-view標簽顯示子頁面。有子路由,父路由頁面一定有一個router-view標簽。
<template> <div> <button v-for="item in nav" @click="routerGo(item.url)">{{item.title}}</button> <h1>電影頁面</h1> <router-view></router-view> </div> </template> <script> export default { data(){ return { nav :[ {title:"歐美", url: "/movie/oumei"}, {title:"國產", url: "/movie/guochan"} ] } }, methods:{ routerGo(url){ this.$router.push({path:url}) } } }; </script>
1.5 paramsid(動態路由參數)
https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html
const routes = [ { path:'/music', meta:{ name:"音樂" }, component(){ return System.import("./views/music/index.vue") } }, { path:'/movie', meta:{name:"電影"}, component(){ return System.import("./views/movie/index.vue") }, children:[ { //動態路徑參數 以冒號開頭 path:'/movie/:id', meta:{name:"電影"}, component(){ return System.import("./views/movie/list.vue") }, } ] }, //重定向路由(當路由地址不在路由數組中的時候,默認跳到music) {path: "*",redirect : "/music"} ]
movie/list.vue頁面
<template> <div> <h1>電影列表{{$route.params.id}}</h1> </div> </template>
新建data.json,然后發起Ajax請求數據(可以用vue-axios代替fetch)

{ "mapList" : { "oumei" : [ { "title" : "美國隊長1", "time" : "1小時30分"}, { "title" : "美國隊長2", "time" : "1小時40分"}, { "title" : "美國隊長3", "time" : "1小時50分"}, { "title" : "美國隊長4", "time" : "1小時55分"} ], "guochan" : [ { "title" : "戰狼1", "time" : "1小時30分"}, { "title" : "戰狼2", "time" : "1小時40分"}, { "title" : "戰狼3", "time" : "1小時50分"} ] } }
1.6路由守衛
router.js
import Vue from 'vue'; import VueRouter from 'vue-router'; import Index from '../views/index.vue'; import axios from 'axios'; Vue.use(VueRouter); const router = new VueRouter({ routes: [ { path: "/", name: "首頁", component: Index, meta: { needLogin: true,"juse":["user","admin"] } } ] }) router.beforeEach(async (to, from, next) => { //當用戶切換路由的時候,執行這里的語句 if(to.meta.needLogin == true){//needLogin字段代表當前頁面需要登錄 //驗證用戶是否登陸了 const { login, username,juse} = await axios.get("/api/checklogin").then(res=>res.data); console.log(login, username)//得到后端返回 if(login == true){ console.log("你通過驗證了") next();//放行 }else{ console.log("沒有通過驗證,去登陸") router.push("/login")//如果注冊時后端驗證用戶名重復就不允許通過,再回到登錄頁面 } }else{ //不需要驗證登陸的,直接放行 console.log("通過驗證了") next(); } console.log(to) }) export default router;
二、vue-axios
axios 是一個基於 Promise 的http請求庫,可以用在瀏覽器和Node.js中,可使用vue-axios發起Ajax請求,Axios本質上也是對原生XHR的封裝,只不過它是Promise的實現版本,符合最新的ES規范。
https://www.npmjs.com/package/vue-axios
安裝:
npm install --save axios vue-axios
在main.js引入:
import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(VueAxios, axios)
根據文檔使用插件,有三種使用方式:

Vue.axios.get(api).then((response) => { console.log(response.data) }) this.axios.get(api).then((response) => { console.log(response.data) }) this.$http.get(api).then((response) => { console.log(response.data) })
有了插件可以不用fetch就能輕松發送ajax了,在電影頁中點擊菜單的時候發ajax。將請求回來的數據,用[]號將國產電影 和 歐美電影的數據枚舉出來,再使用v-bind傳入 list.vue 組件中:
movie/index.vue:
<template> <div> <h1>我是電影頻道主頁</h1> <button v-for="item in tabNav" @click="routerGo(item.url)">{{item.title}}</button> <router-view :mapList="mapList"></router-view> </div> </template> <script> export default { data(){ return { tabNav :[ { title : "歐美" , url : "/movie/oumei" }, { title : "國產" , url : "/movie/guochan" } ], mapList : [] } }, methods : { routerGo(url){ this.$router.push({ path:url }) //發送Ajax請求數據 this.$http.get("../../../data/data.json").then((res) => { this.mapList = res.data.mapList[this.$route.params.id]; console.log(this.mapList) }) } } } </script>
./views/movie/list.vue頁面接收顯示:
<template> <div> <h1>我是詳情頁面{{$route.params.id}}</h1> <ul> <li v-for="item in mapList"> <span>{{item.title}}</span> <span>{{item.time}}</span> </li> </ul> </div> </template> <script> export default { props : ["mapList"] } </script>
三、vue插件
3.1 vue-touch插件
移動端點擊300ms的延遲,vue有一個vue-touch插件能消除300ms的延遲。
網址:https://github.com/vuejs/vue-touch/tree/next
注意:有版本區分。
安裝依賴:
npm install vue-touch@next --save
main.js引入方式:
import VueTouch from 'vue-touch'
Vue.use(VueTouch, {name: 'v-touch'})
頁面使用方式:
<v-touch tag="標簽名" v-on:tap="點擊事件">Tap me!</v-touch>
App.vue:
<v-touch v-for="item in tabNav" :class="{cur : $route.name == item.title}"
v-on:tap="routerGo(item.url)" :key="item.id" tag="li">{{item.title}}</v-touch>
gif.vue組件:
<v-touch tag="div" @tap="play" class="play" v-show="isPlay">play</v-touch>
3.2圖片懶加載
vue懶加載使用vue-lazyload,網址:https://www.npmjs.com/package/vue-lazyload
安裝依賴:
npm install --save vue-lazyload
main.js引入懶加載:

import VueLazyload from 'vue-lazyload' Vue.use(VueLazyload, { preLoad: 1, //高度縮放比例 // error: 'dist/error.png', loading: '../static/loading.gif', attempt: 1 //嘗試加載圖片數量 })
組件頁面使用方式:
<img v-lazy="child.wifi_img_url" >
vue的插件很多
官網插件庫:https://github.com/vuejs/awesome-vue
網址:https://cn.vuejs.org/v2/guide/transitions.html
插件庫:https://segmentfault.com/p/1210000008583242/read?from=timeline
可以使用外部 css動畫插件
網址:https://daneden.github.io/animate.css/
四、mock.js
有一個工具,叫做mock.js快速模擬數據。再也不用追着后端小伙伴要接口了。
在工作中,后端的接口往往是較晚才會出來,並且還要寫接口文檔,於是前端的許多開發都要等到接口給我們才能進行,這樣對於前端來說顯得十分的被動,於是有沒有可以制造假數據來模擬后端接口呢,答案是肯定的。應該有人通過編寫json文件來模擬后台數據,但是很局限,比如增刪改查這些接口怎么實現呢,於是今天我們來介紹一款非常強大的插件Mock.js,可以非常方便的模擬后端的數據,也可以輕松的實現增刪改查這些操作。
安裝依賴:
npm install --save-dev mockjs
require依賴,創建Random對象,就能模擬中文姓名了。
下面就是寫生成“模擬數據.txt”的程序:更多使用請移步官網

var path = require("path"); var fs = require("fs"); var Mock = require('mockjs'); var Random = Mock.Random; //基數據的地址 var jishuju = path.resolve(__dirname,"基數據.json"); //存儲生成文件的地址 var monishuju = path.resolve(__dirname,"模擬數據.txt"); //先刪除舊的數據 fs.writeFileSync(monishuju, ""); console.log("模擬數據.txt已清空,下面為你生成新的") //讀取基數據 fs.readFile(jishuju,function(err,data){ var data = JSON.parse(data.toString()); //遍歷100項,添加一些新的屬性和值 for(var i = 0;i < data.length;i++){ data[i].price = Random.integer(0,100); //售價 data[i].km = Random.integer(0,100); //公里數 data[i].owner = Random.cname(); //賣家姓名 //模擬十年的日期 data[i].buydate = new Date(new Date() - Random.integer(86400000, 86400000 * 365 * 10)); //排量 data[i].engine = Random.pick(['1.4L','1.6L','1.5T','1.6T','1.8L','1.8L','2.0L']); data[i].local = Random.boolean(); //是否本地車 data[i].pai = Random.boolean(); //是否上牌 fs.appendFileSync(monishuju, JSON.stringify(data[i]) + "\n\r") } console.log("模擬數據寫入成功,快打開.txt看看吧!") })
五、cookie和session
這是純后台的東西,我們搞前端的了解即可。
HTTP是無連接的,當你第一次訪問一個服務器的時候,第二次再來到這個服務器(可能就10s之后),服務器此時的HTTP和第一次毫無關系的。對於服務器來說,HTTP是兩次,兩次之間沒有持久保持連續。所以服務器不知道你曾經來過,也不知道你曾經做的事情。
cookie是HTTP的一個性質,不優雅的解決了HTTP無連接,服務器對客戶端的識別問題。
HTTP在最初的版本,就設計了一個cookie的東西,說白了是:
服務器在response的報頭中設置一個set-cookie的報文頭
今后瀏覽器每次訪問這個服務器的時候,都要帶着這個cookies字段上去。
服務器就變相的記住了客戶端電腦曾經的行為。
Cookie:
當服務器在HTTP響應頭部下發了一個Set-Cookie,今后每次Request瀏覽器都會帶着相同的cookie上去。
Seesion:
session就是cookie,是一種特殊的cookie,是不發送明文,而是發送隨機亂碼的cookie。 服務器就會比較這個亂碼和之前誰的一樣,你就是那誰。
5.1 cookie
app.js
var express = require("express"); var app = express(); //簡單的cookie演示 app.get("/",function(req,res){ res.cookie('name', 'Marte', { expires: new Date(Date.now() + 900000), httpOnly: true}); res.send("ok"); }) app.listen(3000)
語法:
res.cookie(k,v,設置)
Set-Cookie: name=Marte; Path=/; Expires=Tue, 14 Aug 2018 10:01:46 GMT; HttpOnly
有什么用,可以方便讓:
瀏覽器記錄服務器曾經給我們的信息
服務器記錄用戶提供的信息
里面有一個Set-Cookie,值為:
name=Marte; expires=Fri, 14-Aug-2018 10:01:46 GMT
表示Cookie的值,和過期時間。
今后的每一次訪問同一個域名下的任何網站,都可以看見Request Header中攜帶了相同的Cookie:
Cookie的性質:
① Cookie不安全,可以在任何時候被瀏覽器的network面板被查看。所以千萬不要試圖讓服務器下發密碼等機密信息。可以被自由修改,信息量不能大。
② Cookie是文件格式存儲。
③ 有超時的限制,可以自由設置存活時間。
在沒有本地存儲之前,用cookie實現本地存儲的功能
cookie一般來說是服務器端更改,瀏覽器只需要帶cookie碼上去即可。
必須使用cookie-parser這個npm包格式化cookie的顯示,有這個依賴,服務器才能讀取cookie
npm install --save cookie-parser
var express = require("express"); var cookieParser = require('cookie-parser') var app = express(); // cookieParser()是中間件 app.use(cookieParser()); //簡單的cookie演示 app.get("/",function(req,res){ res.cookie('name', 'Marte', { expires: new Date(Date.now() + 900000), httpOnly: true}); console.log(req.cookies.name) res.send("ok"); }) app.listen(3000)
實現一個歷史痕跡功能:做一個旅游網站,有很多城市簡介,此時網站首頁能夠記錄你曾經訪問過的地方,在HTML5時代用localStorage足夠好用,如果不讓使用本地存儲,只能借助cookie。
var express = require("express"); var app = express(); app.set("view engine" , "ejs"); app.get("/",function(req,res){ res.render("index.ejs"); }); app.get("/:city",function(req,res){ //識別/后面的字符 var city= req.params.city; res.render("city.ejs", {city}); }); app.listen(3000);
views/city.ejs:
<h1><%= city %>旅游攻略</h1> <script type="text/javascript"> //localStorage.setItem("lvyou","<%= city %>"); //讀 if(localStorage.getItem("lvyou")){ var arr = JSON.parse(localStorage.getItem("lvyou")); }else{ var arr = []; } arr.push("<%= city %>")//避免覆蓋,讀一條用數組存一條 localStorage.setItem("lvyou",JSON.stringify(arr));//設,本地存儲只能放字符串 </script>
views/index.ejs:顯示
<body> <h1>你的足跡:</h1> <div id="info"></div> <script type="text/javascript"> //讀取 var arr = localStorage.getItem("lvyou"); document.getElementById("info").innerHTML = arr; </script> </body>
用cookie實現思路:服務器每次都下發新的set-cookie命令,把你這一次訪問的地點都加入數組。用戶每次都帶着新的cookie上來,首頁不就一直更新了么?
app.js

var express = require("express"); var app = express(); var cookieParser = require('cookie-parser'); app.use(cookieParser()); app.get("/",function(req,res){ res.send("你的旅游足跡" + req.cookies.lvyou); }); app.get("/:city",function(req,res){ var arr = req.cookies.lvyou;//讀cookie if(!arr){ arr = []; } //改cookie var city = req.params.city; arr.push(city); //設cookie res.cookie("lvyou",arr,{maxAge:999999}); res.send(city + "旅游攻略"); }); app.listen(3000);
5.2 session
怎么實現登錄?
登錄很簡單,但HTTP是無連接的,A頁面登錄了,同樣的網站下B頁面不知道你登錄了。
不過有cookie,讓服務器發起Set-Cookie: username=Marte;login=true; 此時瀏覽器今后訪問這個網站的每個頁面都會帶着cookie上去。服務器識別cookie,一看就知道你登錄了!
但是,cookie可以被自由篡改!也就是說,我想登陸誰的號,就登錄了誰的號!
后來出現了session,它不通過cookie下發明文信息,而是發送一個隨機亂碼下去,一般代號都是64位。
服務器同時在內存中(服務器重啟數據會丟失)保存這個隨機碼的人的各種信息。如果有人帶這個隨機亂碼上來,一定是這個人!
我們把這種特別的cookie叫做SESSION,也叫作會話。
也就是說,session就是cookie!是一種特殊的cookie,是不發送明文,而是發送隨機亂碼的cookie。
session使用第三方中間件,叫做express-session。
官方API:https://www.npmjs.com/package/express-session

var express = require("express"); var app = express(); var session = require('express-session') //使用session中間件,這個中間件必須在第一位 app.set('trust proxy', 1) // trust first proxy app.use(session({ //對session id相關的cookie進行簽名 secret: 'Marte', //加密字符串,下發給瀏覽器的隨機亂碼都時基於這個字符串加密的 resave: false, saveUninitialized: true, //是否保存未初始化的會話 cookie: { maxAge : 999999 //設置session的有效時間,單位毫秒 } })) app.get("/",function(req,res){ var sess = req.session; sess.a = ~~(Math.random() * 10000); res.send("ok,已經記錄a為:" + sess.a) }) app.get("/test",function(req,res){ var sess = req.session; if(sess.a){ var str = sess.a.toString(); }else{ var str = "不存在"; } res.send(str) }) app.listen(3000)
今后我的每一次訪問,都會帶着這個碼上,這個碼對於瀏覽器來說,沒有任何意義,但是服務器就是通過這個碼來知道你是你。
登錄案例:
pages/login.html

<body> <h1>模擬登陸</h1> <p>用戶名:<input type="text" id="username"></p> <p>密碼:<input type="text" id="mima" value="123456"></p> <button id="btn"></button> <script type="text/javascript" src="/jquery-1.12.3.min.js"></script> <script type="text/javascript"> $("#btn").click(function(){ $.post("/dopost",{ "username" : $("#username").val(), "mima" : $("#mima").val() },function(data){ alert(data); if(data == "成功登陸!"){ window.location = "/";//刷新 } }) }); </script> </body>
jquery放在js靜態化文件夾中。
app.js

var express = require("express"); var app = express(); var session = require('express-session'); var path = require("path"); var formidable = require('formidable'); //靜態資源 app.use(express.static("js")); app.set('trust proxy', 1) // trust first proxy app.use(session({ secret: 'Marte', //加密字符串,下發的隨機亂碼都是依靠這個字符串加密的 resave: false, saveUninitialized: true })); app.get("/",function(req,res){ if(req.session.login){ //登錄了就顯示登錄頁面 res.send(`<h1>歡迎${req.session.username}成功登錄,<a href="/logout">退出</a></h1>`) }else{ // 用戶沒有登錄,就顯示登錄頁面 res.sendFile(path.join(__dirname, "pages/login.html")); } }); //接受表單 app.post("/login",function(req,res){ var form = new formidable.IncomingForm(); //設置上傳文件夾路徑 form.uploadDir = "./uploads"; form.parse(req, function(err, fields, files) { console.log(fields.username) if(fields.mima == "123456"){ //核心語句,設置session,如果沒有設置session,就和沒有登錄一樣。 req.session.login = true; req.session.username = fields.username; //顯示信息 res.send("成功登陸!"); }else{ res.send("密碼錯誤!"); } }); }); //退出登錄 app.get("/logout",function(req,res){ //剝奪登錄的session req.session.login = false; req.session.username = ""; res.redirect("/"); }); app.listen(3000);
5.3加密
不能在數據庫中用明碼存密碼,如果你保存明碼,此時如果你的數據庫丟失,或者你的員工、工程師使壞,故意泄密,此時用戶其他的QQ、Email如果是同一個密碼就被竊取了。
所以我們就要把密碼加密之后,存儲在數據庫中,當用戶登錄的時候,輸入的密碼再次做同樣的加密,把加密的密文和密文進行比對,如果相同,就說明用戶輸入正確了。
最最著名的兩套加密算法分別是SHA系列、MD5系列。他們都是著名的單向算法,僅僅能夠從明文計算出密文,你不可能找到一個方法從密文計算出明文。也就是說SHA、MD5都是用來加密的,而他們沒有解密功能。
Secure Hash Algorithm(安全哈希算法)
Message Digest Algorithm MD5(中文名為消息摘要算法第五版)
使用http://encode.chahuo.com/來測試一下SHA256加密算法,
sha256加密算法:
原文 |
密文 |
你好 |
670d9743542cae3ea7ebe36af56bd53648b0a1126162e78d81a32934a711302e |
這是單向加密算法,這個密碼經常用於檢測文字信息是否被篡改、是否完整。而不是用於通訊,不是說把密碼給別人,別人再次解密,因為這個密碼不能解碼。
MD5加密算法
原文 |
密文 |
你好 |
7eca689f0d3389d9dea66ae112e5cfd7 |
兩種算法都是:
l 不管文字長短都能加密出64位、32位的加密字符串
l 即使改變了一個字,密文也大改
l 即使你掌握了算法,也不能破譯

var crypto = require("crypto"); //創建一個sha256加密方法 // var sha256 = crypto.createHash("sha256"); // var str = sha256.update("你好").digest("hex"); //digest表示處理為hex十六進制 //創建一個md5加密方法 var md5 = crypto.createHash("md5"); var str = md5.update("世界你好").digest("hex"); console.log(str)