当前位置: 首页 > news >正文

HarmonyOS NEXT实战:自定义封装多种样式导航栏组件

涉及知识点和装饰器

  • @ComponentV2,@Local, @Builder,@BuilderParam,@Extend, @Require ,@Param,@Event等
  • 第三方库:ZRouter ,如项目中本来就用了ZRouter路由库,案例中点返回按钮直接使用了 ZRouter.pop(),没有用到的话也支持自定义返回事件。

背景:

在项目开发进程中,导航栏的应用场景颇为繁多。以我的页面为例,其导航栏呈现为图标、文字与箭头相组合的样式;而设置页面的导航栏则是图标、文字、右侧文字以及小红点的搭配形式;至于公用顶部导航栏,又表现为左侧返回图标、中间文字、右侧图标与文字的布局。倘若针对每一处用到导航栏的地方均单独编写代码,那么代码的重复编写现象将极为严重。基于此,我们可采用自定义封装的方式构建公用组件。如此一来,不仅为项目后期的维护与拓展提供了极大的便利,同时也能够显著提升开发效率,让开发者有更多精力投入到更具价值的工作思考中,减少不必要的重复劳作时间消耗。

先上效果图

  • 图一
    在这里插入图片描述

  • 图二
    在这里插入图片描述

  • 图三
    在这里插入图片描述

实现 图一 效果图

  • 1、首先需要定义好类型,比如 图片+文字+小红点+返回右键等。
@ObservedV2
export class TabHorizontalModel {title: string;index: number; //下标icon: string | Resource;hasIcon: boolean; //是否显示图@Trace rightTitle: string;hasRightTitle: boolean;@Trace hasNew: boolean; //是否显示红点hasRightIcon: boolean; //是否显示图constructor(title: string, index: number = -1, icon: string | Resource = '', hasIcon: boolean = false, rightTitle: string = '', hasRightTitle: boolean = false, hasNew: boolean = false,hasRightIcon: boolean = true) {this.icon = icon;this.hasIcon = hasIcon;this.title = title;this.rightTitle = rightTitle;this.hasRightTitle = hasRightTitle;this.hasNew = hasNew && rightTitle !== '';this.index = index;this.hasRightIcon = hasRightIcon;}
}
  • 2、封装一个通用的 横向Tab 图片、文字、右边文字、小红点 组件
import { CommonConst } from "utils"
import { TabHorizontalModel } from "../model/TabHorizontalModel"/*** Author:J* Describe: 横向Tab 图片、文字、右边文字、小红点*/
@ComponentV2
export struct HorizontalTabItemComp {@Param @Require tabItem: TabHorizontalModel= new TabHorizontalModel('')@Param onItemClick?: () => void = undefinedbuild() {Row() {Image(this.tabItem.icon).width(24).margin({ right: 12 }).visibility(this.tabItem.hasIcon ? Visibility.Visible : Visibility.None)Text(this.tabItem.title).fontSize(16).fontColor($r('app.color.color_222222')).layoutWeight(1)if (this.tabItem.hasNew) {Badge({value: '',position: BadgePosition.Right,style: { badgeSize: 7, badgeColor: $r('app.color.color_FA2A2D') }}) {Text(this.tabItem.rightTitle).fontSize(16).fontColor($r('app.color.color_222222')).visibility(this.tabItem.hasRightTitle ? Visibility.Visible : Visibility.None).margin({ right: 20 })}} else {Text(this.tabItem.rightTitle).fontSize(16).fontColor($r('app.color.color_222222')).visibility(this.tabItem.hasRightTitle ? Visibility.Visible : Visibility.None)}Image($r('app.media.ic_arrow_right_gray_small')).width(24).margin({ left: 12 }).visibility(this.tabItem.hasRightIcon ? Visibility.Visible : Visibility.None)}.width(CommonConst.FULL_PARENT).height(44).backgroundColor($r('app.color.white')).onClick(() => {this.onItemClick?.()})}
}
  • 3、使用案例
    3.1 针对于一个,可以用下面的代码,但是对于一个页面有多个的话,要是一行行的写,虽然可以,但是不建议,而且也不优雅,所以需要用到ForEach来实现。
  HorizontalTabItemComp({tabItem: new TabHorizontalModel("我的积分", 0, $r('app.media.ic_coin'), true),onItemClick: () => {ToastUtil.showToast('我的积分')}}).margin({ left: 12, right: 12 })

3.2 定义一组数据,塞到数组里

