2024年最新微信小程序实战(仿小米商城)(2),双非本科字节跳动前端面试题分享

最后

编程基础的初级开发者,计算机科学专业的学生,以及平时没怎么利用过数据结构与算法的开发人员希望复习这些概念为下次技术面试做准备。或者想学习一些计算机科学的基本概念,以优化代码,提高编程技能。这份笔记都是可以作为参考的。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

名不虚传!字节技术官甩出的"保姆级"数据结构与算法笔记太香了

三、发现页

页面结构分析:

里面展示了一些商品宣传视频(当时还是不太想切太多的页面😂)这里用弹性布局+video组件就搞定了。这里是文档

四、商品详情页

页面结构分析:

商品详情顶部由一个swiper组成,中间部分由一些cells组成(weui)点击这里快速查看

底部是商品的概述及参数配置两部分组成,这个还是比较简单的, 给两个元素分别绑定一个布尔值来控制谁显示谁隐藏。

当然,要使用weui必须引入它的样式文件,我们在app.wxss里引入,然后全局都可以使用了

@import “./lib/weui.wxss”;

嗯,weui的官网和github地址自然少不了。weui官网 、weui github官方文档,在github上阅读代码是一个非常有效的学习方式,但是文件夹嵌套太深找个文件也不容易,这里奉上github阅读神器

使用到的weui:

请容许我贴一段weui抄来的结构

{{goods.header}}

{{goods.description}}

{{goods.meta}}

商品详情页的显示

逻辑分析:

每个商品通过id来跳转到相应的详情页,但是这个id会在哪里呢因为先这个详情页是通过一个个商品来打开的,所以在商品详情页加载时,可以在 onLoad 中获取打开当前页面所调用的 query 参数(是条json数据),因为在showDetail里只用了id来跳转,所以options只有id属性

onLoad: function (options) {

console.log(options); //{id:“4”}

const id=options.id; //获取options里的id

const goods=app.globalData.goodsDetail.filter(item=>{

return item.id==id; //通过id来筛选显示对应的商品

});

this.setData({

goods:goods[0] //因为id是唯一的,所以上面筛选出来的数组只有一条数据,这条数据就是要显示的商品数据

});

}

商品图片预览实现

微信小程序为我们提供了wx.previewImage()方法来实现图片的预览,实现方法如下:

previewImage(e){

const index=e.currentTarget.dataset.index; //获取swiper里的图片的下标

const slide=this.data.goods.goods_slides; //获取商品轮播图

const imgList=[]; //定义一个数组来存放轮播图的url

slide.map(item=>{

imgList.push(item.slide_url); //用js的map方法把图片的url地址取出来放到数组里

});

wx.previewImage({

current: imgList[index], // 当前显示图片的链接,不填则默认为 urls 的第一张

urls: imgList

})

}

五、商品属性选择

页面结构:整个商品属性页的结构是由一些cells组成,所以用weui最合适(插一段:原生的radio真的是很丑,不过weui对它做了改进)

一开始想有weui就简单多了,直接用form表单的bindsubmit处理就可以了,奈何在weui里使用bindsubmit,取不到radio的值,折腾了很久,还是取不到,但是换成原生的radio竟可以取到!!

这个不行,那就换一种吧,用weui radiogroup里的bindchange事件吧,虽然繁琐了些,但是还是能解决问题的。。

话不多说,看代码(感觉写了一些很累赘的代码。。)

selectVersion(e) {

const version = e.detail.value;

const memory = version.split(“,”)[0];

const price = version.split(“,”)[1];

wx.setStorageSync(‘memory’, memory);

wx.setStorageSync(‘price’, price);

this.setData({

memory,

price

});

},

selectColor(e) {

let color = e.detail.value;

let cover_img=this.data.goods_attrSelect[0].goods_slides[0].slide_url;

wx.setStorageSync(‘color’, color);

wx.setStorageSync(‘cover’, cover_img);

this.setData({

color,

cover_img

});

},

colorHasSelected(e) {

const curcIndex = e.currentTarget.dataset.index ? e.currentTarget.dataset.index : 0;

console.log(curcIndex);

this.setData({

curcIndex

});

},

versionHasSelected(e) {

const curvIndex = e.currentTarget.dataset.index ? e.currentTarget.dataset.index : 0;

console.log(curvIndex);

this.setData({

curvIndex

});

}

对应商品的属性页的跳转

逻辑分析:在商品详情页中,通过当前商品的id跳转

toSelect(e){

const id=e.currentTarget.dataset.id;

wx.navigateTo({

url:../selectGoods/selectGoods?id=${id}

});

}

在商品的属性选择页里,同样是通过id筛选显示不同商品的属性选择信息

onLoad: function (options) {

const id = options.id;

console.log(id);

const goods_attrSelect = app.globalData.goodsDetail.filter(item => {

return item.id == id;

});

}

商品属性的联动选择

既然是商品,没有属性选择怎么行呢?兴致一来二话不说就是写。但是这里有一个难点:用户的选择多样性,难道你会把所有用户可能做出的选择都列出来吗?天哪,商品这么多,这是要累死我吗?no,no,no,这种方法不可取。哪还有什么解决办法呢?当时一想到的就是用数据缓存,嗯,这种方法可行,但是用缓存存取用户选择的值的话,这里有一个很大的问题:微信小程序里的数据缓存将data存储在本地缓存中指定的key中,会覆盖掉原来该key对应的内容,无论是wx.setStorage(异步接口)还是wx.setStorageSync(同步接口),这样的话,无论用户选择了多少个商品,只要key值一样,缓存数据永远只有一条!!!我此时的内心是痛苦的。

有什么方法能让数据缓存不覆盖原来的值,而是加上去?说实话,这里卡了我好久。废话不多说,直接上代码

submit(e) {

const pre_item = wx.getStorageSync(‘attr_item’);

const temp = {

‘goods_name’: wx.getStorageSync(‘goods_name’),

‘memory’: wx.getStorageSync(‘memory’),

‘price’: wx.getStorageSync(‘price’),

‘color’: wx.getStorageSync(‘color’),

‘select_num’: wx.getStorageSync(‘select_num’),

‘cover’: wx.getStorageSync(‘cover’),

‘selected’: false,

‘isTouchMove’: false

}

wx.setStorageSync(‘attr_item’, [temp, …pre_item]); //把获取到的pre_item和temp的数据缓存存入attr_item

wx.showToast({

title: ‘已加入购物车’,

icon: ‘success’,

duration: 3000,

success() {

setTimeout(() => {

wx.navigateBack({

url: “…/goods/show”

});

}, 1000)

}

});

}

商品数量的加减操作

实现思路:分别绑定一个事件来操作商品数量的加减,最后将用户选择的数量设置到数据缓存里。

实现代码:

data: {

select_num: 1 //默认选择为数量为1

},

minusCount(e) { //用户减操作

let select_num = this.data.select_num;

select_num–;

if (select_num < 1) {

return;

}

this.setData({

select_num

});

wx.setStorageSync(‘select_num’, select_num);

},

addCount(e) { //用户加操作

let select_num = this.data.select_num;

select_num++;

if (select_num > 5) {

return;

}

this.setData({

select_num

});

wx.setStorageSync(‘select_num’, select_num);

}

六、购物车操作

页面结构分析:购物车列表用一个弹性布局就搞定。底部的操作栏用固定定位 + 弹性布局就搞定。

购物车还是空的

到小米商城逛逛

<icon type=“{{item.selected?‘success’:‘circle’}}” class=“” color=“#ff6700” size=“20” bindtap=“selectList” data-index=“{{index}}”

/>

<image src=“{{item.cover}}”

mode=“aspectFill” />

{{item.goods_name}} {{item.memory}}

{{item.color}}

{{item.select_num}}×

{{item.price}}

删除

全选

合计:

{{totalPrice}}元

结算

底部操作栏样式

.user-operation{

width: 100%;

height: 100rpx;

line-height: 100rpx;

display: flex;

flex-direction: row;

justify-content: space-between;

align-items: center;

position: fixed;

left: 0;

bottom: 0;

}

.select-all,.total-price,.btn-primary.pay{

flex: 1; //三个盒子等分所有设备宽度

font-size: 12pt;

text-align: center;

}

加入购物车操作

逻辑分析:之前解决数据缓存问题,是为加入购物车功能做铺垫。在商品属性的级联选择中,已经获得了用户的所有要加入购物车的数据,这时候,把数据取出来在绑定到购物车页面上就可以了。

实现代码:

data: {

cart_list: [], //初始化一个空数组用来存放购物车列表

},

goIndex() { //如果购物车为空,则让用户去首页

wx.switchTab({

url: “…/index/index”

})

},

onShow: function () {

const attr_item = wx.getStorageSync(‘attr_item’); //获取数据缓存里将要加入购物车的数据

let cart_list = this.data.cart_list;

cart_list = […attr_item]; //把缓存里的数据加到购物车列表里

const select_num = cart_list.map(item => { //获取用户每次选择的数量

return item.select_num;

})

let goods_sum=select_num.reduce(function(prev,cur){

return prev+cur; //用es6的reduce()方法把用户每次选择的数量相加

});

wx.setStorageSync(‘goods_sum’, goods_sum); //再次存入缓存

this.setData({ //更新购物车列表

cart_list

});

}

购物车全选、反选、计算总价功能

这是一个很经典的问题,凡事涉及到购物车的操作,这个功能都是少不了的。

data: {

cart_list: [],

totalPrice: 0,

},

selectList(e) {

let selectAllStatus = this.data.selectAllStatus;

const index = e.currentTarget.dataset.index;

let cart_list = this.data.cart_list;

// console.log(cart_list[index].selected);

const selected = cart_list[index].selected;

cart_list[index].selected = !selected;

console.log(selected);

//购物车列表里的条目只要有一个取消,全选就取消

const symbol = cart_list.some(cart => { //这里用es6的some()函数

return cart.selected === false;

});

if (symbol) { //如果找到false,全选就取消

this.data.selectAllStatus = false;

} else {

this.data.selectAllStatus = true;

}

this.setData({ //更新数据

cart_list,

selectAllStatus: this.data.selectAllStatus

});

this.getTotalPrice();

},

getTotalPrice() { //定义一个计算总价的方法

let cart_list = this.data.cart_list;

let totalPrice = 0;

for (let i = 0; i < cart_list.length; i++) {

if (cart_list[i].selected) {

totalPrice += parseInt(cart_list[i].select_num) * parseInt(cart_list[i].price); //注意这里要用parseInt()把数量和价格取出来

}

}

//更新总价

this.setData({

totalPrice

});

},

selectAll(e) {

let selectAllStatus = this.data.selectAllStatus;

selectAllStatus = !selectAllStatus;

let cart_list = this.data.cart_list;

for (let i = 0; i < cart_list.length; i++) {

cart_list[i].selected = selectAllStatus; //全选为true,则所有购物车列表为true,全选为false,则所有购物车列表为false

}

//更新数据

this.setData({

cart_list,

selectAllStatus

});

this.getTotalPrice();

}

删除购物车操作

data: {

startX: 0, //开始坐标

startY: 0,

},

//滑动事件处理

touchmove(e) {

let

index = e.currentTarget.dataset.index, //获取当前索引

startX = this.data.startX, //获取开始X坐标

startY = this.data.startY, //获取开始Y坐标

touchMoveX = e.changedTouches[0].clientX, //滑动变化坐标

touchMoveY = e.changedTouches[0].clientY, //滑动变化坐标

//获取滑动角度

angle = this.getAngle({

X: startX,

Y: startY

}, {

X: touchMoveX,

Y: touchMoveY

});

this.data.cart_list.forEach(function (v, i) {

v.isTouchMove = false

if (Math.abs(angle) > 30) return;//用户滑动超过30度,删除按钮就不出来

if (i == index) {

if (touchMoveX > startX) //右滑

v.isTouchMove = false

else //左滑

v.isTouchMove = true

}

})

//更新数据

this.setData({

cart_list: this.data.cart_list

})

},

