尚品汇项目难点及解决
v-router重写push、replace方法问题描述:当页面再次进入同一个路由地址时,控制台报错解决方法:修改vue-router的配置文件,也就是router/index.js文件//重写VueRouter.prototype身上的push方法了VueRouter.prototype.push = function(location, resolve, reject) {//第一个形参:路由
v-router重写push、replace方法
问题描述:当页面再次进入同一个路由地址时,控制台报错
解决方法:修改vue-router的配置文件,也就是router/index.js文件
//重写VueRouter.prototype身上的push方法了
VueRouter.prototype.push = function(location, resolve, reject) {
//第一个形参:路由跳转的配置对象(query|params)
//第二个参数:undefined|箭头函数(成功的回调)
//第三个参数:undefined|箭头函数(失败的回调)
if (resolve && reject) {
//push方法传递第二个参数|第三个参数(箭头函数)
//originPush:利用call修改上下文,变为(路由组件.$router)这个对象,第二参数:配置对象、第三、第四个参数:成功和失败回调函数
originPush.call(this, location, resolve, reject);
} else {
//push方法没有产地第二个参数|第三个参数
originPush.call(
this,
location,
() => {},
() => {}
);
}
};
//重写VueRouter.prototype身上的replace方法了
VueRouter.prototype.replace = function(location, resolve, reject) {
if (resolve && reject) {
originReplace.call(this, location, resolve, reject);
} else {
originReplace.call(
this,
location,
() => {},
() => {}
);
}
};
三级联动路由跳转的优化
三级联动路由如下图所示:
点击’电子书‘后跳转的页面如下:
问题分析:
1、由于三级分类都是<a>
标签,所以要实现路由跳转,最简单的方式就是将a标签换成
<router-link to="/search">
,但是由于服务器的数据返回,循环语句的执行,可能在一瞬间,要加载几千个router-link,router-link是组件,组件需要创建,所以很耗费内存,最终会出现卡顿现象。
2、所以采用编程式导航来实现,编程式导航需要绑定事件,如果将事件绑定在每个<a>
标签上,虽然不会出现卡顿现象了,但是当数据返回时,每次循环会就会导致有几千个回调函数,所以可以利用事件委派解决这个问题。
3、最好的解决方案是编程式导航结合事件委派。但是利用事件委派存在两个问题需要解决:
3.1、全部的子节点的事件都委派给了父节点,但是我们需要的是点击一定是a标签,如何区别a标签和其它标签?
在a标签上定义自定义事件data-categoryName,后面用dataset就能获取自定义属性及属性值;
3.2如何获取参数【1、2、3级分类的产品的名字、id】?
在1,2,3级分类上定义自定义属性data-category1Id、data-category2Id、data-category3Id,就能区分了
三级联动TypeNav的代码如下:
template内
<!-- 将点击事件goSearch放在父元素上 -->
<div class="all-sort-list2" @click="goSearch">
<div class="item" v-for="(c1,index) in categoryList" :key = "c1.categoryId">
<h3>
<!-- 为了区别a标签和其它标签,在a标签上定义自定义事件data-categoryName,后面用dataset就能获取;1,2,3级区分同理 -->
<a :data-categoryName="c1.categoryName" :data-category1Id="c1.categoryId" >{{c1.categoryName}}</a>
</h3>
<div class="item-list clearfix">
<div class="subitem" v-for="(c2,index) in c1.categoryChild" :key="c2.categoryId">
<dl class="fore">
<dt>
<a :data-categoryName="c2.categoryName" :data-category2Id="c2.categoryId" >{{c2.categoryName}}</a>
<!-- 声明式导航 --!>
<!-- <router-link to="/search">{{c2.categoryName}}</router-link> -->
</dt>
<dd>
<em v-for="(c3,index) in c2.categoryChild" :key="c3.categoryId">
<a :data-categoryName="c3.categoryName" :data-category2Id="c3.categoryId" >{{c3.categoryName}}</a>
</em>
</dd>
</dl>
</div>
</div>
</div>
</div>
script内
methods:{
goSearch(event){
//利用编程式导航和事件委派
//事件委派会出现一些问题:1.全部的子节点的事件都委派给了父节点,但是我们需要的是点击一定是a标签
let element = event.target;
//dataset可以获取自定义属性与属性值(解构赋值)
let {categoryname,category1id,category2id,category3id} = element.dataset;
console.log(element.dataset)
// 如果标签身上有categoryname那一定是a标签
if(categoryname){
// alert(123);
//整理路由跳转的参数
let location = {name:"search"};
let query = { categoryName:categoryname }
// 2.如何获取参数【1、2、3级分类的产品的名字、id】
if(category1id){
query.category1Id = category1id
}else if(category2id){
query.category2Id = category2id
}else{
query.category3Id = category3id
}
location.query = query;
this.$router.push(location);
// alert(123)
}
},
跨域问题
/api/request.js
1、对axios进行二次封装
//对axios进行二次封装
import axios from "axios";
//引入进度条
import nprogress from "nprogress";
//引入进度条的样式
import "nprogress/nprogress.css"
console.log(nprogress);
//利用axios对象的方法create,创建一个axios实例
const requests = axios.create({
baseURL:"/api",
//请求超时时间为5s
timeout:5000,
});
//请求拦截器:再发请求之前,请求拦截器可以监测到,可以在请求发出之前走一些事情
requests.interceptors.request.use((config)=>{
//config:配置对象,对象里面有个属性很重要,headers请求头
//进度条开始动
nprogress.start();
return config;
})
//响应拦截器
requests.interceptors.response.use((res)=>{
//成功的回调函数:服务器响应数据回来以后,响应拦截器可以检测到,做一些事情
//进度条结束
nprogress.done();
return res.data;
},(error)=>{
//响应失败的回调函数
return Promise.reject(new Error('faile'));
})
//对外暴露
export default requests;
2、对接口进行统一管理
/api/index.js
//当前这个模块:对API进行统一管理
import requests from "./request";
//三级联动接口
// /api/product/getBaseCategoryList get 无参数
export const reqCategoryList = ()=>{
//发请求 axios发请求,返回结果是promise对象
//会出现跨域问题:协议、域名、端口号不同就会出现跨域问题
//http://39.98.123.211
//http://localhost:8080
//解决方法:JSONP、CROS、代理(在config.js配置文件修改)
return requests({url:'/product/getBaseCategoryList',method:"get"})
}
解决跨域问题方法一:代理跨域
在服务器和浏览器中间设置一个代理服务器,解决跨域问题
vue.config.js
module.exports = {
//关闭eslint校验工具
lintOnSave:false,
//代理跨域
devServer:{
proxy: {
"/api": {
target: "http://39.98.123.211",
//路径不需要重写,因为所有的接口都有/api
// pathRewrite: {"^/api" : ""}
},
},
},
}
轮播图解决浏览器异步数据及swiper问题
问题分析:
swiper插件完成轮播图需要两件事:首先将DOM结构渲染完成,然后再创建一个swiper实例。
但是我们从浏览器获取数据是异步的(获取数据也在mounted中),所以不能保证创建swiper实例时(在mounted生命周期函数内创建这个实例)就将DOM结构完成了,要解决这个问题,有以下三种方法:
-
1、update
当有其他数据时,其它数据进行更新,但轮播图的数据不更新时,都会再创建一次swiper实例然后再创建轮播图,所以这个方法不是特别好。 -
2、延时器
延时1秒,轮播图的功能才可以实现,此方法可行但也不是很完美。 -
3、watch+nextTick
如果只有watch,只能保证bannerList数据已经存入到仓库里了,但是不能确定v-for执行完毕,v-for执行完了才能保证DOM结构完成,所以需要结合nextTick来完成。
nextTick
更多推荐
所有评论(0)