官网:https://router.vuejs.org/zh/javascript
用 Vue.js + Vue Router 建立单页应用,是很是简单的。使用 Vue.js ,咱们已经能够经过组合组件来组成应用程序,当你要把 Vue Router 添加进来,咱们须要作的是,将组件 (components) 映射到路由 (routes),而后告诉 Vue Router 在哪里渲染它们。css
安装vue路由:html
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); //一、定义 (路由) 组件,引入路由页面 import music from "./views/music/index.vue"; import movie from "./views/movie/index.vue"; //二、建立路由数组(路由表) const routes = [ { path: '/music', component: music }, { path: '/movie', component: movie }, //重定向路由(当路由地址不在路由数组中的时候,默认跳到music) { path: "*", redirect : "/music" } ] //三、建立router实例,而后传routes配置(这里带有路由的配置参数) const router = new VueRouter({ routes // 至关于 routes: routes }) new Vue({ el: "#app", router, //注入到全局,会被注入到每一个组件中,能够利用$router进行一些信息的获取 render: (h) => h(App) })
而后新建一个views视图文件夹,放两个路由页面:vue
movie文件夹中的index.vuejava
<template> <div> <h1>电影首页</h1> </div> </template>
经过注入路由器,咱们能够在任何组件内经过 this.$router 访问路由器,也能够经过 this.$route 访问当前路由: jquery
最后在App.vue中放路由标签便可显示全部路由表中的组件:ios
<template> <div> <router-view></router-view> </div> </template>
http://127.0.0.1:8080/#/musicgit
添加两个按钮,作选项卡切换页面:github
<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等。
引用路由有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' } ]
在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>
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分"} ] } }
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;
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>
移动端点击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>
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快速模拟数据。不再用追着后端小伙伴要接口了。
在工做中,后端的接口每每是较晚才会出来,而且还要写接口文档,因而前端的许多开发都要等到接口给咱们才能进行,这样对于前端来讲显得十分的被动,因而有没有能够制造假数据来模拟后端接口呢,答案是确定的。应该有人经过编写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看看吧!") })
这是纯后台的东西,咱们搞前端的了解便可。
HTTP是无链接的,当你第一次访问一个服务器的时候,第二次再来到这个服务器(可能就10s以后),服务器此时的HTTP和第一次毫无关系的。对于服务器来讲,HTTP是两次,两次之间没有持久保持连续。因此服务器不知道你曾经来过,也不知道你曾经作的事情。
cookie是HTTP的一个性质,不优雅的解决了HTTP无链接,服务器对客户端的识别问题。
HTTP在最初的版本,就设计了一个cookie的东西,说白了是:
服务器在response的报头中设置一个set-cookie的报文头
从此浏览器每次访问这个服务器的时候,都要带着这个cookies字段上去。
服务器就变相的记住了客户端电脑曾经的行为。
Cookie:
当服务器在HTTP响应头部下发了一个Set-Cookie,从此每次Request浏览器都会带着相同的cookie上去。
Seesion:
session就是cookie,是一种特殊的cookie,是不发送明文,而是发送随机乱码的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);
怎么实现登陆?
登陆很简单,但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);
不能在数据库中用明码存密码,若是你保存明码,此时若是你的数据库丢失,或者你的员工、工程师使坏,故意泄密,此时用户其余的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)