尚品汇前台项目总结

编程入门 行业动态 更新时间:2024-10-11 03:26:09

尚品汇<a href=https://www.elefans.com/category/jswz/34/1770109.html style=前台项目总结"/>

尚品汇前台项目总结

这是我的第一篇个人博客,主要是对我学习前端过程中的一些主记录。由于我在江苏,从2022年过完年,一直到年中,疫情反反复复,又正是大三,马上面临就业难题,我选择了前端。

    从html,css,js基础,webAPI,js进阶,ES6,ajax,node.js一直到最近刚学完尚硅谷的vue2+vue3的全家桶,近期也是刚做完一个尚品汇的项目,作为我第一次做一个相对完整的项目。尚品汇项目是一个电商项目,可以登陆注册账号,搜索查找,产品详情,放大镜,购买商品,加入购物车,下单,提交订单以及支付等模块。用vue-router控制路由的跳转,vuex对仓库中资源进行统一管理,用swiper展示轮播图,element-UI做弹出框,三级联动对分类进行路由跳转,路由之间的转参query和params,还有选中分类或者搜索都会有面包屑处理,综合与价格的排序,手写的分页器作为全局组件,在搜索页面与我的订单中使用,还有在未登录时与登录时的路由守卫判断,个人中心二级路由展示,图片懒加载,用vee-validate插件进行表单验证,路由懒加载。

    这个项目类似的界面,其实没有什么特色,做为培训机构给我们白嫖的练手项目也是非常不错的。在这个项目中,对vue2的使用,还有一些功能实现的原理,以后业务逻辑的实现,是不做项目不打代码练不出来的。在这个过程过我也遇到了非常多的困难,但是这项目比较得普遍,还有跟着老师来的,以及通过百度,很多debug也就相对比较容易一些,只不过还是有困扰的点,我会在之后的博客中详细介绍。

    在做完这个项目之后,我也算是对这阶段的学习告一段落了,在做完这个项目最后,我通过阿里云的学生活动,成功领到了一台服务器,看B站鱼皮大佬的教程部署了wordpress创建了一个很简易的个人博客。还有很多不足希望大佬可以提出来,感谢大佬可以给我的学习过程中提供帮助,我会继续学习,继续更新博客的。

本人博客: 孙浩的个人博客 – 前端学习之路

下面是具体细节问题:

三级联动路由传参:

三级联动

1、先把点击对象拿到,再解构出来(categoryname,categord1id,categord2id,categord3id)自定义属性
2、外层判断categoryname,有则为a链接,内层再判断是哪一级
3、准备好要给真正query参数的对象
let query = {categoryName:categoryname}//表示要查找的是哪个分类
3、判断原本这个有无params参数(可能搜索框有),把要跳转的对象给给真正的

if (this.$route.params) {//有location.params = this.$route.params;location.query = query;this.$router.push(location);
}

但是在跳转路由的时候,若是搜索框里面是空串就会出bug,(外加可能没有点分类,直接搜索)解决:

