第二章 主页整体架构设计


前言

本次继续延续上一章,介绍App主页整体的架构设计,将主页分为四部分。


一、主要框架介绍

主页分为四部分,第一部分是位于主页底部的引导页签,实现页面切换;第二部分是App首页,这个放在第三章具体讲;第三、四部分分别为精选页面和我的页面,这两个放在第四章讲。

二、具体设计

1.主页页签

主要运用Tabs组件,其中barPosition变量控制页签的位置,主要形式为两种: BarPosition.Start:左侧或顶部, vertical(true) true页签位于左侧;false页签位于顶部;
BarPosition.End:右侧或低部, vertical(true) true页签位于右侧;false页签位于低部
代码如下:

//BarPosition.Start 左侧或顶部 vertical(true) true页签位于左侧;false页签位于顶部
      //BarPosition.End 右侧或低部 vertical(true) true页签位于右侧;false页签位于低部
      Tabs({barPosition: BarPosition.End}){
        ForEach(this.items, (item: {title: string, iconSelected: Resource, iconNormal: Resource}, index: number) => {
          TabContent(){
            //页签的内容
            Column(){
              Text(item.title)
              //加载不同的组件
              if(index===0){
                Home()
              }else if (index===1){
                Choice()
              }else {
                Mine()
              }
            }
          }.tabBar(this.TabBuilder(item.title, item.iconSelected, item.iconNormal, index))
        })
      }
      .vertical(false)
      .barWidth('100%') //宽度
      .barHeight(70)  //高度
      .animationDuration(400)
      .onChange((index: number) => {
        this.currentIndex = index;
      })

因为项目中的App的页签位于主页底部,所以Tabs组件形式为BarPosition.End,vertical为false。

2.运用页签控制器进行页面切换

定义Tabs组件控制器TabsController,通过控制Tabs组件进行页面切换

代码如下:

  private controller: TabsController = new TabsController(); //Tabs组件的控制器,用于控制Tabs组件进行页签切换
  private items: Array<{title: string, iconSelected: Resource, iconNormal: Resource}> = [
      {title:'首页', iconSelected: $r('app.media.ic_05'), iconNormal: $r('app.media.ic_01')},
      {title:'精选', iconSelected: $r('app.media.ic_07'), iconNormal: $r('app.media.ic_03')},
      {title:'我的', iconSelected: $r('app.media.ic_08'), iconNormal: $r('app.media.ic_04')},
  ]

3.页面切换反馈

对底部页签使用两组不同颜色的图标,标注页面切换时保证让用户意识到页面的切换,具体使用@Builder装饰器构建TabBuilder()函数,使页签进行具体改变。

代码如下:

  @State currentIndex: number = 0;  //当前索引 0
  //@Builder 装饰器 自定义构建函数
  @Builder TabBuilder(title, iconSelected, iconNormal, index){
    Column(){
      Image(this.currentIndex===index?iconSelected: iconNormal)
        .width(25)
        .height(25)
      Text(title)
        .fontColor(this.currentIndex===index?'#E62E31': '#182431')
        .fontSize(14)
        .fontWeight(500)
    }
    .width('100%')
  }
  ...
  ...
  .onChange((index: number) => {
        this.currentIndex = index;
      })

主页代码展示:

import Home from '../view/HomePage'
import Choice from '../view/ChoicePage'
import Mine from '../view/MinePage'

@Entry
@Component
struct Main {
  @State message: string = '首页';
  private controller: TabsController = new TabsController(); //Tabs组件的控制器,用于控制Tabs组件进行页签切换
  private items: Array<{title: string, iconSelected: Resource, iconNormal: Resource}> = [
      {title:'首页', iconSelected: $r('app.media.ic_05'), iconNormal: $r('app.media.ic_01')},
      {title:'精选', iconSelected: $r('app.media.ic_07'), iconNormal: $r('app.media.ic_03')},
      {title:'我的', iconSelected: $r('app.media.ic_08'), iconNormal: $r('app.media.ic_04')},
  ]
  @State currentIndex: number = 0;  //当前索引 0

  //@Builder 装饰器 自定义构建函数
  @Builder TabBuilder(title, iconSelected, iconNormal, index){
    Column(){
      Image(this.currentIndex===index?iconSelected: iconNormal)
        .width(25)
        .height(25)
      Text(title)
        .fontColor(this.currentIndex===index?'#E62E31': '#182431')
        .fontSize(14)
        .fontWeight(500)
    }
    .width('100%')
  }
  build() {
    Row() {
      //BarPosition.Start 左侧或顶部 vertical(true) true页签位于左侧;false页签位于顶部
      //BarPosition.End 右侧或低部 vertical(true) true页签位于右侧;false页签位于低部
      Tabs({barPosition: BarPosition.End}){
        ForEach(this.items, (item: {title: string, iconSelected: Resource, iconNormal: Resource}, index: number) => {
          TabContent(){
            //页签的内容
            Column(){
              Text(item.title)
              //加载不同的组件
              if(index===0){
                Home()
              }else if (index===1){
                Choice()
              }else {
                Mine()
              }
            }
          }.tabBar(this.TabBuilder(item.title, item.iconSelected, item.iconNormal, index))
        })
      }
      .vertical(false)
      .barWidth('100%') //宽度
      .barHeight(70)  //高度
      .animationDuration(400)
      .onChange((index: number) => {
        this.currentIndex = index;
      })
    }
    .height('100%')
  }
}

效果展示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


总结

本次主要介绍了主页的布局,还有主页底部页签的应用。在主页代码中为了使代码简洁,除了页签的另外三部分被单独编写,此后会频繁使用import…from…语句引用其他代码页。

在Vue3中使用TypeScript实现类似钉钉的日历组件,你可以采用以下步骤: 1. 首先,安装所需的库: - 使用`vue-class-component`和`vue-property-decorator`来支持TypeScript和ES6类语法: ``` npm install vue-class-component vue-property-decorator typescript ``` 2. 创建一个`Calendar.vue`文件,结合`VCalendar`库(例如 https://github.com/xiaoying/v-calendar),这是一个轻量级的Vue日历组件,支持TS类型定义。 ```typescript import { Component, Prop } from 'vue-class-component'; import VCalendar from 'v-calendar'; @Component({ components: { VCalendar, }, }) export default class Calendar extends Vue { @Prop() items: Array<{ date: Date, title?: string }> = []; // 初始化日历实例并处理折叠/展开逻辑 private calendar: VCalendar; mounted() { this.calendar = new VCalendar({ el: this.$refs.calendarContainer, events: this.items.map(item => ({ date: item.date, title: item.title })), // 添加折叠和展开功能,这通常需要自定义的视图模式或选项 views: { custom: { type: 'custom', render: function({ days }) { return days.filter(day => day.events.length > 0).map(day => ( <div> <button @click="toggleDayEvents(day)">{day.days}</button> <ul v-if="day.events"> {day.events.map(event => ( <li>{event.title || '-'}</li> ))} </ul> </div> )); } }, }, }); this.calendar.on('day-click', (date, event) => { // 当用户点击日期时,可以根据需求更新事件列表 }); } toggleDayEvents(day) { // 显示或隐藏对应日期的事件 this.calendar.view.DAY_EVENTS_VISIBLES.set(day.date, !this.calendar.view.DAY_EVENTS_VISIBLES.get(day.date)); } } ``` 在这个例子中,我们通过`VCalendar`组件展示了日历,并定义了`custom`视图来折叠或展开每天的事件。当用户点击日期时,`toggleDayEvents`方法会切换显示状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值