HarmonyOS鸿蒙应用开发( 四、重磅组件List列表组件使用详解)

news2024/11/19 2:43:01

List列表组件,是一个非常常用的组件。可以说在一个应用中,它的身影无处不在。它包含一系列相同宽度的列表项,适合连续、多行呈现同类数据,如商品列表、图片列表和和文本列表等。ArkUI 框架采用 List 容器组件创建列表(类似 Android 的 RecycleView、Compose 的 LazyColumn)。

之所以称List列表组件比较重磅,一方面是因为它很常用,另一方面是因为一旦学会了它,其他组件也自然不在话下。有了它配合数据的加持,可以让你的应用有模有样。类比下 Android 中的 RecycleView,它的地位足够重要吧。

网上介绍 ArkUI 的List组件知识都太零碎,且不够深入和系统。这里以一个任务列表页的完整实现为例,详细介绍下List组件的使用、组件间的值的传递,及项目代码的MVVM结构划分。分享给有需要的小伙伴,喜欢的可以点下关注并收藏。

List组件介绍

List容器组件是一种常用的布局容器,它主要用于展示一系列数据项,这些数据项可以是同类型或不同类型的数据集合。List组件能够自动管理其内部子元素的复用和滚动行为,非常适合构建列表界面,例如商品列表,联系人列表、消息列表等,可以轻松高效地显示结构化、可滚动的信息。

通过在 List 组件中按垂直或者水平方向线性排列子组件 ListItemGroup 或 ListItem,为列表中的行或列提供单个视图。或使用ForEach 迭代一组行或列,或混合任意数量的单个视图和 ForEach 结构,构建一个列表。注意List的子组件必须是 ListItemGroup 或 ListItem,ListItem 和 ListItemGroup 也必须配合 List 来使用。

如下图所示的两个页面:

第一个页面中使用了Swiper容器组件实现的轮播图,紧接着往下是使用的Grid网格容器组件,最下方是Tabs组件。右侧图片则是List容器组件,配合Scroll组件以及LazyForEach组件实现一个商品列表的页面,并且拥有下拉刷新、懒加载和到底提示的效果。

一个简单的示例

List下用ForEach循环数据,列表子项用ListItem组件,组件中再设置布局。divider属性设置列表分割线,listDirection属性设置列表是横向排列还是纵向排列(默认纵向)。

import router from '@ohos.router'
 
@Entry
@Component
struct Index {
  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 
  build() {
    Row() {
      Column() {
        List({ space: 10 }) {
          ForEach(this.arr, (item: number) => {
            ListItem() {
              Text(`${item}`)
                .width('100%')
                .height(100)
                .fontSize(20)
                .fontColor(Color.White)
                .textAlign(TextAlign.Center)
                .borderRadius(10)
                .backgroundColor(0x007DFF)
                .onClick(() => {
                  if (item === 0) {
                    //跳转到GridPage页面
                    router.push({
                      url: 'pages/GridPage'
                    })
                  }
                })
            }
          }, item => item)
        }
        //strokeWidth: 分割线的线宽。
        //color: 分割线的颜色。
        //startMargin:分割线距离列表侧边起始端的距离。
        //endMargin: 分割线距离列表侧边结束端的距离。
        // .divider({
        //   strokeWidth: 1,
        //   color: Color.Gray,
        //   startMargin: 10,
        //   endMargin: 10
        // })
        //Vertical(默认值):子组件ListItem在List容器组件中呈纵向排列。
        //子组件ListItem在List容器组件中呈横向排列。
        .listDirection(Axis.Vertical)
      }
      .padding(12)
      .height('100%')
      .backgroundColor(0xF1F3F5)
    }
    .height('100%')
  }
}

通过 ForEach 提供了组件的循环渲染能力。我们可以使用 ForEach,在其中以嵌套 ListItem 的形式来代替多个平铺的、内容相似的 ListItem,从而减少重复代码。

上述示例显示的有些单调,但是够基础。我们可以丰富一下 ListItem,例如给它加上图标:

@Component
struct ListTest {

