鸿蒙应用ets之仿黑马智慧商城分类页

黑马vue2项目的智慧商城,自己仿写一个鸿蒙版的


前言

黑马的接口调用基础地址更换了,之前的接口需要更换

需要用到黑马智慧商城接口。地址:wiki - 智慧商城-实战项目 (apifox.com)


一、分析布局

总体为纵向布局,分为头部和内容区

内容区左边框框为一个可以滚动的菜单栏

内容区右边框框为一个展示主菜单选项中的子选项内容(可以使用Flex或者Grid布局展示)

二、编写UI界面

1.头部块(红色框内容)

 //头部文字
        Row() {
          Text('全部分类')
            .width('100%')
            .fontSize(25)
            .fontWeight(800)
            .fontColor(Color.Black)
            .textAlign(TextAlign.Center)
        }.width('100%')
      //顶部搜索栏
        Row() {
          Search({ placeholder: '搜索商品' })
            .width('90%')
        }.width('100%').justifyContent(FlexAlign.Center)

2.主菜单块(黄色框内容)

//左边主菜单选项
        Column(){
          List(){
            //渲染主菜单名字
            ForEach(this.allGoodsData,(item:string,index:number)=>{
              ListItem(){
                Text(item)
                  .width('100%').height(50)
                  .fontColor(this.backColor[index === this.currentIndex ? 1 : 0])
                  .fontSize(20).fontWeight(700).textAlign(TextAlign.Center)
              }.padding({top:10})
              .onClick(()=>{
                //当用户点击其他主菜单选项的时候将索引赋值
                this.currentIndex = index
                //这里可以判断后台获取的数据是否包含子选项,我这里偷懒直接定义静态的了
                this.i = index
                if(this.i>7){
                  //索引大于7的主菜单选项没有子选项内容,那么就在子菜单内容展示无内容
                  this.flag = true
                }else{
                  this.flag = false
                }
                //清空子菜单数组内容,便于后面重新赋值
                this.goodsInfo = []
                //更新子菜单内容
                this.updateInfo()
              })
            })
          }.backgroundColor("#ffedefef")
        }.width('30%').height('100%')

3.子选项块(蓝色框内容)

//右边子选项
        Column(){
          //判断用户点击的主菜单获取的数据,子选项是否有数据
          if(!this.flag){//有数据,则渲染数据
            Flex({wrap:FlexWrap.Wrap,justifyContent:FlexAlign.Center}){
              ForEach(this.goodsInfo,(item:any,index:number)=>{
                Column(){
                  Image(item.url)
                    .width('30%').height(100).objectFit(ImageFit.Contain)
                  Text(item.name).fontSize(12).fontWeight(600)
                }
              })
            }.padding('2%')
          }else {//没有数据,展示无数据提示
            Text('暂时没有数据').fontSize(30).fontWeight(800)
          }
        }.width('70%').height('100%')

三 、发送请求获取数据

1.页面出现之前的时候执行

获取默认内容

 //获取分类页的后台数据
  async getGoodsClass(){
    //发送请求
    const data = await axios.get('http://smart-shop.itheima.net/index.php?s=/api/category/list')
    //左边
    const len1 = data.data.data.list.length//获取数据的长度,便于下面渲染
    const category = data.data.data.list//简化
    //循环,将后台数据中的主菜单内容添加到数组中
    for (let i = 0; i < len1; i++) {
      this.allGoodsData.push(category[i].name)
    }
    //右边
    const len2 = category[this.i].children.length//获取每一个主菜单对应的子选项的长度
    //循环将对应的主菜单的子选项的内容添加到数组中
    for (let i = 0; i < len2; i++) {
      var item = {
        name:category[this.i].children[i].name,
        url:category[this.i].children[i].image.preview_url
      }
      this.goodsInfo.push(item)
    }
  }

2.更新主菜单对应的子选项

当用户点击不同的主菜单的时候,需要刷新子选项

//更新对应的商品信息
  async updateInfo(){
    const data = await axios.get('http://smart-shop.itheima.net/index.php?s=/api/category/list')
    const category = data.data.data.list
    const len2 = category[this.i].children.length
      for (let i = 0; i < len2; i++) {
        var item = {
          name:category[this.i].children[i].name,
          url:category[this.i].children[i].image.preview_url
        }
        this.goodsInfo.push(item)
      }
  }

总结

该页面主要实现主菜单的滑动,点击然后展示不同类别的子选项内容

完整代码如下:

