前端筆記之Vue(七)Vue-router&axios&Vue外掛&Mock.js&cookie|session&加密
一、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>
http://127.0.0.1:8080/#/music
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,可以非常方便的模擬後端的資料,也可以輕鬆的實現增刪改查這些操作。
官網:http://mockjs.com/
安裝依賴:
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 |
http://cmd5.com/
兩種演算法都是:
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)示例程式碼
&n