/** 横向Tab */
export const horizontalTabItemData: Array<TabHorizontalModel> = [new TabHorizontalModel("我的积分", 0, $r('app.media.ic_coin'), true, '666', true),new TabHorizontalModel("我的分享", 1, $r('app.media.ic_share_article'), true),new TabHorizontalModel("我的收藏", 2, $r('app.media.ic_collect'), true),new TabHorizontalModel("我的书签", 3, $r('app.media.ic_read_later'), true),new TabHorizontalModel("阅读历史", 4, $r('app.media.ic_read_record'), true),new TabHorizontalModel("开源项目", 5, $r('app.media.ic_github'), true),new TabHorizontalModel("关于作者", 6, $r('app.media.ic_about'), true, '请他喝杯咖啡~', true),
]

3.3 使用ForEach来实现

 ForEach(horizontalTabItemData, (item: TabHorizontalModel, index: number) => {HorizontalTabItemComp({tabItem: item,onItemClick: () => {this.onItemClick(item)}}).margin({ left: 12, right: 12 })})/** 点击事件 */private onItemClick(item: TabHorizontalModel) {ToastUtil.showToast(item.title)if (item.index == 0) {} else if (item.index == 1) {} else if (item.index == 2) {} else if (item.index == 3) {} else if (item.index == 4) {} else if (item.index == 5) {} else if (item.index == 6) {}}

实现 图二 效果图

  • 1、首先需要定义好需要的参数
  /** 标题 */@Param title: ResourceStr = '';/** 返回按钮的点击事件 */@Param backClick?: (event?: ClickEvent) => void = undefined;/** 是否显示右侧按钮 */@Param isShowRight: boolean = false;/** 右侧标题 */@Param rightTitle: ResourceStr = '';/** 右侧图片 */@Param rightImage: ResourceStr = '';/** 右侧点击事件 */@Param rightClick?: (event?: ClickEvent) => void = undefined;
  • 2、封装一个公用的自定义导航栏组件,内置了导航栏的返回按钮、标题、右侧按钮等,完整代码如下:
import { ZRouter } from '@hzw/zrouter';
import { CommonConst } from 'utils';/*** Author:J* Describe:自定义导航栏组件* 内置了导航栏的返回按钮、标题、右侧按钮等*/
@ComponentV2
export struct TitleBarComp {/** 标题 */@Param title: ResourceStr = '';/** 返回按钮的点击事件 */@Param backClick?: (event?: ClickEvent) => void = undefined;/** 是否显示右侧按钮 */@Param isShowRight: boolean = false;/** 右侧标题 */@Param rightTitle: ResourceStr = '';/** 右侧图片 */@Param rightImage: ResourceStr = '';/** 右侧点击事件 */@Param rightClick?: (event?: ClickEvent) => void = undefined;build() {Column() {Row() {Image($r('app.media.ic_arrow_left')).width(44).padding(8).onClick(() => {if (this.backClick) {this.backClick()} else {ZRouter.pop()}})Text(this.title).fontColor($r('app.color.color_222222')).fontSize(16).maxLines(1).fontWeight(FontWeight.Bold)Row() {if (this.rightTitle) {Text(this.rightTitle).fontColor($r('app.color.color_222222')).fontSize(16).margin({ right: 10 })} else {Image(this.rightImage ? this.rightImage : $r('app.media.ic_local_search')).width(44).padding(10)}}.onClick(this.rightClick).visibility(this.isShowRight ? Visibility.Visible : Visibility.Hidden)}.width(CommonConst.FULL_PARENT).height(44).justifyContent(FlexAlign.SpaceBetween).backgroundColor($r('app.color.white'))Divider().width(CommonConst.FULL_PARENT).color($r('app.color.color_F0F0F0'))}.width(CommonConst.FULL_PARENT).height(45)}
}
  • 3、使用案例,包含了多种样式使用
 NavDestination() {Column({space:8}) {Text('第一种样式').fontColor(Color.Red)TitleBarComp({ title: '设置' })Text('第二种样式,自定义返回事件').fontColor(Color.Red)TitleBarComp({title: '设置二', backClick: () => {ToastUtil.showToast('自定义返回事件')}})Text('第三种样式,右边有文字').fontColor(Color.Red)TitleBarComp({title: '设置三',isShowRight: true,rightTitle: '右边',rightClick: () => {ToastUtil.showToast('右边')}})Text('第四种,右边有图片').fontColor(Color.Red)TitleBarComp({title: '设置四',isShowRight: true,rightImage: $r('app.media.ic_share_article'),rightClick: () => {ToastUtil.showToast('右边')}})}.width(CommonConst.FULL_PARENT).height(CommonConst.FULL_PARENT).backgroundColor($r('app.color.white'))}.hideTitleBar(true)

