服务器搭建完成之后,编写了诸多api用于数据传输工作(略)
编写完成之后,回到鸿蒙开发工具,开始编写搜索页面的代码。
打开搜索页面时,先会展示历史搜索记录(如果有的话),然后会根据热门搜索向用户推荐搜索内容。当用户点击历史搜索或者热门搜索的标签或者手动输入搜索内容并点击搜索时,搜索提示将会消失,并展示搜索结果。
在编写的过程中遇到了一个问题:
@State search: boolean = false;
onSearch(textInput) {
this.search = true;
}
build() {
SearchCard({ onSearch: this.onSearch })
if(!this.search) {
...
}
}
将函数作为参数传递给子组件,子组件调用该函数并改变了响应式变量的值,但是却没有引起重绘。具体原因未知,但是可以将响应式变量使用@Link传入子组件中,在子组件中修改变量的值,这样就可以触发响应重绘。
搜索页面效果展示(数据仅为样例):
当用户搜索出来这些列表之后,点某个商店可以进入商店详情页并展示该商店所售卖的单品,而点某个单品可以进入商店并滚动到单品所在地。同时,数据库中还包含了单品所属类别,所以详情页可以按照类别来规划单品。
设计页面如下
遇到的问题
在父组件中定义函数,并将函数传给子组件,子组件调用函数时报错
错误原因:子组件调用函数时找不到函数中this所指的定义在父组件中的数据,所以在传递函数时需要用 .bind(this)
将this引用一同传递过去。
接下来来实现购物车界面,此界面参考美团购物车界面:
可以看到,同一家商店的商品会被归类到一个卡片中,每个商品前都有选择框,每个商店卡片头部也有选择框控制是否选择自家的所有商品,同时,在页脚处,有一个全局的选择框控制是否全选商品;当点击头部的编辑按钮时,页尾的结算按钮会变成删除按钮,删除所有选中的商品。
本人实现该界面的方法是:页首页脚单独编写两个组件Header、Footer来控制,随后通过算法分类出每个出现的商店和商品,通过ForEach渲染出相应的卡片组件StoreCard,在卡片中再次ForEach渲染出子组件ProductCard。然而考虑到还需要实现选择功能,所以使用@Observed
修饰相关类后通过@ObjectLink
传递给子组件。
中间遇到了一点小问题:
在这个卡片中,预想的效果应当是:
-
当点击商店名旁边的选择框时,应当全选或全不全所有该商店的商品。
-
当未点击商店名旁的选择框而是手动选择了全部商品,此时商店选择框应当自动被勾选
-
当全选了商店的商品时,若手动取消了某个商品的选择,应当自动取消勾选商店的全选框
最初我为商店的全选按钮添加了 onChange
事件:
.onChange((value) => {
for (let index = 0; index < this.storeItem.child.length; index++) {
this.storeItem.child[index].selected = value;
}
})
这样就可以实现点击全选后选择所有商品。但是当测试上述第三个功能时,子组件的改变引起了父组件单选框状态的改变,此时会触发这个 onChange
函数,取消一个商品的选择,导致所有不相关的商品一同被取消了选择。
解决方法是:将 onChange
改为 onClick
事件,原理很简单,只有当用户点击全选按钮时才会触发所有商品的全选/全不选方法,所以改为onClick
可以避免程序修改selected
的值而触发事件。
最后编写个人主页见面,初步实现如下: