vue-day07
1-路由
1.1-嵌套路由
-
定义路由规则
/router/index.js
const routes=[ // 嵌套路由 // 父路由 { path:'/login', component:Login, meta:{ title:'登录页面' }, // 子路由 children:[ { path:'/login/user', component:User, meta:{ title:'普通用户登录页面' } }, { path:'/login/enterprise', component:Enterprise, meta:{ title:'企业用户登录页面' } } ] } ]
-
添加二级路由出口(在一级路由组件中添加)
pages/Login.vue
<template> <div> <h1>登录页面</h1> <router-link class="nav-btn" to="/login/user">普通用户</router-link> <router-link class="nav-btn" to="/login/enterprise">企业用户</router-link> <hr> <!-- 二级路由出口(二级路由占位符) --> <router-view></router-view> </div> </template> <script> export default { created() { // 通过操作真实dom, 实现更新页面标题 document.title = this.$route.meta.title; } }; </script> <style> </style>
1.2-路由导航守卫
1.2.1-全局守卫
-
全局前置守卫
- 执行时机: 页面跳转之前, 被触发
- 特点: 具备拦截页面跳转的功能
// 添加全局前置守卫 router.beforeEach((to,from,next)=>{ // 动态设置页面标题 document.title=to.meta.title; // console.log(to,from); // to: 即将前往的页面路由对象 // from: 即将离开的页面路由对象 // next: 方法, 可以实现页面跳转, 默认必须调用一次next // 放行本次路由跳转 next(); });
-
全局解析守卫(2.5.0版本之后新增)
- 执行时机: 页面跳转之前, 全局前置钩子
beforeEach
执行之后, 被触发 - 特点: 不具备拦截页面跳转的功能
router.beforeResolve ((to,from,next)=>{ // console.log(to,from); // to: 即将前往的页面路由对象 // from: 即将离开的页面路由对象 // next: 方法, 可以实现页面跳转, 默认必须调用一次next // 放行本次路由跳转 next(); });
- 执行时机: 页面跳转之前, 全局前置钩子
-
全局后置钩子
- 执行时机: 页面跳转完成之后, 被触发
- 特点: 不具备拦截页面跳转的功能
// 全局后置钩子 router.afterEach((to, from) => { // 动态设置页面标题 document.title = to.meta.title; // to:即将前往的页面路由对象 // from: 即将离开的页面路由对象 console.log('afterEach'); });
1.2.2-路由独享守卫
- 特点: 具备拦截页面跳转的功能
- 执行时机: 在页面跳转之前, 全局前置守卫
beforeEach
执行之后, 自动触发 - 生效范围: 只对当前路由对象对应的页面跳转起作用
const routes = [
{
path: '/',
component: Home,
meta: {
title: '网站首页'
},
// 路由独享守卫: 全局前置守卫执行之后, 被触发
beforeEnter(to,from,next){
// to: 即将前往的页面路由对象
// from: 即将离开的页面路由对象
// next: 方法, 可以实现页面跳转, 默认必须调用一次next
// console.log('beforeEnter');
// 默认情况下, next方法必须调用
next();
}
}
]
1.2.3-组件内的守卫
1.2.3.1-特点
- 具备拦截页面跳转的功能, 所以如果显示声明了组件内的导航守卫钩子, 一定要手动调用
next
方法, 否则页面无法正常显示
1.2.3.2-钩子函数
- beforeRouteEnter
- 执行时机: 路由组件被渲染之前
- 注意: 不能使用
this
关键字获取组件实例对象
- beforeRouteUpdate
- 执行时机: 动态路由对应的组件, 由于动态参数发生改变被重复渲染的时候, 自动触发
- beforeRouteLeave
- 执行时机: 导航离开该组件的对应路由时调用
export default{
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
next(vm=>{
// 通过vm获取组件实例对象
console.log(vm);
})
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
next();
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
next();
}
}
1.3-页面滚动处理
// 4-创建路由实例
const router = new Router({
// 路由规则数组
routes,
// 指定路由模式
mode: 'hash',
// 自定义路由导航链接高亮类名
linkActiveClass: 'active',
// 控制组件页面滚动条的位置
scrollBehavior(){
return {x:0,y:100}
}
});
1.4-404路由
const routes=[
// 404路由
{
path:'*',
component:NotFound,
meta: {
title: '404页面'
}
}
]
1.5-使用嵌套路由改造后台管理系统
-
路由文件
router/index.js
// 1-导入路由模块 import Vue from 'vue' import VueRouter from 'vue-router'; // 2-注册插件 Vue.use(VueRouter); // 3-创建路由规则 // 导入页面组件 import Main from '../pages/Main'; import Goods from '../pages/Goods'; import Order from '../pages/Order'; import User from '../pages/User'; import Layout from '../pages/Layout'; const routes = [{ path: '/', component: Layout, children: [{ path: '/main', component: Main, meta: { title: '管理中心' } }, { path: '/goods', component: Goods, meta: { title: '商品管理' } }, { path: '/user', component: User, meta: { title: '会员管理' } }, { path: '/order', component: Order, meta: { title: '订单中心' } } ] }]; // 4-创建路由对象 const router = new VueRouter({ routes, mode: 'hash', linkActiveClass: 'active' }); // 5-导出路由实例对象 export default router;
-
根组件
App.vue
<template> <div> <!-- 一级:路由出口 --> <router-view></router-view> </div> </template> <script> export default { }; </script> <style> </style>
-
布局组件
Layout.vue
<template> <div class="container"> <div class="left"> <ul class="navbar"> <!-- 启用路由严格匹配模式 --> <router-link tag="li" to="/main">管理中心</router-link> <router-link tag="li" to="/goods">商品管理</router-link> <router-link tag="li" to="/user">会员管理</router-link> <router-link tag="li" to="/order">订单管理</router-link> </ul> </div> <div class="right"> <!-- 头部 --> <Header></Header> <div class="content"> <!-- 二级路由占位符 --> <router-view></router-view> </div> <!-- 底部 --> <Footer /> </div> </div> </template> <script> // 1-导入页组件 // 导入功能组件 import Header from "../components/Header"; import Footer from "../components/Footer"; export default { // 2-注册组件 components: { Header, Footer }, data() { return { // 页面组件名称 page: "Order" }; }, methods: { // 切换页面 changePage(page) { this.page = page; } } }; </script> <style> *{ padding: 0; margin: 0; box-sizing: border-box; } .container { background-color: #ddd; /* vh:相对单位; 100vh=屏幕的高度 1vh==1/100屏幕高度; viewport height */ height: 100vh; display: flex; } /* 左侧导航栏 */ .container .left { 226px; background: #00152a; } .left .navbar li { list-style: none; line-height: 50px; color: #fff; text-align: center; cursor: pointer; } .left .navbar li:hover { background: #0077b8; } .left .navbar li.active { background: #0077b8; } .container .right { flex: 1; display: flex; flex-direction: column; } .right .header { height: 60px; line-height: 60px; text-align: center; background: #fff; } .right .content { margin: 10px; background: #fff; height: 300px; text-align: center; flex: 1; } .right .footer { line-height: 60px; text-align: center; background: #fff; } </style>
2-axios
2.0-原生js发送ajax请求的步骤
-
创建一个XMLHttpRequest对象
const xhr=new XMLHttpRequest();
-
设置请求行
xhr.open('请求方式GET/POST','数据接口地址');
-
发送请求
xhr.send();
-
监听服务器的响应
xhr.onreadystatechange=function(){ if(xhr.readyState===4&&xhr.status==200){ console.log('请求被响应',xhr.responseText); console.log('请求被响应',xhr.responseXML,); } }
2.1-axios的介绍
- axios是基于ES6中promise的一个第三方的http类库
2.1.1-安装
npm i axios -S
2.2-axios发送数据请求
2.2.1-get请求
import axios from 'axios';
axios({
// 指定数据接口
url:'',
// 指定数数据提交方式为GET
method:'GET',
// get请求的参数
params:{
}
}).then(res=>{
console.log(res);
})
// 专门用来发送get请求的方法
axios.get('接口地址',{
// get请求的参数
params:{
}
}).then(res=>{
// 成功处理函数
})
2.2.1-post请求
import axios from 'axios';
axios({
// 指定数据接口
url:'',
// 指定数数据提交方式为GET
method:'POST',
// POST请求的参数
data:{
}
}).then(res=>{
console.log(res);
})
// 专门用来发送post请求的方法
axios.post('接口地址',{
// 直接书写请求体: 需要提交给数据接口的参数
name:'',
age:''
}).then(res=>{
// 成功处理函数
})
2.3-拦截器
2.3.1-请求拦截器
// 请求拦截器
// req: 系统自动注入, 包含了和请求相关的一些数据对象
axios.interceptors.request.use(function(req){
// console.log(req,'interceptors.request');
// console.log(req.headers);
// 添加自定义请求头
req.headers.token='12345678';
// 一定要有返回值
return req;
});
2.3.2-响应拦截器
// 响应拦截器
// response: 系统自动注入的参数, 包含和响应相关的数据对象
axios.interceptors.response.use(function(response){
// console.log(response,'interceptors.response');
// response.data是服务端返回的真实数据
return response.data;
});
2.4-axios的全局配置
-
全局配置基础域名(baseURL)
axios.defaults.baseURL='http://localhost:3000/api';
-
配置请求头
// 配置请求头 axios.defaults.headers.auth='abc';
2.5-axios.all()方法
- 作用: 批量执行数据请求
- 返回值: 数组
- 参数: 数组
export default {
methods:{
// 获取分类列表
async getCates(){
const res=await axios({
url:'/getcate',
method:'GET',
params:{
name:'张三',
age:20
}
});
return res.data;
},
// 获取轮播图数据
async getBanners(){
const res=await axios.get('/getbanner',{
// get请求参数
params:{
name:'lisi',
age:20
}
});
return res.data;
}
},
created(){
// this.getCates();
// this.getBanners();
axios.all([this.getCates(),this.getBanners()]).then(res=>{
// 数组的解构赋值
const [cates,banners]=res;
// 更新数据
if(cates.code===200){
this.cates=cates.list;
}
if(banners.code===200){
this.banners=banners.list;
}
})
},
}
2.6-axios.create()方法
-
作用: 创建一个axios实例对象
import axios from 'axios'; const http=axios.create({ // 配置基础域名 baseURL:'http://localhost:3000/api', // 请求头: 系统, 自定义 headers:{ token:'123456789' } }); // 请求拦截器 // req: 系统自动注入, 包含了和请求相关的一些数据对象 http.interceptors.request.use(function(req){ // console.log(req,'interceptors.request'); // console.log(req.headers); // 添加自定义请求头 req.headers.token='12345678'; // 一定要有返回值 return req; }); // 响应拦截器 // response: 系统自动注入的参数, 包含和响应相关的数据对象 http.interceptors.response.use(function(response){ // console.log(response,'interceptors.response'); // response.data是服务端返回的真实数据 return response.data; }); export default http;
3-测试数据接口服务器的搭建
-
下载数据接口源代码
shop-api-数据接口服务器.zip
-
解压
-
安装依赖: 进入数据接口项目根目录, 执行如下命令行
npm i
-
导入数据库备份文件
-
修改项目配置文件(主要修改数据库配置信息), 打开
/config/global.js
, 做如下修改exports.dbConfig = { host: 'localhost', //数据库地址 user: 'root',//数据库用户名 password: 'root',//数据库用户密码 port: 3306, database: 'shop_db' // 数据库名字 }
-
启动数据接口服务器
npm run start // 或者(如果没有安装nodemon工具,使用如下命令启动) node ./bin/www
-
通过浏览器访问
http://localhost:3000
, 如果能正常响应, 说明数据接口服务器启动成功
axios案例模板所需依赖项
- bootstrap: 第三方的css演示库, 主要提供了一些css类选择器, 可以快速对页面进行美化
- swiper: 一个第三方的轮播图插件
npm i swiper@3.4.2 bootstrap@3.3.7 -S
4-token
- token: 服务端返回的一个随机字符串, 包含了一些登录用户的信息, 后端程序可对其进行解密操作
- 作用: 登录凭证, 请求需要登录认证的数据接口的时候, 需要将其发送给数据接口进行登录认证