本节课最大收获
组件之间的通信,使用vuex
- eventBus
- vuex
- 父子组件通信prop emit
axios的封装办法 mock产生前端数据与接口 token的设置
样式less的使用
less官方网站 less快速入门 less优势:
-
使用嵌套代替层叠或与层叠结合使用的能力 -
书写代码更简洁,模仿了HTML组织结构
less下载: 版本号去npm官网查询npm官网
npm i less@4.1.2
npm i less-loader@6.0.0 // less的解析器
路由的重定向
路由为‘./’的时候,被重定向到‘./home’,直接跳转到home页面 点击相同路由时报错的解决 因为路由router限制了不能重复跳转到一个页面,所以会报错 解决办法:增加判断条件,当将要跳转的页面与当前页面路由不相同时,才会跳转
if(this.$route.path != item.path && !(this.$route.path === '/home' && item.path === '/')) {
this.$router.push(item.path);
}
vuex
官方文档 核心概念
-
state:状态管理树,所有状态都写在这里 -
getters:可以认为是store中的计算属性 -
mutations:修改state的方法(唯一的修改方法),需要是同步的过程 -
actions:处理异步的一个方法,先提交给mutation -
modules:由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象就有可能变得相当臃肿。为解决以上为题,vuex允许将store分割成模块(module),每个模块拥有自己的state,mutation,action,gerrer,甚至是嵌套子模块–从上至下进行同样方式的分割
vuex的使用
1.下载vuex,确保版本的正确性
npm i vuex@3.6.2
2.引入vuex,并在vue中全局注入
3.创建vuex的实例–store,并对外暴露
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
4.创建一个新的vuex模块tab.js,并对外暴露
export default {
state: {
},
mutations: {
}
}
在index.js中引入并登记模块
import tab from './tab'
export default new Vuex.Store({
modules: {
tab
}
})
5.在main.js中引入
import store from './store'
并放到vue实例上
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
目前就完成了vuex的创建与挂载,项目结构为 main.js的内容为 index.js的内容为
tab.js的内容为
6.在需要使用共有变量的页面中使用
state的使用:
(1)在computed计算属性中去获取state模块tab中的参数isCollapse,并存储在变量isCollapse中
<el-menu
default-active="1-4-1"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
:collapse="isCollapseData"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
>
computed: {
isCollapseData() {
return this.$store.state.tab.isCollapse;
}
},
(2)使用vuex辅助函数mapState
引入辅助函数mapState
import { mapState } from 'vuex'
在计算属性中使用,由于该函数范围值是对象,所以需要解构才能拿到数据,使用扩展运算符 ‘…’ 进行解构(ES6语法)
computed: {
...mapState({
tags: state => state.tab.tabsList
})
},
mutation的使用:
(1)执行mutation中的函数collapseMenu,在methods中写一个函数,通过调用函数来执行
<el-button @click="handleMenu" icon="el-icon-menu" size="mini"></el-button>
handleMenu() {
this.$store.commit('collapseMenu');
}
(2)使用vuex辅助函数mapMutations
引入辅助函数mapMutations
import { mapMutations } from 'vuex'
在methods中引入mutation的函数closeTag
...mapMutations(['closeTag']),
在需要使用时,直接使用引入的mutation函数,使用方法和其他methods的函数使用方法一致
this.closeTag(item);
浏览器大小自适应
采用element-ui的栅格布局,实现自适应(本质是百分比)
<el-row>
<el-col :span="12"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="12"><div class="grid-content bg-purple-light"></div></el-col>
</el-row>
axios
axios自身封装很多好用的API,可以直接调用,如get和post axios安装
npm install axios
由于接口数目较多,重复使用axios的一个函数代码量过多,所以采用封装的办法,先把axios进行封装,再使用,详见axios中文文档 axios基本信息 拦截器:如在axios请求头里面加token,可以写在请求拦截器中 响应拦截器:1.服务器端回传消息时,在拿到消息后,可以进行一些操作。如判断状态码是否非200;2.处理业务,后端返回的code,可以判断一下业务状态,如果非正常状态,可以统一处理。 axios封装 新建utils文件夹,放置工具类、小数处理封装等,axios封装代码写在request.js中 axios的请求配置选项,这些是创建请求时可以用的配置选项。只有 url 是必需的。如果没有指定 method,请求将默认使用 GET 方法。请求配置详情
import axios from "axios";
const http = axios.create({
baseURL: '/api',
timeout: 10000,
})
export default http
设置拦截器:(写在上述代码下面,同一文件夹中)
http.interceptors.request.use(function (config) {
return config;
}, function (error) {
return Promise.reject(error);
});
http.interceptors.response.use(function (response) {
return response;
}, function (error) {
return Promise.reject(error);
});
src目录下新建api文件夹,用来保存接口
import http from "@/utils/request";
export const getData = () => {
return http.get('/home/getData')
}
mock前端数据模拟
mock官网,前端用来模拟后端接口的一个库,通过拦截前端发器的请求,自己定义一些返回数据。自己与自己的数据交互。 安装
npm install mockjs
mock函数,实际上是一个拦截器 保存在api目录下的mock.js 1.使用mock函数,第一个参数定义请求拦截地址,请求拦截地址使用域名(即IP)后面的地址,可以写绝对路径,也可以使用正则表达式的路径。第二个参数定义请求类型,可以是get或者post等,get可以省略不写。第三个参数是一个函数,定义拦截到请求后的处理逻辑。
import Mock from 'mockjs'
Mock.mock('/api/home/getData', function(){
console.log('已拦截!');
})
2.在main.js中引入
import './api/mock'
mock的封装
新建文件夹,将数据分开保存 1.在home.js中写模拟数据的函数 2.在mock.js中引入home,并定义mock请求拦截
import Mock from 'mockjs'
import homeApi from './mockServeData/home'
Mock.mock('/api/home/getData', homeApi.getStatisticalData)
echarts使用
官网示例 安装echarts,一定要跟具体的版本号
npm i echarts@5.1.2
1.在需要使用页面的script中引入
import * as echarts from 'echarts'
echarts初始化放在mounted生命周期中,因为需要获取dom相关内容,而在mounted中dom刚好初始化完成。因为需要使用接口数据去初始化图表,所以以下代码写在接口调用函数里面。 2.使用ref获取dom并初始化
<div ref="echarts1" style="height: 280px"></div>
const echarts1 = echarts.init(this.$refs.echarts1);
3.指定图标的配置项和数据
var echarts1Option = {};
处理接口返回的数据
const { orderData } = data.data;
const xAxis = Object.keys(orderData.data[0]);
console.log("orderData.data[0] = ", orderData.data[0]);
console.log("xAxis = ", xAxis);
const xAxisData = {
data: xAxis
};
echarts1Option.xAxis = xAxisData;
echarts1Option.yAxis = {};
echarts1Option.legend = xAxisData;
echarts1Option.series = []
xAxis.forEach(key => {
echarts1Option.series.push({
name: key,
data: orderData.data.map(item => item[key]),
type: 'line'
})
});
Tips: Object.keys() 方法属于ES6语法,可以获取对象的枚举值,将对象中的数据提取到列表中
主要用于将对象中的数据提取出来,放在数组中存储
const xAxis = Object.keys(orderData.data[0]);
4.根据配置项和数据显示图表
echarts1.setOption(echarts1Option);
深拷贝与浅拷贝
参考这篇笔记 浅拷贝和深拷贝都能创建出一个新的对象,但浅拷贝在复制引用类型时,只复制引用地址,新旧对象还是共享同一块内存,修改对象属性会影响原对象;而深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
- 浅拷贝常见方法
Object.assign() 扩展运算符 Array.concat() Array.slice() - 深拷贝常见方法
_.cloneDeep() JSON.stringify() 手写递归方法
项目中的深拷贝
JSON.stringify 方法将某个对象转换成 JSON 字符串形式 JSON.parse 方法将数据转换为 JavaScript 对象
this.form = JSON.parse(JSON.stringify(row));
扩展运算符
… 扩展运算符能将可迭代对象转换为逗号分隔的参数系列 参考这篇笔记
项目中的使用
getUser({ params: {...this.userForm, ...this.pageData}}).then(({ data }) => {
this.tableData = data.list;
this.total = data.count || 0;
});
token
前端输入用户名密码后,提交到后端,由后端生成一个token给前端,之后前端在调用接口时,将token添加到header中进行请求,后端判断token是否正确,正确的话才返回对应信息。总之就是为了进行身份校验。 对于跨页面判断token是否存在(也就是页面间的通信),需要使用cookie进行存储(也可以用localstorage存储,区别在这里),cookie下载方式:
npm i js-cookie@3.0.1
cookie引入
import Cookie from 'js-cookie'
cookie使用:
submit(){
const token = Mock.Random.guid();
Cookie.set('token', token);
}
当跳转到其他页面时,需要判断是否有cookie,如果没有的话就需要会跳到登录页面,此时需要用到导航守卫。
导航守卫
官方教程 全局导航守卫:当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
})
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
项目应用实例
写在main.js里面,当已经完成了router文件夹中index.js的引入以及router的注册之后,给router添加钩子beforeEach,即全局前置导航守卫,代码如下:
router.beforeEach((to, from, next) => {
const token = Cookie.get('token');
if(!token && to.name !== 'login') {
next({ name: 'login' })
} else if(token && to.name === 'login'){
next({ name: 'home' })
} else {
next()
}
})
|