import axios from '@ohos/axios'
@Component
export struct More{

  //存放商品总列表的数组
  @State allGoodsData:string[]=[]
  //存放分类商品的信息数组
  @State goodsInfo:any[]=[]
  //默认查询分类商品组
  @State i:number = 0
  //背景颜色数组
  @State backColor:string[]=["#ff868585", "#ffff0000"]
  //用户点击现在的索引
  @State currentIndex:number = 0
  //判断是否有商品信息的标志
  @State flag:boolean = false

 aboutToAppear(){
    this.getGoodsClass()
  }

  //获取分类页的后台数据
  async getGoodsClass(){
    //发送请求
    const data = await axios.get('http://smart-shop.itheima.net/index.php?s=/api/category/list')
    //左边
    const len1 = data.data.data.list.length//获取数据的长度,便于下面渲染
    const category = data.data.data.list//简化
    //循环,将后台数据中的主菜单内容添加到数组中
    for (let i = 0; i < len1; i++) {
      this.allGoodsData.push(category[i].name)
    }
    //右边
    const len2 = category[this.i].children.length//获取每一个主菜单对应的子选项的长度
    //循环将对应的主菜单的子选项的内容添加到数组中
    for (let i = 0; i < len2; i++) {
      var item = {
        name:category[this.i].children[i].name,
        url:category[this.i].children[i].image.preview_url
      }
      this.goodsInfo.push(item)
    }
  }

  //更新对应的商品信息
  async updateInfo(){
    const data = await axios.get('http://smart-shop.itheima.net/index.php?s=/api/category/list')
    const category = data.data.data.list
    const len2 = category[this.i].children.length
      for (let i = 0; i < len2; i++) {
        var item = {
          name:category[this.i].children[i].name,
          url:category[this.i].children[i].image.preview_url
        }
        this.goodsInfo.push(item)
      }
  }


  build(){
    //总体纵向布局
    Column(){
      //头部文字
        Row() {
          Text('全部分类')
            .width('100%')
            .fontSize(25)
            .fontWeight(800)
            .fontColor(Color.Black)
            .textAlign(TextAlign.Center)
        }.width('100%')
      //顶部搜索栏
        Row() {
          Search({ placeholder: '搜索商品' })
            .width('90%')
        }.width('100%').justifyContent(FlexAlign.Center)

      Row(){
        //左边主菜单选项
        Column(){
          List(){
            //渲染主菜单名字
            ForEach(this.allGoodsData,(item:string,index:number)=>{
              ListItem(){
                Text(item)
                  .width('100%').height(50)
                  .fontColor(this.backColor[index === this.currentIndex ? 1 : 0])
                  .fontSize(20).fontWeight(700).textAlign(TextAlign.Center)
              }.padding({top:10})
              .onClick(()=>{
                //当用户点击其他主菜单选项的时候将索引赋值
                this.currentIndex = index
                //这里可以判断后台获取的数据是否包含子选项,我这里偷懒直接定义静态的了
                this.i = index
                if(this.i>7){
                  //索引大于7的主菜单选项没有子选项内容,那么就在子菜单内容展示无内容
                  this.flag = true
                }else{
                  this.flag = false
                }
                //清空子菜单数组内容,便于后面重新赋值
                this.goodsInfo = []
                //更新子菜单内容
                this.updateInfo()
              })
            })
          }.backgroundColor("#ffedefef")
        }.width('30%').height('100%')
        //右边子选项
        Column(){
          //判断用户点击的主菜单获取的数据,子选项是否有数据
          if(!this.flag){//有数据,则渲染数据
            Flex({wrap:FlexWrap.Wrap,justifyContent:FlexAlign.Center}){
              ForEach(this.goodsInfo,(item:any,index:number)=>{
                Column(){
                  Image(item.url)
                    .width('30%').height(100).objectFit(ImageFit.Contain)
                  Text(item.name).fontSize(12).fontWeight(600)
                }
              })
            }.padding('2%')
          }else {//没有数据,展示无数据提示
            Text('暂时没有数据').fontSize(30).fontWeight(800)
          }
        }.width('70%').height('100%')
      }.width('100%').layoutWeight(1)
    }
    .width('100%').height('100%')
  }
}

