1.创建项目
2.清空工作
1.删除了src/assets、components、views
2.重置App.vue
<template>
<div>123</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
2.重置router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
]
const router = new VueRouter({
routes
})
export default router
3.项目搭建
1.reset.css
1.assets/css下创建reset.css文件
2.main.js引入
// 1.引入reset.css
import "./assets/css/reset.css"
2.rem.js
1.assets/js下创建rem.js
2.main.js引入
// 2.rem.js
import "./assets/js/rem"
px to rem
1.安装插件 px to rem ,默认换算是16
2.编辑器左下角—》设置图标—》settings(设置)—》搜索框:px to rem —>看到16,改成100
3.alt+z 实现px转rem rem转px
3.目录划分
-src
-assets 静态资源
-css
-js
-img
-components 公共组件
-filters 过滤器
-pages 路由组件
-home home页面
home.vue路由组件
-components 拼接home的组件们
banner.vue
list.vue
-request 请求
-router 路由
index.js 路由
App.vue 根组件
main.js 入口文件
4.一级路由
1.创建一堆相关组件
login 登录
index 大首页
movie 电影
movieDetail 电影详情
food 外卖
foodDetail 外卖详情
2.配置规则[src/router/index.js]
// 引入相关组件
import login from "../pages/login/login.vue"
import index from "../pages/index/index.vue"
import movie from "../pages/movie/movie.vue"
import movieDetail from "../pages/movieDetail/movieDetail.vue"
import food from "../pages/food/food.vue"
import foodDetail from "../pages/foodDetail/foodDetail.vue"
const routes = [
{
path:"/login",
component:login
},
{
path:"/index",
component:index
},
{
path:"/movie",
component:movie
},
{
path:"/movieDetail",
component:movieDetail
},
{
path:"/food",
name:food,
component:()=>import('../components/food.vue')
},
{
path:"/foodDetail",
component:foodDetail
},
{
path:"*",
redirect: "/login"
}
]
3.路由出口 [ src/App.vue]
<!-- 路由出口 -->
<router-view></router-view>
5.路由跳转|路由导航
1.router-link直接跳转
<router-link to="/index">前往大首页</router-link>
2.编程式导航
this.$router.push(path) //添加了一条新的历史记录
this.$router.replace(path) //用新的记录替换当前历史记录
this.$router.go(-1) //返回
6.二级路由
1.pages创建相关组件
home 首页
cate 分类
shop 购物车
mine 我的
2.路由出口 [ src/pages/index/index.vue]
<div>
<!-- 变化区域 -->
<router-view></router-view>
</div>
3.二级路由规则 [ router/index.js]
{
path: "/index",
component: index,
// 二级路由规则,path不加"/"
children: [
{
path: "home",
component: home
},
{
path: "cate",
component: cate
},
{
path: "shop",
component: shop
},
{
path: "mine",
component: mine
},
// 二级重定向
{
path:"",
redirect: "home"
}
]
},
4.底部导航高亮效果1 router-link-active
.footer .router-link-active{
color: blue;
}
5.路由导航高亮2 active-class
<!-- 底部导航 -->
<div class="footer">
<router-link to="/index/home" active-class="select">首页</router-link>
<router-link to="/index/cate" active-class="select">分类</router-link>
<router-link to="/index/shop" active-class="select">购物车</router-link>
<router-link to="/index/mine" active-class="select">我的</router-link>
</div>
.footer .select{
color: blue;
}
7.home.vue 路由导航
<template>
<div>
<h3>首页</h3>
<div class="box">
<h3>router-link</h3>
<!-- router-link 直接跳,没有条件 -->
<router-link to="/movie">电影</router-link>
<router-link to="/food">外卖</router-link>
</div>
<div class="box">
<h3>push:添加了一条新的历史记录</h3>
<button @click="toMovie">电影</button>
<button @click="toFood">外卖</button>
</div>
<div class="box">
<h3>replace:用新的记录替换当前历史记录</h3>
<button @click="toMovie2">电影</button>
<button @click="toFood2">外卖</button>
</div>
</div>
</template>
<script>
export default {
methods:{
toMovie(){
this.$router.push("/movie")
},
toFood(){
this.$router.push("/food")
},
toMovie2(){
this.$router.replace("/movie")
},
toFood2(){
this.$router.replace("/food")
}
}
}
</script>
8.movie.vue 返回
<template>
<div>
<h3>movie</h3>
<button @click="goback">返回</button>
</div>
</template>
<script>
export default {
methods:{
goback(){
this.$router.go(-1)
}
}
}
9.封装了公共组件
1.src/components中创建了公共组件goBack和toSearch
2.src/components中创建index.js
import goBack from "./goBack.vue"
import toSearch from "./toSearch.vue"
let myComponent={
goBack:goBack,
toSearch,
}
for(let key in myComponent){
Vue.component(key,myComponent[key])
}
3.main.js引入
// 引入全局组件
import "./components"
10.封装了过滤器
1.src/filters中创建过滤器filterPrice filterTime
2.src/filters/index.js
import Vue from "vue"
import filterPrice from "./filterPrice"
import filterTime from "./filterTime"
import filterTel from "./filterTel"
let filters={
filterPrice,
filterTime,
filterTel
}
for(let key in filters){
Vue.filter(key,filters[key])
}
3.main.js引入
// 引入过滤器
import "./filters"
11.动画
1.下载animate.css
npm i animate.css --save
2.main.js引入
// 引入animate.css
import "animate.css"
3.使用
<transition
enter-active-class="animate__animated animate__bounceInLeft"
>
<router-view></router-view>
</transition>
12.字体图标
1.下载字体图标
2.将iconfont.css放入静态资源assets中
3.main.js引入
import "./assets/css/iconfont.css"
4.使用
<template>
<i @click="$router.go(-1)" class="iconfont icon-back_icon"></i>
</template>
路由高阶
13.路由传参 (? search传参) 电影
1.movie.vue 进行传参
<ul>
<li is="router-link" :to="'/movieDetail?a=1&b=2&c=3&id='+item.id" v-for="item in list" :key="item.id" >
<h3>{{item.name}}</h3>
<div>时间:{{item.time|filterTime}}</div>
<div>价格:{{item.price|filterPrice}}</div>
</li>
</ul>
2.movieDetail.vue进行接收
mounted(){
// $router 路由对象,用来实现路由导航
// $route 路由信息,用来获取路径内容
console.log(this.$route.query.id);
//ajax
}
14.动态路由传参 [外卖]
1.food.vue绑定事件
<ul>
<li v-for="item in list" :key="item.id" @click="toDetail(item.id,item.name)">
<h3>{{item.name}}</h3>
<div>price:{{item.price|filterPrice}}</div>
</li>
</ul>
2.food.vue跳转
methods:{
toDetail(id,name){
// 动态路由
this.$router.push("/foodDetail/"+id+"/"+name)
}
}
3.修改路由规则 [src/router/index.js]
{
path: "/foodDetail/:id/:name",
component: foodDetail
},
4.foodDetail.vue接收参数
export default {
mounted(){
console.log(this.$route.params.id);
//ajax
}
}
15.命名路由
1.src/router/index.js
{
path: "/login",
component: login,
// 命名路由
name:"login"
},
{
path: "/search",
component: search,
name:"搜索页面"
},
<router-link :to="{name:'搜索页面'}" class="iconfont icon-sousuo"></router-link>
16.元信息 meta
home、cate、shop、mine都需要一个头部,但是内容不一样,可以使用元信息实现。[src/router/index.js]
children: [
{
path: "home",
component: home,
// 元信息
meta:{
title:"首页",
}
},
{
path: "cate",
component: cate,
meta:{
title:"分类"
}
},
{
path: "shop",
component: shop,
meta:{
title:"购物车"
}
},
{
path: "mine",
component: mine,
meta:{
title:"个人中心"
}
},
// 二级重定向
{
path:"",
redirect: "home"
}
]
Index.vue使用
<div class="header">{{$route.meta.title}}</div>
17.懒加载
let index = () => import("../pages/index/index.vue")
let movie = () => import("../pages/movie/movie.vue")
let movieDetail=()=>Promise.resolve(import("../pages/movieDetail/movieDetail.vue"))
let food=()=>Promise.resolve(import("../pages/food/food.vue"))
18.命名视图-了解
1.app.vue 写了2个出口
<div>
<router-view name="view1"></router-view>
<!-- 路由出口 没有name就是默认路由出口-->
<router-view></router-view>
</div>
2.src/router/index.js
{
path: "/login",
components:{
default:()=>import("../pages/login/login.vue"),
view1:()=>import("../components/ceshi.vue")
},
},
19.模式
设置模式mode [src/routr/index.js]
const router = new VueRouter({
//路由规则
routes,
// mode默认是hash
//history 不带# ,hash是带#
mode:"history"
})
打包命令:
npm run build
hash和history的区别
开发环境下(8080),hash和history没有区别
生产环境:
hash
1.前进 后退 刷新ok
"http://localhost:3000/#/login" "#/login"是hash值,hash的改变不会影响请求
2.采用的是window.onhashchange=()=>{}实现的
history
1.前进 后退ok 刷新(404,数据)
一旦刷新,那么就走了后端路由,如果后端有这个路由,直接数据展示,如果后端没有该路由,404
2.采用HTML5新增的interface 里面的pushState() replaceState()
3.工作的时候如果要用history,需要后端配合
20.后端开启方法 [代码/backstage]
cmd执行
npm i
npm start //localhost:3000
将打包后的前端代码放入www目录即可。
21.三层
设置了保卫人员,必须保卫人员同意了才能执行。
保安: 进 保卫的是:整个小区
前台:进 保卫的是:公司 出
秘书:进 保卫的是:老板 出
22.登录拦截- 全局守卫
需求:如果登陆了,才可以访问所有的路由,否则,只能访问登录。
1.login.vue设计一个标识,用来判断是否登录
login(){
if(this.name=="admin"&&this.pass=="123"){
//设计一个标识,用来后面判断是否登录 islogin=true
localStorage.setItem("islogin",true)
this.$router.push("/index/home")
}else{
alert("账号密码错误")
}
}
2.router/index.js 设置全局前置守卫,判断
// to:前往的$route
// from:从哪里来的$route
router.beforeEach((to,from,next)=>{
// 1.取出来islogin
let islogin=localStorage.getItem("islogin");//'true' null
// 2.如果去的是登录路由,直接进
if(to.path==="/login"){
next();
return ;
}
// 3.如果去的不是登录,判断islogin,真就进,否则,去登录
if(islogin){
next();
return;
}
next("/login")
})
23.路由独享守卫
需求:只有外卖小哥可以访问外卖一条线,只有用户可以访问电影一条线
1.router/index.js添加路由独享守卫
{
path: "/food",
component: food,
//路由独享守卫:守卫当前路由 path
beforeEnter(to, from, next) {
console.log("路由独享守卫");
// 如果是外卖小哥 type=1 ,就进入,如果不是,去个人中心
let type = localStorage.getItem("type");
if (type == "1") {
next()
} else {
next("/index/mine")
}
}
},
{
path: "/foodDetail/:id/:name",
component: foodDetail,
beforeEnter(to, from, next) {
let type = localStorage.getItem("type");
if (type == "1") {
next()
} else {
next("/index/mine")
}
}
},
2.home.vue
data(){
return {
type:localStorage.getItem("type")
}
},
<div class="box">
<h3>router-link</h3>
<!-- router-link 直接跳,没有条件 -->
<router-link to="/movie" v-if="type=='2'">电影</router-link>
<router-link to="/food" v-else>外卖</router-link>
</div>
<div class="box">
<h3>push:添加了一条新的历史记录</h3>
<button @click="toMovie" v-if="type=='2'">电影</button>
<button @click="toFood" v-else>外卖</button>
</div>
<div class="box">
<h3>replace:用新的记录替换当前历史记录</h3>
<button @click="toMovie2" v-if="type=='2'">电影</button>
<button @click="toFood2" v-else>外卖</button>
</div>
23.组件内部守卫[movie.vue]
需求:去电影页面,只要从首页过来才可以访问,否则不给访问
beforeCreate(){
console.log("创建之前")
},
//组件内部守卫
//组件进来之前:守卫的是组件让不让访问
// 这个钩子函数,比beforeCreate还要早,所以里面不能使用this,如果需要使用路由信息,那么使用to代替
beforeRouteEnter(to, from, next) {
console.log("进来之前")
console.log(this);
if (from.path == "/index/home"||from.path=="/movieDetail") {
next();
} else {
next("/login");
}
},
24.电影详情跳转电影详情[movieDetail.vue]
// 从movieDetail-->movieDetail ,参数换了,mounted不再触发
beforeRouteUpdate(to, from, next) {
console.log("路由更新之前");
console.log(to.query.id);
//ajax
next();
},
25.组件离开[movie.vue]
//离开之前:没有next,组件就不离开了
beforeRouteLeave(to, from, next) {
next()
},
26.守卫流程
router.beforeEach()[所有的path]-->beforeEnter() [path]-->beforeRouteEnter() [component]--->aterEach()-->8个生命周期
27.路由导航守卫
全局守卫
router.beforeEach((to,from,next)=>{}) //所有路由进来之前 登录拦截
router.afterEach((to,from)=>{}) //所有路由进来之后
路由独享守卫
beforeEnter(to,from,next){} //守卫path
组件内部守卫
beforeRouteEnter(to,from,next){} //路由进来之前 无this
beforeRouteUpdate(to,from,next){} //路由更新之前
beforeRouteLeave(to,from,next){} //路由离开之前
28滚动行为
const router = new VueRouter({
routes,
mode: "history",
//滚动处理
scrollBehavior(to,from,savePosition){
console.group("====滚动行为===")
console.log(savePosition);//{x:0,y:375}
console.groupEnd()
//如果保存了位置,就返回保存的地方;否则,返回到(0,0)
if(savePosition){
return savePosition
}else{
return {x:0,y:0 }
}
}
})
29vue.config.js配置文件
module.exports={
devServer:{
port:8080,
host:'localhost',
open:true
}
}