实现 图三 效果图

  • 背景:这个逻辑比较复杂,一步步优化实现,为啥还需要自定义,直接用官方自带的Tabs+TabContent就可以实现啊;如果只是针对于一行都是简单文字切换那还好,但是对于那种,左边、右边是图片+中间是文字用自带的就不行了,因为下面的内容的宽度是铺满屏幕的宽度的,所以需要自定义。
  • 1、定义需要的参数,自定义左边视图,右边视图,内容,下划线,是否滑动等,具体可以看完整代码。
@Param currentTabIndex: number = 0;@Param tabContentArr: boolean[] = []; //存储页面状态private tabsController: TabsController = new TabsController();@Param tabs: Array<TabBarModel> = [];//左边视图@BuilderParam tabBarLeft: () => void = this.barLeft;//右边视图@BuilderParam tabBarRight: () => void = this.barRight;//内容@BuilderParam tabContentBuilder: ($$: TabBarModel) => void = this._TabContentBuilder;//是否显示下划线@Param isShowDivider: boolean = false;//是否滑动@Param scrollable: boolean = false;//顶部中间视图是否居中 true居中 false 默认 居左@Param isTabBarCenter: boolean = false;//选中字体颜色@Param selectFontColor: ResourceColor = $r('app.color.color_222222');//滑动条是否显示@Param isDividerVisible: boolean = true;//更新@Event changeFactory: (currentTabIndex: number, isShowDivider: boolean) => void = (currentTabIndex: number, isShowDivider: boolean) => {}
  • 2、自定义顶部视图,List替换tabBar 配合Tabs 左视图–tabBar–右视图