<think>好的,我现在需要解决用户提出的关于AArch64架构中R_AARCH64_ADR_PREL_PG_HI21重定位错误以及.bss段相关的截断问题。用户提到了引用中的几个情况,我需要结合这些信息来找到解决方法。 首先,用户提供的引用[1]提到,旧的uboot(2019.04之前)只能处理21位的重定位,导致代码段超过1MB就会报错。解决方法是通过4K对齐,利用高位计算重定位,实现32位寻址。这涉及到修改start.S和relocate_64.S文件。这说明可能需要调整代码段的对齐方式或者重定位的计算方法。 引用[2]指出问题明确是由ADRP指令引起的,而ADRP指令在AArch64中用于生成地址的高位部分,结合ADD等指令形成完整地址。如果地址偏移超过ADRP能表示的范围(±4GB),就会导致重定位错误。这可能意味着代码或数据的位置超出了ADRP指令的寻址范围,需要调整内存布局或使用不同的指令。 引用[3]提到AArch64虽然有64位的相对PC寻址指令,但缺少对应的重定位方式,导致链接器无法正确处理某些情况。这可能涉及到工具链的支持问题,需要检查编译器或链接器的版本,或者使用特定的编译选项。 接下来,我需要将这些信息整合起来,形成解决方案。可能的步骤包括: 1. **检查工具链版本**:确保使用的编译器、链接器版本较新,支持AArch64的更大地址范围。 2. **调整内存布局**:确保.bss段或其他相关段的位置在ADRP指令的寻址范围内,可能需要修改链接脚本,将关键段放置在4GB范围内。 3. **代码段对齐**:按照引用[1]的建议,将代码段4K对齐,从而允许使用高位地址计算,扩展寻址范围。 4. **修改重定位代码**:在start.S和relocate_64.S中调整重定位的逻辑,使用高位计算方式,避免截断。 5. **替换ADRP指令**:如果可能,使用LDR指令结合文字池(literal pool)来加载大地址,避免依赖ADRP的寻址限制。 6. **链接脚本优化**:在链接脚本中明确分配.bss段的位置,避免其超出ADRP的寻址范围,或者调整段的对齐方式。 需要验证这些步骤的有效性。例如,在修改链接脚本时,可能需要将.bss段放置在靠近代码段的位置,或者确保其地址在±4GB范围内。同时,代码中的ADRP指令如果引用了超出范围的符号,可能需要替换为其他寻址方式,或者调整符号的位置。 另外,可能需要查阅更多关于AArch64重定位类型的文档,了解R_AARCH64_ADR_PREL_PG_HI21的具体限制和处理方法。比如,该重定位类型是否允许更大的偏移,或者是否有其他重定位类型可以替代。 最后,可能需要实际编译和链接代码,观察错误是否解决,并根据调试信息进一步调整。例如,使用编译选项-ffunction-sections和-fdata-sections来优化段的分布,或者使用链接器选项--fix-cortex-a53-843419来应对特定的处理器问题,虽然这可能不直接相关,但有时能提供线索。</think>### 解决R_AARCH64_ADR_PREL_PG_HI21重定位截断问题的分步方法 #### 问题本质 此错误由AArch64架构的`ADRP`指令寻址范围限制引发,当`.bss`段或其他关键段与代码段距离超过`ADRP`指令的4GB寻址范围时,会导致重定位失败[^2][^3]。 --- #### 解决方案 1. **调整链接脚本(关键步骤)** - **目标**:确保`.bss`段与代码段距离在4GB范围内。 - **修改方法**:在链接脚本中强制指定`.bss`段紧邻代码段: ```ld .bss : { __bss_start = .; *(.bss*) __bss_end = .; } >RAM AT>RAM ``` 添加`>RAM AT>RAM`约束内存区域连续性[^1]。 2. **代码段4K对齐优化** - **原理**:4K对齐后,低位地址可忽略,利用高位地址扩展寻址范围。 - **修改文件**:`arch/arm/cpu/armv8/start.S` ```asm .align 12 /* 4K对齐 */ _start: ... ``` 3. **重定位逻辑修正** - **修改文件**:`arch/arm/lib/relocate_64.S` ```asm ldr x0, =__rel_dyn_start ldr x1, =__rel_dyn_end sub x2, x1, x0 lsr x2, x2, #3 /* 右移3位,实现高位寻址计算 */ ``` 4. **替代ADRP指令(可选)** - **使用文字池加载地址**: ```asm ldr x0, =symbol_name // 替代ADRP+ADD组合 ``` --- #### 验证方法 1. 使用`aarch64-linux-gnu-objdump -d u-boot`检查`.bss`段与代码段偏移 2. 观察编译日志是否出现`relocation truncated`警告 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值