  build() {
    List() {
      ListItem() {
        Row() {
          Image($r('app.media.icon')).width(20).height(20).margin(10)
          Text("Kotlin").fontSize(10)
        }
      }
      ListItem() {
        Row() {
          Image($r('app.media.icon')).width(20).height(20).margin(10)
          Text("TypeScript").fontSize(10)
        }
      }
      ListItem() {
        Row() {
          Image($r('app.media.icon')).width(20).height(20).margin(10)
          Text("ArkTS").fontSize(10)
        }
      }
    }
    .backgroundColor('#FFF1F3F5')
    .alignListItem(ListItemAlign.Start)
  }
}

List列表滚动事件监听

List组件提供了一系列事件方法用来监听列表的滚动,您可以根据需要,监听这些事件来做一些操作:

  • onScroll:列表滑动时触发,返回值scrollOffset为滑动偏移量,scrollState为当前滑动状态。
  • onScrollIndex:列表滑动时触发,返回值分别为滑动起始位置索引值与滑动结束位置索引值。
  • onReachStart:列表到达起始位置时触发。
  • onReachEnd:列表到底末尾位置时触发。
  • onScrollStop:列表滑动停止时触发。

使用示例代码如下:

List({ space: 10 }) {
  ForEach(this.arr, (item) => {
    ListItem() {
      Text(`${item}`)
        ...
    }
  }, item => item)
}
.onScrollIndex((firstIndex: number, lastIndex: number) => {
  console.info('first' + firstIndex)
  console.info('last' + lastIndex)
})
.onScroll((scrollOffset: number, scrollState: ScrollState) => {
  console.info('scrollOffset' + scrollOffset)
  console.info('scrollState' + scrollState)
})
.onReachStart(() => {
  console.info('onReachStart')
})
.onReachEnd(() => {
  console.info('onReachEnd')
})
.onScrollStop(() => {
  console.info('onScrollStop')
})

List使用详解

以下内容举例实现下图中的任务列表展示,详细介绍下List组件的使用。

任务列表页

在pages目录下,创建TaskListPage.ets文件。任务列表页由上部分的标题、返回按钮以及正中间的任务列表组成。使用Navigation以及List组件构成元素,使用ForEach遍历生成具体列表。大致内容如下:

// TaskListPage.ets
Navigation() {
  Column() {
    // 页面中间的列表
    TaskList()
  }
  .width(Const.THOUSANDTH_1000)
  .justifyContent(FlexAlign.Center)
}
.size({ width: Const.THOUSANDTH_1000, height: Const.THOUSANDTH_1000 })
.title(Const.ADD_TASK_TITLE)
.titleMode(NavigationTitleMode.Mini)

TaskListComponent组件

TaskListPage中,使用了自定义的TaskList()列表组件。由于TaskList是一个自定义的视图组件,所以放在view目录里最合适。在TaskList列表的右侧有一个判断是否开启的文字标识,点击某个列表需要跳转到对应的任务编辑页里。列表组件实现如下:

// TaskListComponent.ets
List({ space: Const.LIST_ITEM_SPACE }) {
  ForEach(this.taskList, (item: ITaskItem) => {
    ListItem() {
      Row() {
        Row() {
          Image(item?.icon)
          Text(item?.taskName)
            ...
        }
        .width(Const.THOUSANDTH_500)

        Blank()
          .layoutWeight(1)

        // 状态显示
        if (item?.isOpen) {
          Text($r('app.string.already_open'))
        }
        Image($r('app.media.ic_right_grey'))
          .width(Const.DEFAULT_8)
          .height(Const.DEFAULT_16)

      }
      ...
    }
    ...

    // 路由跳转到任务编辑页
    .onClick(() => {
      router.pushUrl({
        url: 'pages/TaskEditPage',
        params: {
          params: formatParams(item)
        }
      })
    })
    ...
  })
}

TaskListComponent列表组件完整实现如下:

// view--/task/--TaskListComponent.ets
import router from '@ohos.router';
import { CommonConstants as Const } from '../../common/constants/CommonConstants';
import { formatParams } from '../../viewmodel/TaskViewModel';
import { ITaskItem } from '../../model/TaskInitList';