getAngle(start, end) {

let X = end.X - start.X,

Y = end.Y - start.Y

//返回角度 /Math.atan()返回数字的反正切值

return 360 * Math.atan(Y / X) / (2 * Math.PI);

},

delCartItem(e) {

const index=e.currentTarget.dataset.index; //获取购物车要删除商品的下标

this.data.cart_list.splice(index, 1);

wx.clearStorageSync(“select_num”);

this.setData({

cart_list: this.data.cart_list

});

}

七、商品的匹配及搜索功能实现

页面结构分析:先把搜索提示框固定定位到搜索栏下方,如果搜索到商品,则用商品展示模版输出该数据

搜索

{{item.header}}

逻辑分析:

我的实现思路是:

  • 如果匹配到商品,搜索框下方就要让搜索提示框显示;

  • 当用户输入搜索的内容为空,搜索提示框隐藏

  • 用户点击搜索按钮,则把所有匹配到的商品列表显示出来,注意要模糊搜索不区分大小写,提高用户体验;

  • 用户点击匹配到的商品条目,则搜索该商品

实现方法:

  • filter()+indexOf()+toLowerCase();

代码如下:

import showDetail from “…/…/modules/showDetail”;

const app=getApp();

Page({

/**

  • 页面的初始数据

*/

data: {

goods_list:[],

search_list:[],

is_hidden:true

},

searchInput(e){

let search_list=this.getList(e.detail.value); //获取用户的输入值

if(e.detail.value==“”){ //如果用户没输入,搜索提示列表置空,并且让搜索提示框隐藏

search_list=[];

this.data.is_hidden=true;

}else{

this.data.is_hidden=false;

}

//更新数据

this.setData({

search_list,

is_hidden:this.data.is_hidden

});

},

search(e){

//按关键字筛选商品,如果关键字匹配到商品名称,则返回该商品列表

const keywords=wx.getStorageSync(‘keywords’);

wx.showLoading({

title: ‘请稍等’,

});

setTimeout(()=>{

this.setData({

goods_list:this.getList(keywords),

is_hidden:true //如果搜索到了商品,就让搜索框隐藏

});

wx.hideLoading();

},500);

},

showDetail,

showItemDetail(e){

//按关键字筛选商品,如果关键字匹配到商品名称,则返回该商品列表

const header=e.currentTarget.dataset.header.toLowerCase();

console.log(header);

wx.showLoading({

title: ‘请稍等’,

})

setTimeout(()=>{

wx.hideLoading()

this.setData({

goods_list:this.getList(header),

is_hidden:true

});

},500)

},

/**

  • attr:需要匹配筛选的数据

*/

getList(attr){ //定义一个获取商品标题的方法

return app.globalData.phone.goods_list.filter(item=>{

return item.header.toString().toLowerCase().indexOf(attr)>-1;

});

}

})

八、收货地址页

实现思路:用数据缓存和数据绑定来控制input的disabled实现实时编辑

代码如下:

基础面试题

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

主要内容包括:HTML,CSS,JavaScript,浏览器,性能优化等等

t(()=>{

this.setData({

goods_list:this.getList(keywords),

is_hidden:true //如果搜索到了商品,就让搜索框隐藏

});

wx.hideLoading();

},500);

},

showDetail,

showItemDetail(e){

//按关键字筛选商品,如果关键字匹配到商品名称,则返回该商品列表

const header=e.currentTarget.dataset.header.toLowerCase();

console.log(header);

wx.showLoading({

title: ‘请稍等’,

})

setTimeout(()=>{

wx.hideLoading()

this.setData({

goods_list:this.getList(header),

is_hidden:true

});

},500)

},

/**

  • attr:需要匹配筛选的数据

*/

getList(attr){ //定义一个获取商品标题的方法

return app.globalData.phone.goods_list.filter(item=>{

return item.header.toString().toLowerCase().indexOf(attr)>-1;

});

}

})

八、收货地址页

实现思路:用数据缓存和数据绑定来控制input的disabled实现实时编辑

代码如下:

基础面试题

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

主要内容包括:HTML,CSS,JavaScript,浏览器,性能优化等等

[外链图片转存中…(img-e9GUWbFL-1715751428840)]

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值