Column() {//切换this.customTabBar()//下划线Divider().color($r('app.color.color_F0F0F0')).visibility(this.isShowDivider ? Visibility.Visible : Visibility.None)//TabContent中的tabBar居中显示,所以暂时不用tabBarTabs({ controller: this.tabsController, barPosition: BarPosition.Start }) {ForEach(this.tabs, (item: TabBarModel, index: number) => {TabContent() {//滑到哪个页面再加载,防止一块加载if (this.currentTabIndex === index || this.tabContentArr[index]) {this.tabContentBuilder(item)}}// .tabBar()}, (item: string) => item)}.layoutWeight(1).barHeight(0) //隐藏tabBar.scrollable(this.scrollable).onChange(index => {this.tabContentArr[index] = truethis.changeFactory(index,this.tabs[index].isShowDivider)})}.width(CommonConst.FULL_PARENT).backgroundColor($r('app.color.white'))
  • 3、 List实现【标题+横线】选中效果
  @BuildercustomTabBar() {Row() {//左边自定义this.tabBarLeft()//中间CustomTabBarComp({currentTabIndex: this.currentTabIndex,tabs: this.tabs,selectFontColor: this.selectFontColor,isTabBarCenter: this.isTabBarCenter,onTabClick: (index: number) => {this.tabsController.changeIndex(index)},isDividerVisible: this.isDividerVisible})//右边自定义this.tabBarRight()}.width(CommonConst.FULL_PARENT).height(44)}
  • 4、标题+横线 List和TabContent.tabBar都可以用

@ComponentV2
export struct TabBarViewComp {@Param private index: number = 0@Param currentTabIndex: number = 0@Param tabs: Array<TabBarModel> = new Array<TabBarModel>()//选中字体颜色@Param selectFontColor: ResourceColor = $r('app.color.color_222222');@Param onTabClick: (index: number) => void = () => {};@Param isDividerVisible: boolean = true;build() {Column() {//右上角图片Image(this.tabs[this.index].rightSrc).height(11).margin({ left: 46 }).visibility(this.tabs[this.index].isShowRightSrc ? Visibility.Visible : Visibility.None)Text(this.tabs[this.index].name).fontSize(this.currentTabIndex == this.index ? 16 : 14).fontColor(this.currentTabIndex == this.index ? this.selectFontColor : $r('app.color.color_505050')).fontWeight(this.currentTabIndex == this.index ? FontWeight.Bold : FontWeight.Normal).margin({ top: this.tabs[this.index].isShowRightSrc ? 0 : 11 })Divider().width(16).height(4).backgroundColor($r('app.color.colorPrimary')).margin({ top: 4, bottom: 4 }).borderRadius(12).visibility(this.isDividerVisible && this.currentTabIndex == this.index ? Visibility.Visible : Visibility.Hidden)}.margin({ right: 15 }).onClick(() => {this.onTabClick(this.index)})}
}
  • 5、完整代码如下

import { CommonConst } from "utils";
import { TabBarModel } from "../model/TabBarModel";/*** Author:J* Describe:自定义tabBar 左视图--tabBar--右视图** ListWithTabBarView({}) List替换tabBar 配合Tabs  左视图--tabBar--右视图* CustomTabBarComp({}) List实现【标题+横线】选中效果* TabBarViewComp({})  标题+横线   List和TabContent.tabBar都可以用*/
@Preview
@ComponentV2
export struct ListWithTabBarView {@Param currentTabIndex: number = 0;@Param tabContentArr: boolean[] = []; //存储页面状态private tabsController: TabsController = new TabsController();@Param tabs: Array<TabBarModel> = [];//左边视图@BuilderParam tabBarLeft: () => void = this.barLeft;//右边视图@BuilderParam tabBarRight: () => void = this.barRight;//内容@BuilderParam tabContentBuilder: ($$: TabBarModel) => void = this._TabContentBuilder;//是否显示下划线@Param isShowDivider: boolean = false;//是否滑动@Param scrollable: boolean = false;//顶部中间视图是否居中 true居中 false 默认 居左@Param isTabBarCenter: boolean = false;//选中字体颜色@Param selectFontColor: ResourceColor = $r('app.color.color_222222');//滑动条是否显示@Param isDividerVisible: boolean = true;//更新@Event changeFactory: (currentTabIndex: number, isShowDivider: boolean) => void = (currentTabIndex: number, isShowDivider: boolean) => {}aboutToAppear() {for (let index = 0; index < this.tabs.length; index++) {this.tabContentArr.push(index == 0 ? true : false)}}build() {Column() {//切换this.customTabBar()//下划线Divider().color($r('app.color.color_F0F0F0')).visibility(this.isShowDivider ? Visibility.Visible : Visibility.None)//TabContent中的tabBar居中显示,所以暂时不用tabBarTabs({ controller: this.tabsController, barPosition: BarPosition.Start }) {ForEach(this.tabs, (item: TabBarModel, index: number) => {TabContent() {//滑到哪个页面再加载,防止一块加载if (this.currentTabIndex === index || this.tabContentArr[index]) {this.tabContentBuilder(item)}}// .tabBar()}, (item: string) => item)}.layoutWeight(1).barHeight(0) //隐藏tabBar.scrollable(this.scrollable).onChange(index => {this.tabContentArr[index] = truethis.changeFactory(index,this.tabs[index].isShowDivider)})}.width(CommonConst.FULL_PARENT).backgroundColor($r('app.color.white'))// .padding({ left: 12, right: 12 })}@Builder_TabContentBuilder($$: TabBarModel) {Text("tabContentBuilder:()=>{your @Builder View}")}@BuildercustomTabBar() {Row() {//左边自定义this.tabBarLeft()//中间CustomTabBarComp({currentTabIndex: this.currentTabIndex,tabs: this.tabs,selectFontColor: this.selectFontColor,isTabBarCenter: this.isTabBarCenter,onTabClick: (index: number) => {this.tabsController.changeIndex(index)},isDividerVisible: this.isDividerVisible})//右边自定义this.tabBarRight()}.width(CommonConst.FULL_PARENT).height(44)}@BuilderbarLeft() {}@BuilderbarRight() {}
}@ComponentV2
export struct CustomTabBarComp {@Param currentTabIndex: number = 0;@Param tabs: Array<TabBarModel> = new Array<TabBarModel>()//选中字体颜色@Param selectFontColor: ResourceColor = $r('app.color.color_222222');@Param onTabClick: (index: number) => void = () => {};@Param isTabBarCenter: boolean = false;@Param isDividerVisible: boolean = true;build() {Row() {List() {ForEach(this.tabs, (item: TabBarModel, index: number) => {ListItem() {TabBarViewComp({index: index,currentTabIndex: this.currentTabIndex,tabs: this.tabs,selectFontColor: this.selectFontColor,onTabClick: (index: number) => {this.onTabClick(index)},isDividerVisible: this.isDividerVisible})}})}// .width(Constants.FULL_PARENT).height(44).listDirection(Axis.Horizontal).alignListItem(ListItemAlign.Center).scrollBar(BarState.Off)// .margin({ right: 8 })}.layoutWeight(1).justifyContent(this.isTabBarCenter ? FlexAlign.Center : FlexAlign.Start)}
}@ComponentV2
export struct TabBarViewComp {@Param private index: number = 0@Param currentTabIndex: number = 0@Param tabs: Array<TabBarModel> = new Array<TabBarModel>()//选中字体颜色@Param selectFontColor: ResourceColor = $r('app.color.color_222222');@Param onTabClick: (index: number) => void = () => {};@Param isDividerVisible: boolean = true;build() {Column() {//右上角图片Image(this.tabs[this.index].rightSrc).height(11).margin({ left: 46 }).visibility(this.tabs[this.index].isShowRightSrc ? Visibility.Visible : Visibility.None)Text(this.tabs[this.index].name).fontSize(this.currentTabIndex == this.index ? 16 : 14).fontColor(this.currentTabIndex == this.index ? this.selectFontColor : $r('app.color.color_505050')).fontWeight(this.currentTabIndex == this.index ? FontWeight.Bold : FontWeight.Normal).margin({ top: this.tabs[this.index].isShowRightSrc ? 0 : 11 })Divider().width(16).height(4).backgroundColor($r('app.color.colorPrimary')).margin({ top: 4, bottom: 4 }).borderRadius(12).visibility(this.isDividerVisible && this.currentTabIndex == this.index ? Visibility.Visible : Visibility.Hidden)}.margin({ right: 15 }).onClick(() => {this.onTabClick(this.index)})}
}
  • 6、使用案例如下,多种样式的使用:
import { ToastUtil } from '@pura/harmony-utils'
import { ListWithTabBarView, TabBarModel } from 'uicomponents'
import { CommonConst } from 'utils'
import { GetFourStyleTabData, GetOneStyleTabData, GetThreeStyleTabData, GetTwoStyleTabData } from './TestModel'@Preview
@ComponentV2
export struct TestTabBarView {@Local currentTabIndex: number = 0@Local isShowDivider: boolean = GetOneStyleTabData[0].isShowDivider@Local currentTabIndex2: number = 0@Local currentTabIndex3: number = 0@Local currentTabIndex4: number = 0build() {NavDestination() {Column() {Text('第一种样式').text(Color.Red)ListWithTabBarView({currentTabIndex: this.currentTabIndex,tabs: GetOneStyleTabData,tabBarLeft: this.tabBarLeft,tabBarRight: this.tabBarRight,tabContentBuilder: this.tabContentBuilder,isShowDivider: this.isShowDivider,changeFactory: (currentTabIndex, isShowDivider) => {this.currentTabIndex = currentTabIndexthis.isShowDivider = isShowDivider}}).height(80)Text('第二种样式').text(Color.Pink)ListWithTabBarView({currentTabIndex: this.currentTabIndex2,tabs: GetTwoStyleTabData,tabBarLeft: this.tabBarLeft2,tabBarRight: this.tabBarRight2,tabContentBuilder: this.tabContentBuilder,changeFactory: (currentTabIndex) => {this.currentTabIndex2 = currentTabIndex},isTabBarCenter: true}).height(80)Text('第三种样式').text(Color.Blue)ListWithTabBarView({currentTabIndex: this.currentTabIndex,tabs: GetThreeStyleTabData,tabBarLeft: this.tabBarLeft3,tabBarRight: this.tabBarRight3,tabContentBuilder: this.tabContentBuilder,isTabBarCenter: true,changeFactory: (currentTabIndex) => {this.currentTabIndex = currentTabIndex}}).height(80)Text('第四种样式').text(Color.Grey)ListWithTabBarView({currentTabIndex: this.currentTabIndex4,tabs: GetFourStyleTabData,tabBarLeft: this.tabBarLeft4,tabContentBuilder: (tab): void => this.tabContentBuilder(tab),isShowDivider: true,changeFactory: (currentTabIndex) => {this.currentTabIndex4 = currentTabIndex}}).layoutWeight(1).height(80)}.width(CommonConst.FULL_PARENT).height(CommonConst.FULL_PARENT)}}@BuildertabBarLeft() {Text().width(12)}@BuildertabBarRight() {Row({ space: 12 }) {Image($r('app.media.app_icon')).width(24).visibility(this.currentTabIndex == 0 || this.currentTabIndex == 1 ? Visibility.Visible : Visibility.Hidden).onClick(() => {ToastUtil.showToast('点了1')})Image($r('app.media.app_icon')).width(24).onClick(() => {ToastUtil.showToast('点了')})}.padding({ right: 12 })}@BuildertabContentBuilder($$: TabBarModel) {Text($$.id)}@BuildertabBarLeft2() {Image($r('app.media.ic_arrow_left')).width(24).margin({ left: 12, right: 6 }).onClick(() => {ToastUtil.showToast('返回键')// ZRouter.pop()})}@BuildertabBarRight2() {Image($r('app.media.app_icon')).width(24).margin({ right: 12 }).onClick(() => {ToastUtil.showToast('点了')})}@BuildertabBarLeft3() {Image($r('app.media.app_icon')).width(24).fillColor(Color.Black).margin({ left: 12, right: 20 }).onClick(() => {ToastUtil.showToast('设置')})}@BuildertabBarRight3() {Image(this.currentTabIndex == 1 ? $r('app.media.ic_next') : $r('app.media.ic_local_search')).width(24).margin({ right: 12 }).visibility(this.currentTabIndex != 2 ? Visibility.Visible : Visibility.Hidden).onClick(() => {ToastUtil.showToast(this.currentTabIndex == 1 ? '点了1' : '搜索')})}@BuildertabBarLeft4() {Text().width(12)}
}@Extend(Text)
function text(color: ResourceColor) {.height(44).width(CommonConst.FULL_PARENT).fontColor(Color.White).backgroundColor(color)
}

以往系列文章

  1. 《探索 HarmonyOS NEXT(5.0):开启构建模块化项目架构奇幻之旅 —— 模块化基础篇》
  2. 《探索 HarmonyOS NEXT(5.0):开启构建模块化项目架构奇幻之旅 —— 构建基础特性层》
  3. 《探索 HarmonyOS NEXT(5.0):开启构建模块化项目架构奇幻之旅 —— 构建公共能力层》
  4. 《探索 HarmonyOS NEXT(5.0):开启构建模块化项目架构奇幻之旅 —— Tabs底部导航栏》
  5. 《探索 HarmonyOS NEXT (5.0):开启构建模块化项目架构奇幻之旅 —— 动态路由 ZRouter:引领高效模块通信的智慧中枢》
  6. 《探索 HarmonyOS NEXT(5.0):开启构建模块化项目架构奇幻之旅 ——第三方库的使用:网络请求RCP、二次封装上下拉刷新、弹窗》
  7. HarmonyOS NEXT:模块化项目 ——修改应用图标+启动页等
  8. HarmonyOSNext模块化设计实践:打造简洁高效的登录注册页面

若本文对您稍有帮助,诚望您不吝点赞,多谢。

有兴趣的同学可以点击查看源码

  • gitee:https://gitee.com/jiaojiaoone/explore-harmony-next/tree/case%2Fwanandroid/
  • github:https://github.com/JasonYinH/ExploreHarmonyNext.git

欢迎加我微信一起交流:+V:yinshiyuba

相关文章:

HarmonyOS NEXT实战:自定义封装多种样式导航栏组件

涉及知识点和装饰器 ComponentV2&#xff0c;Local&#xff0c; Builder&#xff0c;BuilderParam&#xff0c;Extend&#xff0c; Require &#xff0c;Param&#xff0c;Event等第三方库&#xff1a;ZRouter &#xff0c;如项目中本来就用了ZRouter路由库&#xff0c;案例中…...

大数据面试笔试宝典之Flink面试

1.Flink 是如何支持批流一体的? F link 通过一个底层引擎同时支持流处理和批处理. 在流处理引擎之上,F link 有以下机制: 1)检查点机制和状态机制:用于实现容错、有状态的处理; 2)水印机制:用于实现事件时钟; 3)窗口和触发器:用于限制计算范围,并定义呈现结果的…...

pytorch整体环境打包安装到另一台电脑上

步骤一&#xff1a;安装conda-pack 首先利用 pip list 指令检查conda环境安装在哪里&#xff0c;在系统环境&#xff08;base&#xff09;下&#xff0c;于是我是使用的conda指令完成的。 # 使用Conda安装&#xff08;如果已安装conda&#xff09; conda install conda-pack …...

PostgreSQL 数据库连接

title: PostgreSQL 数据库连接 date: 2024/12/29 updated: 2024/12/29 author: cmdragon excerpt: PostgreSQL是一款功能强大的开源关系数据库管理系统,在现代应用中广泛应用于数据存储和管理。连接到数据库是与PostgreSQL进行交互的第一步,这一过程涉及到多个方面,包括连…...

【算法】复杂性理论初步

六、算法复杂性初步 重要的复杂性类 P P P 的定义 多项式时间内可解的问题 若 L ∈ P L∈P L∈P&#xff0c;则存在确定性多项式时间的图灵机 M M M&#xff0c;使得 M ( x ) 1 ⟺ x ∈ L M(x)1⟺x∈L M(x)1⟺x∈L N P NP NP 的定义 多项式时间内可验证验证解的正确性 &…...

HarmonyOS NEXT应用开发实战:免费练手的网络API接口分享

学习一项技能&#xff0c;最好也最快的办法就是直接动手实战。在实战中不断的总结经验和收获成就感。这里分享些好用且免费的网络API练手接口&#xff0c;这对于想要提升自己网络开发能力的开发者来说&#xff0c;无疑是极大的福音。今天&#xff0c;我将详细介绍一个API接口集…...

C++的第一个程序

前言 在学习c之前&#xff0c;你一定还记得c语言的第一个程序 当时刚刚开始进行语言学习 因此告诉到&#xff0c;仅仅需要记住就可以 #include <stdio.h>int main(){printf("Hello World");return 0; }而对于c中的第一个程序&#xff0c;似乎有所变化 C的…...

Java 中 Stream 流的使用详解

Java 中 Stream 流的使用详解 什么是 Stream&#xff1f; Stream 是 Java 8 引入的一种全新的操作集合的方式。它支持通过声明性方式对集合进行复杂的数据操作&#xff08;如过滤、排序、聚合等&#xff09;&#xff0c;避免使用大量的 for 循环&#xff0c;提高代码的可读性…...

【UE5.3.2】生成vs工程并rider打开

Rider是跨平台的,UE也是,当前现在windows上测试首先安装ue5.3.2 会自动有右键的菜单: windows上,右键,生成vs工程 生成的结果 sln默认是vs打开的,我的是vs2022,可以open with 选择 rider :Rider 会弹出 RiderLink是什么插...

ssh免密码登陆配置

ssh 命令本身不支持直接在命令中带上密码&#xff0c;出于安全考虑&#xff0c;SSH 协议不允许将密码明文写在命令中。直接在命令行中输入密码是一种不推荐的做法&#xff0c;因为它会暴露密码&#xff0c;增加安全风险。 如果你希望实现自动化登录而不手动输入密码&#xff0…...

Hive之import和export使用详解

在hive-0.8.0后引入了import/export命令。 Export命令可以导出一张表或分区的数据和元数据信息到一个输出位置&#xff0c;并且导出数据可以被移动到另一个hadoop集群或hive实例&#xff0c;并且可以通过import命令导入数据。 当导出一个分区表&#xff0c;原始数据可能在hdf…...

数据库锁的深入探讨

数据库锁&#xff08;Database Lock&#xff09;是多用户环境中用于保证数据一致性和隔离性的机制。随着数据库系统的发展&#xff0c;特别是在高并发的场景下&#xff0c;锁的机制变得尤为重要。通过使用锁&#xff0c;数据库能够防止并发操作导致的数据冲突或不一致。本文将深…...

【每日学点鸿蒙知识】沉浸式状态栏、类似ref 属性功能属性实现、自定义对话框背景透明、RichEditor粘贴回调、自动滚动列表

1、HarmonyOS 沉浸式状态栏&#xff1f; 实现沉浸式状态栏功能时&#xff0c;能够实现&#xff0c;但是目前每个自定义组件都需要padding top 状态栏的高度才行&#xff0c;有办法实现统一设置吗&#xff1f;不需要每个自定义组件中都padding top 状态栏的高度&#xff1f; 暂…...

Hive刷分区MSCK

一、MSCK刷分区 我们平时通常是通过alter table add partition方式增加Hive的分区的&#xff0c;但有时候会通过HDFS put/cp命令或flink、flum程序往表目录下拷贝分区目录&#xff0c;如果目录多&#xff0c;需要执行多条alter语句&#xff0c;非常麻烦。Hive提供了一个"…...

在Ubuntu下通过Docker部署Mastodon服务器

嘿&#xff0c;朋友们&#xff0c;今天咱们来聊聊如何在Ubuntu上通过Docker部署Mastodon服务器。想要拥有自己的社交媒体平台&#xff1f;Mastodon就是个不错的选择&#xff01;&#x1f310;&#x1f680; Docker与Mastodon简介 Docker是一个开源的容器化平台&#xff0c;让…...

【EtherCATBasics】- KRTS C++示例精讲(2)

EtherCATBasics示例讲解 目录 EtherCATBasics示例讲解结构说明代码讲解 项目打开请查看【BaseFunction精讲】。 结构说明 EtherCATBasics&#xff1a;应用层程序&#xff0c;主要用于人机交互、数据显示、内核层数据交互等&#xff1b; EtherCATBasics.h &#xff1a; 数据定义…...

MYSQL无法被连接问题

如果您在尝试连接到MySQL服务器时遇到问题&#xff0c;以下描述了您可以采取的一些措施来纠正该问题。 确保服务器正在运行。如果没有&#xff0c;则客户端无法连接到它。例如&#xff0c;如果尝试连接到服务器失败并出现以下消息之一&#xff0c;则可能是服务器未运行&#xf…...

【Python】什么是字典(Dictionary)?

什么是字典&#xff08;Dictionary&#xff09;&#xff1f; 字典&#xff08;Dictionary&#xff09;是 Python 中一种 可变&#xff08;mutable&#xff09;的数据结构&#xff0c;用于存储键值对&#xff08;key-value pairs&#xff09;。字典通过 键&#xff08;key&…...

Web安全 - API 成批分配漏洞的四种修复方案

文章目录 概述危害修复建议与实施方案解决方案 1&#xff1a;手动绑定数据解决方案 2&#xff1a;使用 DTO 进行数据过滤解决方案 3&#xff1a;启用字段白名单解决方案 4&#xff1a;验证输入数据模式 验证修复有效性小结 概述 批量分配漏洞&#xff08;Mass Assignment&#…...

计算机网络实验室建设方案

一、计算机网络实验室拓扑结构 计算机网络综合实验室解决方案&#xff0c;是面向高校网络相关专业开展教学实训的综合实训基地解决方案。教学实训系统采用 B&#xff0f;S架构&#xff0c;通过公有云教学实训平台在线学习模式&#xff0c;轻松实现网络系统建设与运维技术的教学…...

ubuntu20.04 调试bcache源码

搭建单步调试bcache的环境&#xff0c;/dev/sdb作为backing dev&#xff0c; /dev/sdc作为cache dev。 一、宿主机环境 1&#xff09;安装ubuntu 20.04 &#xff1a; 参考ubuntu20.04 搭建kernel调试环境第一篇--安装系统_ubuntu kernel-CSDN博客安装&#xff0c;其中的第六…...

xss csrf怎么预防?

一、XSS&#xff08;跨站脚本攻击&#xff09;预防 XSS 是指攻击者向目标网站注入恶意脚本&#xff0c;从而在用户浏览器中执行。 1. 输入过滤 清理用户输入&#xff1a; 拦截或清理HTML特殊字符&#xff08;如 <, >, , ", &&#xff09;。使用安全库&#x…...

near-synonym反义词生成(2):Prompt +Bert-MLM(FT)

near-synonym之反义词生成方法二 near-synonym, 中文反义词/近义词/同义词(antonym/synonym)工具包. 方法一为(neg_antonym): Word2vec -> ANN -> NLI -> Length 方法二为(mlm_antonym): Prompt Bert-MLM(FT) Beam-Search 项目地址 github: https://github.com/yon…...

【服务器项目部署】⭐️将本地项目部署到服务器!

目录 &#x1f378;前言 &#x1f37b;一、服务器选择 &#x1f379; 二、服务器环境部署 2.1 java 环境部署 2.2 mysql 环境部署 &#x1f378;三、项目部署 3.1 静态页面调整 3.2 服务器端口开放 3.3 项目部署 ​ &#x1f379;四、测试 &#x1f378;前言 小伙伴们大家好…...

Neo4j Desktop无法打开

解决方案——断网 9号——周一早上就开始打不开&#xff0c;后面去他官网找解决方案&#xff0c;看他们老外解决方法都是重新安装&#xff0c;但是都没彻底解决&#xff0c;我试着重新下载安装桌面版&#xff1a;1.6.1版本&#xff0c;9号晚上7.30的时候经过两次重新安装可以打…...

【编程语言】Kotlin快速入门 - 泛型

Kotlin的泛型与Java十分类似&#xff0c;也是使用这种的语法结构&#xff1a; class Fruit<T> {fun eat(f : T): Unit {println("eat...")}fun <T> buy(p : T): T {return p} }泛型限制 和Java一样&#xff0c;Kotlin也允许泛型是某个类的子类 fun &l…...

【PostgreSQL】入门篇——在不同操作系统上安装 PostgreSQL

PostgreSQL在 Windows、macOS 和 Linux&#xff08;以 Ubuntu 为例&#xff09;的安装步骤&#xff0c;以及可能出现的问题和解决办法。 一、在 Windows 上安装 PostgreSQL 1. 下载 PostgreSQL 安装程序 访问 PostgreSQL 官方网站&#xff1a;PostgreSQL Downloads点击“Dow…...

【Docker】部署MySQL容器

关于docker&#xff0c;Windows上使用Powershell/CMD执行指令&#xff0c;Linux系统直接使用终端执行指令。 拉取MySQL 也可以跳过拉取步骤&#xff0c;直接run&#xff0c;这样本地容器不存在的话&#xff0c;会自动拉取最新/指定的版本。 # 默认拉取最新版本 docker pull …...

mysql9.0windows安装

第一步下载 官网地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 点击后&#xff0c;选择不登录下载 第二步安装 双击下载的msi文件进行安装。打开后页面如下&#xff0c;选择安装类型&#xff0c;选择自定义安装。点击Next下一步。 自行选择安装目录 选好后点击…...

word中文献引用[]符号的上下标格式修改

word中文献引用[]符号的上下标格式修改 百度网址 1、查找打开使用通配符&#xff0c;输入[[][0-9]{1,2}[]]&#xff0c;即可匹配所有的字[1],[12]这些字符&#xff0c;然后鼠标点击替换为的空白处&#xff0c;再点击特殊格式–>“字体”&#xff0c;选中上标&#xff0c;最…...