@Component
export default struct TaskList {
  @Consume taskList: ITaskItem[];

  build() {
    List({ space: Const.LIST_ITEM_SPACE }) {
      ForEach(this.taskList, (item: ITaskItem) => {
        ListItem() {
          Row() {
            Row() {
              Image(item?.icon)
                .width(Const.DEFAULT_24)
                .height(Const.DEFAULT_24)
                .margin({ right: Const.DEFAULT_8 })
              Text(item?.taskName).fontSize(Const.DEFAULT_20).fontColor($r('app.color.titleColor'))
            }.width(Const.THOUSANDTH_500)

            Blank()
              .layoutWeight(1)
            if (item?.isOpen) {
              Text($r('app.string.already_open'))
                .fontSize(Const.DEFAULT_16)
                .flexGrow(1)
                .align(Alignment.End)
                .margin({ right: Const.DEFAULT_8 })
                .fontColor($r('app.color.titleColor'))
            }
            Image($r('app.media.ic_right_grey'))
            .width(Const.DEFAULT_8)
            .height(Const.DEFAULT_16)
          }
          .width(Const.THOUSANDTH_1000)
          .justifyContent(FlexAlign.SpaceBetween)
          .padding({ left: Const.DEFAULT_12, right: Const.DEFAULT_12 })
        }
        .height(Const.THOUSANDTH_80)
        .borderRadius(Const.DEFAULT_12)
        .onClick(() => {
          router.pushUrl({
            url: 'pages/TaskEditPage',
            params: {
              params: formatParams(item)
            }
          })
        })
        .backgroundColor($r('app.color.white'))
      }, (item: ITaskItem) => JSON.stringify(item))
    }
    .height(Const.THOUSANDTH_1000)
    .width(Const.THOUSANDTH_940)
  }
}

model数据模型定义

model目录下的数据模型定义:

// TaskInitList.ets
import AchievementMapInfo from '../common/bean/AchievementMapInfo';

import TaskInfo from '../common/bean/TaskInfo';
import { CommonConstants as Const } from '../common/constants/CommonConstants';

export interface ITaskItem {
  taskID: number;
  taskName: Resource;
  isOpen: boolean;
  unit: string;
  icon: Resource;
  dialogBg: Resource;
  targetValue: string;
  isAlarm: boolean;
  startTime: string;
  endTime: string;
  frequency: string;
  isInit: boolean;
  step: number;
}

ViewModel定义

 viewmodel目录下的TaskViewModel定义:

import { CommonConstants as Const } from '../common/constants/CommonConstants';
import Logger from '../common/utils/Logger';
import reminder from '../service/ReminderAgent';
import TaskInfoApi from '../common/database/tables/TaskInfoApi';
import { padTo2Digits } from '../common/utils/Utils';
import TaskInfo, { oneWeek } from '../common/bean/TaskInfo';
import { TaskMapById, RemindContentMap, ITaskItem } from '../model/TaskInitList';
import PublishReminderInfo from '../common/bean/PublishReminderInfo';

const publishReminder = reminder.publishReminder;
const cancelReminder = reminder.cancelReminder;
const hasNotificationId = reminder.hasNotificationId;
export const taskOriginData: ITaskItem[] = TaskMapById;

/**
 * @description Get all task status
 * @return object[] Database query results
 */
export const getAllTask = () => {
  return new Promise<TaskInfo[]>((resolve) => {
    TaskInfoApi.query(Const.GLOBAL_KEY, true, (res: TaskInfo[]) => {
      if (res?.length === 0) {
        Logger.warn('queryTaskList', 'has no data!!');
        resolve(res ?? []);
      }
      resolve(res);
    })
  });
}

/**
 * @description format data as json string
 * @param params = {}
 */
export const formatParams = (params: ITaskItem) => {
  return JSON.stringify(params);
}
//......

完整的任务列表页

最终的任务列表页面实现如下:

// TaskListPage.ets
import { ITaskItem } from '../model/TaskInitList';
import TaskList from '../view/task/TaskListComponent';
import { CommonConstants as Const } from '../common/constants/CommonConstants';
import { getAllTask, taskIndexDataInit, taskOriginData } from '../viewmodel/TaskViewModel';
import TaskInfo from '../common/bean/TaskInfo';

@Entry
@Component
@Preview
struct TaskIndex {
  @Provide taskList: ITaskItem[] = taskOriginData;

  onPageShow() {
    getAllTask().then((res: TaskInfo[]) => {
      let deepCopyDataStr = JSON.stringify(this.taskList);
      let deepCopyData: ITaskItem[] = JSON.parse(deepCopyDataStr);
      this.taskList = taskIndexDataInit(deepCopyData, res);
    })
  }

  build() {
    Row() {
      Navigation() {
        Column() {
          TaskList()
        }
        .width(Const.THOUSANDTH_1000)
        .justifyContent(FlexAlign.Center)
      }
      .size({ width: Const.THOUSANDTH_1000, height: Const.THOUSANDTH_1000 })
      .title(Const.ADD_TASK_TITLE)
      .titleMode(NavigationTitleMode.Mini)
    }
    .backgroundColor($r('app.color.primaryBgColor'))
    .height(Const.THOUSANDTH_1000)
  }
}

List组件值的传递

特别注意,上述 TaskListPage页面中调用了自定义的TaskList()列表组件,如何完成父与子组件的传值的呢?即如何把数据从mode中获取出来传递给TaskList组件?并未见有参数传递啊。这就涉及arkUI的状态管理相关的装饰器了。

在上述示例中,虽然没见到TaskList()列表组件中有参数传递,但是发现有 @Provide taskList 这一装饰器修饰的变量,且把mode中的数据赋值给了它。

在HarmonyOS ArkUI开发框架中,@Consume和@Provide是状态管理相关的装饰器,用于组件间的数据传递与同步。它们主要用于跨组件的状态共享,尤其是在多层级的父子组件之间。

@Provide:该装饰器用来声明一个状态变量,并将其提供给后代组件使用。当一个状态变量被@Provide装饰后,这个变量会自动对所有子组件可见,无需通过props或事件手动向下级组件传递。后代组件可以直接通过@Consume装饰器来获取并使用这个变量。

@Consume:此装饰器用于从祖先组件中消费(获取)由@Provide提供的状态变量。当在一个组件内使用@Consume装饰器时,它会绑定到其祖先组件中对应@Provide修饰的同名或别名状态变量上,实现双向数据同步。

// 在父组件中提供状态
class ParentComponent {
  @Provide("theta")
  theta_axis = 0;

  // 其他逻辑...
}

// 在子组件中消费状态
@Entry
@Component
struct ChildComponent {
  @Consume("theta") // 使用相同的别名"theta"
 consumeTheta: number;

  render() {
    return <Text>{`Theta Axis Value: ${this.consumeTheta}`}</Text>;
  }
}

ParentComponent提供了名为“theta”的状态变量,而ChildComponent通过@Consume装饰器消费了这个变量,并在渲染函数中显示它的值。当theta_axis发生变化时,ChildComponent中的consumeTheta也会相应更新。

MVVM结构介绍

在HarmonyOS ArkUI开发框架中,MVVM(Model-View-ViewModel)是一种用于构建用户界面的开发模式。它将应用程序分为三个主要部分:

Model

Model 代表应用程序的数据模型。在 arkUI 中,Model 可能是数据实体、数据访问对象(DAO)或者远程服务的数据源。Model 负责数据的获取、存储和处理。

View

View(视图层) 是用户界面的表示。在 arkUI 中,View 表示应用程序的界面元素,如 UI 控件,布局等。View 负责将数据展示给用户,并接收用户的交互操作。在ArkUI中,视图层由一系列UI组件组成,如Text、Image、List等,并通过声明式语法进行布局和样式设计。

ViewModel