if (this.$route.query) {let loction = {name: "search",params: { keyword: this.keyword || undefined },//没有则是undefined};loction.query = this.$route.query;this.$router.push(loction);
}


浏览器报错,因为在push的时候是要返回一个promise的所以为了一劳永逸要重写push和replace方法。(当然不写也行,就是飘红)

let originPush = VueRouter.prototype.push;
VueRouter.prototype.push = function (location, resolve, reject) {if (resolve && reject) {//当传了成功与失败的回调时originPush.call(this, location, resolve, reject)} else {originPush.call(this, location, () => { }, () => { })//没有传的话就返回两个 空对象}
}

ngrogress,让请求的时候显示进度条

//请求拦截器:在发请求之前,请求拦截器可以检测到请请发之前做的一些事
requests.interceptors.request.use((config) => {//config:配置对象,里面有请求头//发请求前进度条开始nProgress.start()return config
})//响应拦截器
requests.interceptors.response.use((res) => {//成功的回调:服务器响应数据回来以后,响应拦截器可以检测到//响应成功进度条结束nProgress.done()return res.data;
}, (err) => {return Promise.reject(new Error('faile'));
})

防抖和节流


防抖:在连续快速触发的时候,后面的会重复计时。
节流:在一定范围内重复快速触发,只有一次生效。
用lodash插件实现

mock插件的使用

因为后端没有主页下面的数据,所以我们还像调用接口一样,只不过请求会拦截,从而调用本地资源

src下新建文件夹,放mock中数据,还有模拟写的接口
//先引入mockjs模块
import mockjs from "mockjs";//把JSON数据格式引入进来
// webpack默认对外暴露:图片,JSON
import banner from "./banner.json"
import floor from "./floor.json"//mock数据:第一个参数为请求地址,第二个参数为请求数据
mockjs.mock("/mock/banner", { code: 200, data: banner })
mockjs.mock("/mock/floor", { code: 200, data: floor })
在api文件夹中再新建,再创建一个axios实例,发送请求
const requests = axios.create({baseURL: "/mock",//基础路径,发请求时路径会自动出现/apitimeout: 5000,//代表请求超时时间
})


面包屑

面包屑


面包屑来源有3种:三级联动分类,搜索框,searchSelector子组件中的分类
前两种都只要把相应的categoryName变为undefined,再重新发送请求即可,搜索框多一步,要把input里清空,但搜索框不在同一个组件,所以就要用到兄弟间传参,选用$bus,再第三种,又分售卖的品牌和属性,只要把数据改了,再发一遍请求即可
排序(综合与价格)
先定义两个变量获取最开始是综合还是价格,升序还是降序。再定义一个新的用于再发请求,若点的是当前的元素,再排序反转,若点的是另一个,则默认为降序,然后把数据更新再发请求。

changeOrder(flag) {//1为综合,2为价格let originFlag = this.searchParams.order.split(":")[0]; //最开始是综合还是价格let originSort = this.searchParams.order.split(":")[1]; //最开始的升序还是降序let newOrder = "";//点的是当前的元素,再就是排序反转if (flag === originFlag) {newOrder = `${originFlag}:${originSort == "desc" ? "asc" : "desc"}`;} else {//点的不是当前元素,再转到目标元素且,默认desc降序newOrder = `${flag}:${"desc"}`;}//将新的order赋给searchParams并再次发请求this.searchParams.order = newOrder;this.getData();
},

分页器

分页器


点哪个把哪一页的编号,更新数据再发请求
重点是手写分页器
分3个部分
第一部分是:1和……
第二部分是:连续的页码
第三部分是:……和最后一页的编号
由于后端没有直接返回多少页,所以要计算。
主要是第二部分,中间的连续页。

分页器特殊情况,在前5后5之内,连续页为5(连续的页数可以自定义)

startNumAndEndNum() {//先定义两个变量存储起始数字和结束数字let start = 0,end = 0;//连续的页码至少要有5页//不正常现象(总页数没有连续的页码多)if (this.continues > this.totalPage) {start = 1;end = this.totalPage;} else {start = this.pageNo - parseInt(this.continues / 2);end = this.pageNo + parseInt(this.continues / 2);//若是算出来start可能会少于1if (start < 1) {start = 1;end = this.continues;}//若end大于了最大页数if (end > this.totalPage) {end = this.totalPage;start = this.totalPage - this.continues + 1;}}return { start, end };
},


返回一个对象,限定了连续的开始和结束(eg:若连续页为5,当前页为6,再连续页为4,5,6,7,8)对称
但要是算出来开始小于了1再把开始限定为1,算出来结束大于了最大页,再把结束限定为最大页,且开始再变为了最大页-连续页+1
点击进入详情页路由时,会默认到最底部,解决:
在配置路由的时候加scrollBehavior配置项

let router = new VueRouter({routes,//让路由跳转后,自动滚轮在最上方scrollBehavior() {return { y: 0 }}
})


放大镜

放大镜


放大镜效果本来在pink老师就练过一次,这里再练一次,且单独拿出来做为子组件。
首先绑定一个鼠标悬浮事件,出现一个遮罩层加一个大图,但是这个大图的显示出的大小还是一样的,只不过放大了2倍,然后就是移动的时候对应同时移动了
用$refs获取DOM,第一让遮罩层跟着鼠标移动,第二相对应放大层的背景图也要移动,但是鼠标向右移时,背景图是向左移2倍,第三约束遮罩层的范围

handler(e) {let mask = this.$refs.mask; //获取遮罩层DOMlet big = this.$refs.big; //获取放大层DOM//获取遮罩层左上角的坐标:鼠标的坐标-0.5*遮罩层冠宽或高let left = e.offsetX - mask.offsetWidth / 2;let top = e.offsetY - mask.offsetHeight / 2;// 约束遮罩层的范围if (left <= 0) {left = 0;} else if (left >= mask.offsetWidth) {left = mask.offsetWidth;}if (top <= 0) {top = 0;} else if (top >= mask.offsetHeight) {top = mask.offsetHeight;}mask.style.left = left + "px";mask.style.top = top + "px";big.style.left = -2 * left + "px";big.style.top = -2 * top + "px";
},

uuid(之前禹哥教过用这个的轻量版nanoid)


因为要进购物车,但是未登录的话,后端是不会返回数据的,所以要用uuid生成一个token
新建一个utils,再建一个js文件,判断是还本地已经有了,没有就生成,存在本地存储的同时还要把数据返回
这里把两个方法再单独放一个模块,作为对浏览器中本地存储的操作

import { v4 as uuidv4 } from 'uuid'
export const getUUID = () => {//先从本地获取uuid是否有let uuid_token = localStorage.getItem('UUIDTOKEN')//如果没有if (!uuid_token) {//生成游客临时身份uuid_token = uuidv4();localStorage.setItem('UUIDTOKEN', uuid_token)}//返回id,没有return 再返回的是undefinedreturn uuid_token;
}

购物车中全选


全选分两部分:第一部分是点击全选复选框,让所有的都选上,只需要把数据中的isChecked属性都变为1即可

async updataAllCartChecked(e) {try {let isChecked = e.target.checked ? "1" : "0";this.isAllChecked = e.target.checked;await this.$store.dispatch("updataAllCartIsChecked", isChecked);this.getData();} catch (error) {alert(error.message);}},


第二部分是当点击其余小项时判断,若当时状态全部的小项全勾上的时候,则把全选给勾上

let flag = true;//遍历的是数组所以直接用in的话,v就是键名,数组键名为索引//遍历判断若全是勾选状态再把全选也勾上for (let v of this.cartInfoList) {if (!v.isChecked) {flag = false;}}this.isAllChecked = flag;this.getData();} catch (error) {alert(error.message);}
},

导航守卫


因为商城项目是要有用户,然后访问对应购物车等每个用户私有的数据的,所以在登录或未登录的时候不能跳转到一些特定的路由去,所以就要用到路由导航守卫了。
当用户未登录:
要是去订单,支付,订单详情页面都把路由跳转到登录页面,为了登录之后可以直接访问原本要去的路由,则可以用params参数转到登录页方便跳转。
当用户登录了:
要去登录或者注册页,是不行的,直接去往主页(其实这个需求可以不要)
还有就是因为token是存在浏览器本地的,而name是存在仓库的,所以要判断有token但是没有用户名,有就放行,没有则再获取一下用户信息,但这里要判断一下成功与失败,若是失败的话再要跳转到登录界面,因为你即便有token,但是长时间不登录,后端的数据会更新,从而token会失效

大概如下图,来自CSDN的@毛毛虫鸣鸣

个人中心(二级路由,路由懒加载,路由重定位)

{name: 'center',path: '/center',component: () => import('@/pages/Center'),//路由懒加载children: [{path: 'myorder',component: () => import('@/pages/Center/myOrder')}, {path: 'grouporder',component: () => import('@/pages/Center/groupOrder')}, , {path: '',//当路径默认的时候(完全的路径的/center/)redirect: '/center/myorder'//重定向到myorder路由}]},

想要去支付页面,一定要从订单来才行,所以要用独享路由守卫

{name: 'pay',path: '/pay',component: () => import('@/pages/Pay'),beforeEnter: (to, from, next) => {//只有是从trade订单来的才能进入pay支付路由if (from.path == '/trade') {next()} else {next(false)}}
},

使用图片懒加载(用vue-lazyload插件)

图片懒加载

//引入插件(图片懒加载)
import VueLazyload from 'vue-lazyload'
//引入懒加载的图片
import loadimage from '@/assets/images/111.jpg'
//注册图片懒加载插件
Vue.use(VueLazyload, {loading: loadimage,
})

使用plugins表单验证插件(其实用element-UI也行)

eg:手机号 :

<div class="content"><label>手机号:</label><inputplaceholder="请输入你的手机号"v-model="phone"name="phone"v-validate="{ required: true, regex: /^1\d{10}$/ }"        //以1开始,后面10个数字:class="{ invalid: errors.has('phone') }"                         //否则提示/><span class="error-msg">{{ errors.first("phone") }}</span>
</div>

为了方便也是全局引入

import "@/plugins/validate"

再新建一个文件使用插件

//vee-validate插件:表单验证区域
import Vue from 'vue'
import VeeValidate from 'vee-validate';
//中文提示
import zh_CN from "vee-validate/dist/locale/zh_CN"
//使用注册
Vue.use(VeeValidate)//表单验证
VeeValidate.Validator.localize("zh_CN", {messages: {...zh_CN.messages,is: (field) => `${field}必须与密码相同`,//修改内置规则的message,让确认密码与密码相同},attributes: {phone: "手机号",code: "验证码",password: "密码",password1: "确认密码",agree: "协议"}
})//自定义校验规则,必须要打勾才行
VeeValidate.Validator.extend("tongyi", {validate: (value) => {return value},getMessage: (field) => field + "必须同意"
})

大概的项目就是这样了,项目配置,因为现在默认是vue3了,所以像脚手架一定要安装对应的版本,最新本是不能向下兼容的。还有不是所有路由中,footer组件都要显示的所以要加一个属性,来判断是否显示,路由中不能直接绑定自定义属性所以要在meta配置项下定义一个show来判断。还有就是因为要解决跨域问题,这次项目通过代理的方法解决,在vue.confing.js中加入

devServer: {proxy: {'/api': {target: '',//访问的接口地址}}
}



    还有因为要请求,所以就要涉及到异步,就要用到async与await配合使用,若要判断成功还是失败,还要用到try……catch()
再一个问题就是在切换组件的时候,因为三级联动组件不仅在home路由中使用,在别的也要,所以要注册为全局组件,还有就是切换的时候会销毁组件,但是在一些路由中要用到,为了不重复得请求接口,只发一次请求,就把请求放在App.vue中mounted中(对仓库的操作)

    整个项目完全,差不多不到两周的时间,其中学到了很多东西,编程还是要打代码才可以,很多问题就是在实践中发现的,所以我打算再做一个后台项目,加深对vue2的使用,之后再学小程序,再深入原码。不得不说因为这个项目是培训机构上的课,不是专门拿出来当做网上的白嫖福利,所以开发周期太长了,不过好在非常得细。

更多推荐

尚品汇前台项目总结

本文发布于:2024-03-15 05:05:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1738162.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:前台   项目   尚品汇

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!