电商平台项目 Vue day2
1、注意点:
编程式导航路由跳转到当前路由(参数不变), 多次执行会抛出NavigationDuplicated的警告错误? [ 即电商平台多次点击搜索,但搜索内容不变时,控制台会报错 ]
这种异常,对于程序没有任何影响的
为什么会出现这种现象:
由于vue-router最新版本3.5.2,引入了promise,当传递参数多次且重复,会抛出异常,因此出现上面现象,
第一种解决方案:是给push函数,传入相应的成功的回调与失败的回调
goSearch() { // 常用:对象传参 this.$router.push( { name: "xiangqing", params: { keyword: this.keyword }, query: { id: this.keyword.toUpperCase() }, }, //添加下面的成功失败回调(治标不治本方法) () => {}, () => {} ); },
第二种解决方案:直接在router组件里修改push参数,在这个根文件里添加成功失败回调
// 解决header里重复点击push上传时控制面板会飘红的问题,治本 // 直接把header里的修改放到push里,当然,先备份一份先 let originPush = VueRouter.prototype.push // 重写push // location告诉原来的push往哪跳, resolve成功时, reject失败时 VueRouter.prototype.push = function(location, resolve, reject) { // 如果有成功和失败的返回函数,则使用正常push备份的originPush, // 如果没有,则在push备份的originPush上面添加resolve和reject if (resolve && reject) { originPush.call(this, location, resolve, reject) } else { originPush.call(this, location, () => {}, () => {}) } }
言归正传,day1的时候已经把header和footer两个非路由组件搞定,并实现了组件间的跳转,接下来进行home路由组件的制作。
1、将Home组件的静态组件拆分(拆分成7个组件)
总体步骤:
1.1静态页面(样式)
1.2拆分静态组件
1.3发请求获取服务器数据进行展示
1.4开发动态业务
拆分组件:结构+样式+图片资源
(1)、1号组件是三级联动,在多个模块(Home、Search、Detail)中都需要使用,所以把它设成全局组件
---全局组件好处:只需要在 main.js注册一次,可以在项目的任意地方使用
1.1、在Home组件里新建TypeNav文件夹存放‘’商品分类导航的对应文件(html、css/less、img)
1.2、注册全局组件
// main.js中,三级联动组件--因为很多组件都用,所以设置成全局组件
import TypeNav from '@/pages/Home/TypeNav'
// 使用三级联动组件 TypeNav. 2个参数(全局组件的名字,哪一个组件)
Vue.component(TypeNav.name, TypeNav)
1.3、注册好了在home组件中使用
<template>
<div>
<!-- 使用三级联动全局组件 -->
<TypeNav></TypeNav>
</div>
</template>
(2)、相同步骤在Home里拆分其它组件,注意(html、css/less、img)的区分
---注意:有的图片地址不对,用Ctrl+h全局替换
overflow:hidden作用是当元素内的内容溢出的时候使它隐藏溢出的部分,
可用于:超出部分隐藏、清除浮动、解决外边距塌陷(父级元素内部有子元素,如果给子元素添加margin-top样式,那么父级元素也会跟着下来,造成外边距塌陷)
(3)、引入、注册、使用(三件套)其余组件【TypeNav在全局引入了,这些则是局部引入】
商品的内容需要从后台获取,可以用PostMan软件测试一下接口能不能连接后台服务器
---如果服务器返回200,则代表成功,反之失败
二、axios二次封装(静态页面已经搞好,接下来利用axios向服务器发请求获取数据)
使用前先在控制台安装axios:
cnpm install --save axios
2.1:在src下创建api文件夹存放axios,src->api->request.js
request.js是创造axios的实例和axios的拦截器以及发送真正的网络请求的地方
axios具体内容可以查看: axios中文文档
import axios from "axios";
//1、对axios二次封装
const requests = axios.create({
//基础路径,requests发出的请求在端口号后面会跟改baseURl
//baseURL设置为api,所以所有的请求端口后都会携带/api
baseURL:'/api',
//发一个请求如果5s内没响应,那么就请求失败
timeout: 5000,
})
//2、配置请求拦截器, request就是axios
requests.interceptors.request.use(config => {
//config内主要是对请求头Header配置
//比如添加token
return config;
})
//3、配置响应拦截器
requests.interceptors.response.use((res) => {
//成功的回调函数
return res.data;
},(error) => {
//失败的回调函数
console.log("响应失败"+error)
return Promise.reject(new Error('fail'))
})
//4、对外暴露
export default requests;
2.2:接口统一管理
当项目很小时,接口可以放在组件的生命周期中发送请求
当项目很大时,有很多接口,可以把接口放到一起统一管理:
在api文件夹内创建index.js组件,用于存放所有接口,统一管理
//当前模块,API进行统一管理,即对请求接口统一管理
import requests from "@/api/request";
//首页三级分类接口
export const reqCateGoryList = () => {
return requests({
//因为baseURL里自动携带了/api,所以这里不用加上/api。如果那边没有这边就要加上
//method指什么请求
url: '/product/getBaseCategoryList',
method: 'GET'
})
}
在main.js里测试一下是否能够成功请求后台数据:
import {reqCateGoryList} from './api'
//发起请求
reqCateGoryList();
404请求失败,跨域了。
三、跨域问题
两个服务器相互请求,协议、域名、端口号必须一致,不然就是跨域,无法找到对方
解决方法:cors、jsonp、代理(常用)
这里使用代理服务器的方法:(在vue.config.js配置,配置完要重启代码)
module.exports = {
//关闭eslint
lintOnSave: false,
devServer: {
// development server port 8000
//port: 8001,
//代理服务器解决跨域
proxy: {
//但在请求路径中发现/api时跳转到后面的代理服务器
'/api': {
//提供数据的服务器地址
target: 'http://gmall-h5-api.atguigu.cn',
}
},
}
}
代理相关看: webpack官网相关知识解读
网站中的webpack.config.js就是vue.config.js文件。
四、页面加载进度条
可以使用nprogress插件来完成,安装完后可以去package.json里确认
cnpm install -save nprogress
安装好后再api的request的响应拦截器使用。先引入,
//---------------无关的代码这里会先去除--------------
//引入进度条
import nprogress from 'nprogress';
//引入进度条样式,想要修改进度条默认样式可以去下面的css里改
import "nprogress/nprogress.css";
//这里使用进度条插件的2个方法,1、start(进度条开始) 2、done(进度条结束)
//2、配置请求拦截器:在发请求前执行
requests.interceptors.request.use(config => {
//在发请求前开启进度条,的start方法
nprogress.start();
return config;
})
//3、配置相应拦截器:在发请求侯执行
requests.interceptors.response.use((res) => {
//成功的回调函数
//响应成功,关闭进度条,使用done方法
nprogress.done()
return res.data;
},(error) => {
//失败的回调函数
console.log("响应失败"+error)
return Promise.reject(new Error('fail'))
})
//4、对外暴露
export default requests;
简单来说,先导入进度条插件,在页面加载前使用start方法,结束后使用done方法
五、使用Vuex集中式管理数据
cnpm install --save vuex@3.6.2 Vue2要用3版本的,不指定默认安4版本
创建文件夹store -> index.js存放Vuex 【2种形式】(这里不用这种)
//引入
import Vue from 'vue'
import Vuex from 'vuex'
//使用
Vue.use(Vuex)
//对外暴露store的一个实例
export default new Vuex.Store({
state:{},
mutations:{},
actions:{},
getters:{},
)
如果模块很多就要用到模块化开发,把每个模块的数据单独放一个小仓库,再由store引入
设置好Vuex之后需要引入,到mian.js中引入和使用,和router步骤一样
//引入Vuex
import store from './store';
new Vue({
render: h => h(App),
router,
//使用Vuex
store,
}).$mount('#app')
六、动态展示三级联动组件
1、像这种多个地方都需要用到的组件,把它放到components里面(就是那个存放静态组件的那里)
2、在三级联动组件TypeNav里:
export default {
name:'TypeNav',
// 组件挂载,向服务器发送请求获取数据
mounted(){
//通知Vuex发请求,获取数据,并存储于仓库当中,
//这里actions取名叫做categorylist,然后去Vuex里配置actions
this.$store.dispatch('categorylist')
}
3、接收TypeNav的请求,并引入之前封装的api
在store文件夹(Vuex)的小仓库home里引入api接口reqCateGoryList,然后在actions里书写业务
//引入api接口
import { reqCateGoryList } from '@/api/index'
//处理actions的地方,可以书写业务逻辑、处理异步
const actions = {
categorylist() {
let result = reqCateGoryList()
console.log(result);
}
};
咱们这里使用异步来进行,也就是async await
//处理actions的地方,可以书写业务逻辑、处理异步
const actions = {
async categorylist() {
let result = await reqCateGoryList()
console.log(result);
}
};
通过Vuex原理处理数据
//引入api接口
import { reqCateGoryList } from '@/api'
//处理actions的地方,可以书写业务逻辑、处理异步
const actions = {
// {commit} 是结构赋值
async categorylist({ commit }) {
let result = await reqCateGoryList()
if (result.code == 200) {
commit('CATEGORYLIST', result.data);
}
}
};
//修改数据的地方
const mutations = {
CATEGORYLIST(state, categorylist) {
state.categorylist = categorylist
}
};
//存储数据的地方
const state = {
categorylist: []
};
4、到TypeNav接收数据
computed: {
...mapState({
//右侧需要的是一个函数,当使用这个计算属性的时候,右侧会立即执行一次
//注入一个参数state,即Vuex大仓库里的数据
categoryList: (state) => state.home.categoryList,
}),
},
5、数据有了,把html中的静态内容删掉,用v-for生成
至此,动态三级分类搞定