ViewModel(视图模型层),作为Model和View之间的桥梁,包含了视图所需要的数据以及视图相关的业务逻辑。ViewModel对Model中的数据进行处理并提供给View使用,同时响应View的交互事件,执行相应的业务操作。在 arkUI 中,ViewModel 包含业务逻辑和状态管理,负责处理 View 层和 Model 层之间的通信。ViewModel 通常通过数据绑定的方式将数据从 Model 层传递给 View 层,并接收来自 View 层的用户输入。

在ArkUI中,开发者可以通过数据绑定机制来实现ViewModel和View之间的数据同步,即当ViewModel中的数据发生变化时,关联的视图会自动更新,反之亦然。

通过采用 MVVM 结构,arkUI 提供了一种分离关注点、使界面逻辑更易于测试和维护的方式,同时也使得界面的设计和逻辑更灵活和可扩展。借助数据绑定,开发人员可以更方便地管理界面的数据和状态,提高开发效率。通过这样的分离,ArkUI的MVVM结构提升了代码可读性、复用性和可测试性,同时也简化了用户界面与后端业务逻辑之间的耦合度。

一个典型的mvvm结构

举例,一个完整项目典型的mvvm结构。一个好的结构很重要,它提升了代码可读性、复用性和可测试性,同时也简化了用户界面与后端业务逻辑之间的耦合度。

目录结构示意:

├──entry/src/main/ets                 // 代码区
│  ├──agency                          // 2x4 ArkTS卡片目录
│  │  └──pages
│  │     └──AgencyCard.ets            // 2x4 ArkTS卡片任务
│  ├──common
│  │  ├──constants
│  │  │  └──CommonConstants.ets       // 公共常量
│  │  ├──database
│  │  │  ├──rdb                       // 数据库封装类
│  │  │  │  ├──RdbHelper.ets
│  │  │  │  ├──RdbUtils.ets
│  │  │  │  └──TableHelper.ets
│  │  │  └──tables                    // 数据表
│  │  │     ├──DayInfoApi.ets
│  │  │     ├──GlobalInfoApi.ets
│  │  └──utils
│  │     ├──BroadCast.ets             // 通知
│  │     ├──FormUtils.ets             // 卡片操作工具类
│  │     ├──GlobalContext.ets         
│  │     ├──Logger.ets                // 日志类
│  │     └──Utils.ets                 // 工具类
│  ├──entryability
│  │  └──EntryAbility.ets             // 程序入口类
│  ├──entryformability
│  │  └──EntryFormAbility.ets         // 卡片创建,更新,删除操作类
│  ├──model                           // model
│  │  ├──AchieveModel.ets
│  │  ├──DatabaseModel.ets            // 数据库model
│  │  ├──Mine.ets
│  │  ├──NavItemModel.ets             // 菜单栏model
│  │  ├──TaskInitList.ets
│  ├──pages
│  │  ├──MainPage.ets                 // 应用主页面
│  │  ├──MinePage.ets                 // 我的页面
│  ├──progress                        // 2x2 ArkTS卡片目录
│  │  └──pages
│  │     └──ProgressCard.ets          // 2x2 ArkTS卡片任务进度
│  ├──service
│  │  └──ReminderAgent.ets            // 后台提醒代理操作类
│  ├──view
│  │  ├──dialog                       // 弹窗组件
│  │  │  ├──AchievementDialog.ets     // 成就弹窗
│  │  │  ├──CustomDialogView.ets      // 自定义弹窗
│  │  ├──home                         // 主页面相关组件
│  │  │  ├──AddBtnComponent.ets       // 添加任务按钮组件
│  │  │  ├──HomeTopComponent.ets      // 首页顶部组件
│  │  │  └──WeekCalendarComponent.ets // 日历组件
│  │  ├──HealthTextComponent.ets      // 自定义text组件
│  │  ├──HomeComponent.ets            // 首页页面
│  │  ├──ListInfo.ets                 // 用户信息列表
│  │  └──UserBaseInfo.ets             // 用户基本信息
│  └──viewmodel                       // viewmodel
│     ├──AchievementInfo.ets          // 成就信息接口
│     ├──WeekCalendarInfo.ets         // 日期信息接口
│     └──WeekCalendarMethodInfo.ets   // 日期操作接口
└──entry/src/main/resources           // 资源文件目录

其他资源

循环渲染(ForEach)

HarmonyOS4.0从零开始的开发教程08构建列表页面_harmony 列表界面-CSDN博客

https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/tutorials_List

优秀案例(文档中心)

HarmonyOS 鸿蒙系统 | 鸿蒙学堂 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1406937.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RFID标签是什么?该技术有哪些应用领域?

射频识别&#xff08;RFID&#xff09;技术利用电磁场&#xff0c;自动识别和跟踪附在物体上的标签&#xff0c;其中&#xff0c;近场通信&#xff08;NFC&#xff09;是一种基于短距离RFID高频技术的标准&#xff0c;支持13.56 MHz的频率。 NFC技术在现今的产品中应用广泛&am…

智能GPT图书管理系统(SpringBoot2+Vue2)、接入GPT接口,支持AI智能图书馆

☀️技术栈介绍 ☃️前端主要技术栈 技术作用版本Vue提供前端交互2.6.14Vue-Router路由式编程导航3.5.1Element-UI模块组件库&#xff0c;绘制界面2.4.5Axios发送ajax请求给后端请求数据1.2.1core-js兼容性更强&#xff0c;浏览器适配3.8.3swiper轮播图插件&#xff08;快速实…

Ubuntu findfont: Font family ‘SimHei‘ not found.

matplotlib中文乱码显示 当我们遇到这样奇怪的问题时, 结果往往很搞笑 尝试1不行 Stopping Jupyter Installing font-manager: sudo apt install font-manager Cleaning the matplotlib cache directory: rm ~/.cache/matplotlib -fr Restarting Jupyter. 尝试2 This work fo…

【机组】计算机组成原理实验指导书.

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《机组 | 模块单元实验》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 ​ 目录 第一章 性能特点 1.1 系…

(音乐软件)Spotify声破天8.9.6.458

【应用名称】&#xff1a;Spotify-声破天 【适用平台】&#xff1a;#Android 【软件标签】&#xff1a;#Spotify 【应用版本】&#xff1a;8.9.4 → 8.9.6 【应用大小】&#xff1a;67MB 【软件说明】&#xff1a;软件升级更新。iOS可配合qx小火箭类的工具对该软件进行解锁…

vue(vue2)使用svg格式图标

先安装插件 配置svg文件夹&#xff0c;新建icons文件&#xff0c;svg文件夹放svg后缀文件 index.js文件中的配置 import Vue from "vue" import svgIcon from "/common/iconSvg/index.vue"Vue.component(svg-icon,svgIcon) //挂载全局组件//下面…

雪洁宠物领养管理系统的设计与实现-计算机毕业设计源码58331

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

Qt解析含颜色的QString字符串显示到控件

1、需求 开发接收含颜色字符串显示到窗口&#xff0c;可解析字符串颜色配置窗口属性&#xff0c;且分割字符串显示。 mprintf(“xxxxxx”)&#xff1b;打印的xxxxxx含有颜色配置。 2、实现方法 2.1、条件 选用Qt的PlainTextEdit控件显示字符串&#xff0c;配置为只读模式 …

存内计算引领新一代技术革新,开启算力新时代

文章目录 存内计算与传统计算的区别 存内计算与传统计算的区别 存内计算芯片的优势 存内计算在各个领域的应用 存内计算技术对未来发展的影响 CSDN存内计算开发者社区&#xff1a;引领新一代技术革新的最前沿 社区内容专业度 社区具备的资源 社区的开放性 社区招募令…

网络上的诈骗:了解网络钓鱼

网络钓鱼&#xff08;Phishing&#xff09;是一种常见的网络诈骗形式&#xff0c;旨在通过假冒合法的电子通讯手段骗取个人信息、财务数据或登录凭证。 这种攻击通常涉及发送看似来自可信来源的电子邮件、短信或社交媒体消息&#xff0c;诱使受害者提供敏感信息或点击恶意链接…

前端项目部署发版流程

一、本地代码以全部提交并推送至仓库 二、项目根目录添加&#xff08;Dockerfile、nginx.conf文件&#xff09; 三、npm run build打包生成dist文件&#xff08;项目根目录&#xff09; 四、启动docker(登录状态) 五、执行命令 docker buildx build -t ‘项目的容器集群地…

【产品交互】超全面B端设计规范总结

不知不觉已经深耕在B端这个领域3年有余&#xff0c;很多人接触过B端后会觉得乏味&#xff0c;因为B端的设计在视觉上并没有C端那么有冲击力&#xff0c;更多的是结合业务逻辑&#xff0c;设计出符合业务需求的交互&#xff0c;以及界面排版的合理性&#xff0c;达到产品的可用性…

国产芯片替代趋势:发展前景与挑战全面解读

在当今数字化浪潮中&#xff0c;国产芯片替代正成为引人注目的趋势。本文将深入剖析该趋势的发展前景与挑战&#xff0c;并提供替代芯片查询的实用技巧。无论是科技从业者普通用户&#xff0c;都将在这篇文章中找到了对未来技术格局的洞察。同时&#xff0c;我们将通过上道合顺…

气象条件对铸铁平台地基深度有哪些影响呢——河北北重

气象条件对铸铁平台地基有以下影响&#xff1a; . 1.地震 地震可能导致地基的震动和错动&#xff0c;因此地震活跃区域的建筑物通常需要更深的地基以提供更大的稳定性。 2..温度变化&#xff1a;气温的变化会导致地基中的土壤膨胀和收缩&#xff0c;从而影响地基的稳定性。特…

《WebKit 技术内幕》学习之五(4): HTML解释器和DOM 模型

4 影子&#xff08;Shadow&#xff09;DOM 影子 DOM 是一个新东西&#xff0c;主要解决了一个文档中可能需要大量交互的多个 DOM 树建立和维护各自的功能边界的问题。 4.1 什么是影子 DOM 当开发这样一个用户界面的控件——这个控件可能由一些 HTML 的标签元素…

【GitHub项目推荐--人脸识别】【转载】

01 带有移动应用程序的人脸识别库 OpenFace 作为用于人脸识别的通用库&#xff0c;能够实现瞬态和移动人脸识别&#xff0c;目前在 GitHub 上斩获 14291 Star。以下为 LFW 数据集 Sylvestor Stallone 输入单个图像的流程。 项目地址&#xff1a;https://github.com/cmusatya…

新年钜惠|泰迪智能科技免费协助企业完成3个行业AI案例建模

在新年到来之际&#xff0c;为了感谢各企业一直以来对泰迪智能科技的支持&#xff0c;日前我们推出了新年钜惠活动即&#xff1a;免费协助企业完成3个行业AI案例建模。我们希望通过这样的活动&#xff0c;可以帮助更多的企业迈出AI应用的第一步&#xff0c;同时我们也希望能够为…

黑马苍穹外卖学习Day10

文章目录 Spring Task介绍cron表达式入门案例 订单状态定时处理需求分析代码开发功能测试 WebSocket介绍入门案例 来单提醒需求分析代码开发 客户催单需求分析代码开发 Spring Task 介绍 cron表达式 入门案例 订单状态定时处理 需求分析 代码开发 新建一个task包里面编写代码…

记录xxl-job重复执行引发业务问题

业务问题描述 1.创建运单&#xff0c;发现重复&#xff08;同一个车架号两条记录&#xff09; 2.通知重复反馈&#xff0c;A系统读取中间表状态为未处理数据&#xff0c;推送到B系统 原因分析 1.以上两个问题都是xxljob定时执行的 2.通过日志分析&#xff0c;读取中间表数…

【sgTree】自定义组件:加载el-tree树节点整棵树数据,实现增删改操作。

特性 可以自定义主键、配置选项支持预定义节点图标&#xff1a;folder文件夹|normal普通样式多个提示文本可以自定义支持动态接口增删改节点可以自定义根节点id可以设置最多允许添加的层级深度支持拖拽排序&#xff0c;排序过程还可以针对拖拽的节点深度进行自定义限制支持隐藏…