HarmonyOS NEXT应用开发边学边玩系列:从零实现一影视APP (四、最近上映电影滚动展示及加载更多的实现)

news/2025/1/16 9:37:01/

在HarmonyOS NEXT开发环境中,可以使用多种组件和库来构建丰富且交互友好的应用。本文将展示如何使用HarmonyOS NEXT框架和nutpi/axios库,从零开始实现一个简单的影视APP的首页,主要关注最近上映电影的滚动展示及加载更多功能的实现。

开源项目地址:https://atomgit.com/csdn-qq8864/hmmovie

好的作品是需要不断打磨的,在你的学习和体验过程中有任何问题,欢迎到我的开源项目代码仓下面提交issue,持续优化。

安装nutpi/axios

首先,需要在项目中安装nutpi/axios库。

ohpm install @ohos/axios

在这里插入图片描述

实现最近上映电影接口

使用nutpi/axios库来实现最近上映电影的接口请求。接口请求如下:

import {axiosClient,HttpPromise} from '../../utils/axiosClient';
import { HotMovieReq, MovieRespData, SwiperData } from '../bean/ApiTypes';// 1.获取轮播图接口
export const getSwiperData = (): HttpPromise<SwiperData> => axiosClient.get({url:'/swiperdata'});// 2.获取即将上映影视接口
export const getSoonMovie = (start:number,count:number): HttpPromise<MovieRespData> => axiosClient.post({url:'/soonmovie',data: { start:start,count:count }});// 3.获取热门影视接口
export const getHotMovie = (req:HotMovieReq): HttpPromise<MovieRespData> => axiosClient.post({url:'/hotmovie',data:req});

代码讲解

  1. 创建axios客户端:创建了一个axios客户端axiosClient,并设置了基础URL和请求超时时间。
  2. 定义接口函数getSoonMovies函数向接口发送GET请求以获取最近上映的电影数据,并返回一个Promise对象。

实现首页组件

接下来,将实现首页组件,包括最近上映电影的滚动展示和加载更多功能。

import { getSoonMovies } from '../../common/api/movie';
import { MovieItem } from '../../common/bean/MovieItem';
import { Log } from '../../utils/logutil';
import { NavPathStack } from '@ohos.router';
import { BusinessError } from '@kit.BasicServicesKit';@Builder
export function HomePageBuilder() {HomePage()
}@Component
struct HomePage {pageStack: NavPathStack = new NavPathStack()@State soonMvList: MovieItem[] = []// 组件生命周期aboutToAppear() {Log.info('HomePage aboutToAppear');this.fetchSoonMovies();}// 获取最近上映电影数据fetchSoonMovies() {getSoonMovies().then((res) => {Log.debug(res.data.message)Log.debug("request", "res.data.code:%{public}d", res.data.code)if (res.data.code == 0) {this.soonMvList = res.data.data}}).catch((err: BusinessError) => {Log.debug("request", "err.data.code:%d", err.code)Log.debug("request", err.message)});}build() {Column({ space: 0 }) {Flex({direction: FlexDirection.Row,justifyContent: FlexAlign.SpaceBetween,alignContent: FlexAlign.SpaceBetween}) {Text('即将上映').fontWeight(FontWeight.Bold)Text('加载更多 >>').fontSize(14).fontColor(Color.Black).onClick(() => {this.pageStack.pushDestinationByName("MovieMorePage", { types: 1 }).catch((e: Error) => {console.log(`catch exception: ${JSON.stringify(e)}`)}).then(() => {// 跳转成功});})}.padding(10)Scroll() {Row({ space: 5 }) {ForEach(this.soonMvList, (item: MovieItem) => {Column({ space: 0 }) {Image(item.cover).objectFit(ImageFit.Auto).height(160).borderRadius(5).onClick(() => {this.pageStack.pushDestinationByName("MovieDetailPage", { id: item.id }).catch((e: Error) => {console.log(`catch exception: ${JSON.stringify(e)}`)}).then(() => {// 跳转成功});})Text(item.title).alignSelf(ItemAlign.Center).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }).width(100).fontSize(14).fontWeight(FontWeight.Bold).padding(10)}.justifyContent(FlexAlign.Center)}, (itm: MovieItem) => itm.id)}}.scrollable(ScrollDirection.Horizontal)}.width('100%').height('100%')}
}

代码讲解

  1. 导入模块:导入了之前定义的getSoonMovies函数,以及一些其他必要的模块。
  2. 定义组件状态
    • soonMvList:用于存储最近上映电影的数据。
  3. 组件生命周期
    • aboutToAppear:组件即将出现在页面时执行的日志记录,并调用fetchSoonMovies函数获取数据。
  4. 构建页面
    • Column:垂直布局容器。
    • Flex:弹性布局容器,用于布局“即将上映”和“加载更多”按钮。
      • Text('即将上映'):显示“即将上映”标题。
      • Text('加载更多 >>'):显示“加载更多”按钮,并设置点击事件,点击时导航到加载更多页面。
    • Scroll:滚动容器,设置为水平滚动。
      • Row:水平布局容器,用于放置电影项。
      • ForEach:遍历soonMvList数组,为每个电影项创建一个Column
        • Column:垂直布局容器,用于放置电影的图片和标题。
          • Image:显示电影封面图片,并设置点击事件,点击时导航到电影详情页面。
          • Text:显示电影标题,并设置样式。

配置路由

为了实现页面跳转,需要在entry/src/main/resources/base/profile路径下的route_map.json文件中配置路由。

{"routerMap": [{"name": "HomePage","pageSourceFile": "src/main/ets/pages/home/Home.ets","buildFunction": "HomePageBuilder","data": {"description": "this is HomePage"}},{"name": "MovieMorePage","pageSourceFile": "src/main/ets/pages/home/MovieMore.ets","buildFunction": "MovieMorePageBuilder","data": {"description": "this is MovieMorePage"}},{"name": "MovieDetailPage","pageSourceFile": "src/main/ets/pages/home/Detail.ets","buildFunction": "MovieDetailPageBuilder","data": {"description": "this is MovieDetailPage"}}]
}

代码讲解

  1. 配置路由
    • HomePage:配置首页的路由信息。
    • MovieMorePage:配置加载更多页面的路由信息。
    • MovieDetailPage:配置电影详情页面的路由信息。

涉及到的常用组件

Flex

Flex组件用于创建弹性布局容器,可以控制子组件的排列方式和对齐方式。

Flex({direction: FlexDirection.Row,justifyContent: FlexAlign.SpaceBetween,alignContent: FlexAlign.SpaceBetween
}) {Text('即将上映').fontWeight(FontWeight.Bold)Text('加载更多 >>').fontSize(14).fontColor(Color.Black)
}

Scroll

Scroll组件用于创建可滚动的容器,可以设置滚动方向为水平或垂直。

Scroll() {Row({ space: 5 }) {ForEach(this.soonMvList, (item: MovieItem) => {Column({ space: 0 }) {Image(item.cover).objectFit(ImageFit.Auto).height(160).borderRadius(5)}}, (itm: MovieItem) => itm.id)}
}.scrollable(ScrollDirection.Horizontal)

ForEach

ForEach组件用于遍历数组并为每个元素生成一个子组件。

ForEach(this.soonMvList, (item: MovieItem) => {Column({ space: 0 }) {Image(item.cover).objectFit(ImageFit.Auto).height(160).borderRadius(5)}
}, (itm: MovieItem) => itm.id)

Image

Image组件用于显示图片,可以设置图片的显示方式、大小和形状。

Image(item.cover).objectFit(ImageFit.Auto).height(160).borderRadius(5)

Text

Text组件用于显示文本,可以设置文本的大小、颜色、对齐方式等。

Text(item.title).fontSize(14).fontWeight(FontWeight.Bold).padding(10)

ColumnRow

ColumnRow组件分别用于创建垂直和水平布局容器。

Column({ space: 0 }) {// 子组件
}Row({ space: 5 }) {// 子组件
}

onClick

onClick事件用于处理组件的点击事件。

Text('加载更多 >>').fontSize(14).fontColor(Color.Black).onClick(() => {this.pageStack.pushDestinationByName("MovieMorePage", { types: 1 }).catch((e: Error) => {console.log(`catch exception: ${JSON.stringify(e)}`)}).then(() => {// 跳转成功});})

总结

通过本文,展示了如何使用HarmonyOS NEXT框架和nutpi/axios库来实现一个简单的影视APP的首页,包括最近上映电影的滚动展示和加载更多功能。nutpi/axios库的使用大大简化了网络请求的操作,使代码更加简洁易读。同时,还介绍了涉及到的常用组件的使用方法。

希望这篇文章对你有所帮助,让你在开发HarmonyOS NEXT应用时更加得心应手。如果你有任何问题或建议,欢迎在评论区留言交流!

参考代码

以下是完整的HomePage组件代码:


import { Log } from '../../utils/logutil';
import { BusinessError } from '@kit.BasicServicesKit';
import { router } from '@kit.ArkUI';
import { MovieItem, SwiperItem } from '../../common/bean/ApiTypes';
import { getHotMovie, getHotTv,getMvTop250,getNewMovie,getPiaoMovie,getSoonMovie, getSwiperData, getUsHotMv } from '../../common/api/movie';
import { PiaoFangRespData } from '../../common/bean/PiaoFangResp';class BasicDataSource<T> implements IDataSource {private listeners: DataChangeListener[] = [];private originDataArray: T[] = [];totalCount(): number {return this.originDataArray.length;}getData(index: number): T {return this.originDataArray[index];}registerDataChangeListener(listener: DataChangeListener): void {if (this.listeners.indexOf(listener) < 0) {this.listeners.push(listener);}}unregisterDataChangeListener(listener: DataChangeListener): void {const pos = this.listeners.indexOf(listener);if (pos >= 0) {this.listeners.slice(pos, 1);}}// 通知LazyForEach组件需要重新重载所有子组件notifyDataReload(): void {this.listeners.forEach(listener => {listener.onDataReloaded();})}// 通知LazyForEach组件需要在index对应索引处添加子组件notifyDataAdd(index: number): void {this.listeners.forEach(listener => {listener.onDataAdd(index);})}
}class SwiperDataSource<T> extends BasicDataSource<T> {private dataArray: T[] = [];totalCount(): number {return this.dataArray.length;}getData(index: number): T {return this.dataArray[index];}// 在列表末尾添加数据并通知监听器pushData(data: T): void {this.dataArray.push(data);this.notifyDataAdd(this.dataArray.length - 1);}// 重载数据reloadData(): void {// 不会引起状态变化this.dataArray = [];// 必须通过DataChangeListener来更新this.notifyDataReload();}
}@Component
export default struct Home {@Consume pageStack: NavPathStackprivate swiperController: SwiperController = new SwiperController()private swiperData: SwiperDataSource<SwiperItem> = new SwiperDataSource()@State soonMvList:MovieItem[]=[]@State hotMvList:MovieItem[]=[]@State hotTvList:MovieItem[]=[]@State usMvList:MovieItem[]=[]@State topMvList:MovieItem[]=[]@State piaoList:PiaoFangRespData[]=[]// 组件生命周期aboutToAppear() {Log.info('Home aboutToAppear');getSwiperData().then((res) => {Log.debug(res.data.message)Log.debug("request","res.data.code:%{public}d",res.data.code)for (const itm of res.data.data) {this.swiperData.pushData(itm)}}).catch((err: BusinessError) => {Log.debug("request","err.data.code:%d",err.code)Log.debug("request",err.message)});getPiaoMovie().then((res) => {Log.debug(res.data.message)for (const itm of res.data.data) {this.piaoList.push(itm)}}).catch((err: BusinessError) => {Log.debug("request","err.data.code:%d",err.code)Log.debug("request",err.message)});getSoonMovie(1,10).then((res) => {Log.debug(res.data.message)Log.debug("request","res.data.code:%{public}d",res.data.code)for (const itm of res.data.data) {this.soonMvList.push(itm)}}).catch((err: BusinessError) => {Log.debug("request","err.data.code:%d",err.code)Log.debug("request",err.message)});getHotMovie({start:1,count:10,city:'郑州'}).then((res) => {Log.debug(res.data.message)Log.debug("request","res.data.code:%{public}d",res.data.code)for (const itm of res.data.data) {this.hotMvList.push(itm)}}).catch((err: BusinessError) => {Log.debug("request","err.data.code:%d",err.code)Log.debug("request",err.message)});getHotTv(1,10).then((res) => {Log.debug(res.data.message)Log.debug("request","res.data.code:%{public}d",res.data.code)for (const itm of res.data.data) {this.hotTvList.push(itm)}}).catch((err: BusinessError) => {Log.debug("request","err.data.code:%d",err.code)Log.debug("request",err.message)});getUsHotMv(1,10).then((res) => {Log.debug(res.data.message)Log.debug("request","res.data.code:%{public}d",res.data.code)for (const itm of res.data.data) {this.usMvList.push(itm)}}).catch((err: BusinessError) => {Log.debug("request","err.data.code:%d",err.code)Log.debug("request",err.message)});getMvTop250(1,10).then((res) => {Log.debug(res.data.message)for (const itm of res.data.data) {this.topMvList.push(itm)}}).catch((err: BusinessError) => {Log.debug("request","err.data.code:%d",err.code)Log.debug("request",err.message)});}// 组件生命周期aboutToDisappear() {Log.info('Home aboutToDisappear');}build() {Scroll() {Column({ space: 0 }) {//titleFlex({direction: FlexDirection.Row,justifyContent: FlexAlign.SpaceBetween,alignContent: FlexAlign.SpaceBetween}){Blank().width(40)Text('爱影家').fontSize(26).fontWeight(FontWeight.Bold)Image($r('app.media.search')).width(42).height(42).padding({bottom:8}).onClick(() => {this.pageStack.pushDestinationByName("SearchPage", { }).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})}.padding(10).width('100%').height(50)// 轮播图Swiper(this.swiperController) {LazyForEach(this.swiperData, (item: SwiperItem) => {Stack({ alignContent: Alignment.Center }) {Image(item.imageUrl).width('100%').height(180).zIndex(1).onClick(() => {this.pageStack.pushDestinationByName("MovieDetailPage", { id:item.id }).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})// 显示轮播图标题Text(item.title).padding(5).margin({ top: 135 }).width('100%').height(60).textAlign(TextAlign.Center).maxLines(2).textOverflow({ overflow: TextOverflow.Clip }).fontSize(22).fontColor(Color.White).opacity(100)// 设置标题的透明度 不透明度设为100%,表示完全不透明.backgroundColor('#808080AA')// 背景颜色设为透明.zIndex(2).onClick(() => {this.pageStack.pushDestinationByName("MovieDetailPage", { id:item.id }).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})}}, (item: SwiperItem) => item.id)}.cachedCount(2).index(1).autoPlay(true).interval(4000).loop(true).indicatorInteractive(true).duration(1000).itemSpace(0).curve(Curve.Linear).onChange((index: number) => {console.info(index.toString())}).onGestureSwipe((index: number, extraInfo: SwiperAnimationEvent) => {console.info("index: " + index)console.info("current offset: " + extraInfo.currentOffset)}).height(180) // 设置高度Text('今日票房').fontWeight(FontWeight.Bold).padding(10).alignSelf(ItemAlign.Start)Scroll() {Row({ space: 5 }) {ForEach(this.piaoList, (item: PiaoFangRespData,idx) => {Column({ space: 2 }) {Text(idx.toString()).fontSize(20).fontColor(Color.Orange)Text(item.name).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }).fontSize(14).fontWeight(FontWeight.Bold).alignSelf(ItemAlign.Center).padding(5)Text(item.release_date).fontSize(12).fontColor(Color.White).alignSelf(ItemAlign.Center)Text('票房:'+item.box_million).fontSize(12).fontColor(Color.White).alignSelf(ItemAlign.Center)Text('占比:'+item.share_box).fontSize(12).fontColor(Color.White).alignSelf(ItemAlign.Center)}.width(120).height(120).backgroundColor('rgba(85, 170, 255, 0.60)').borderRadius(5).justifyContent(FlexAlign.Center)}, (itm: PiaoFangRespData, idx) => itm.name)}}.scrollable(ScrollDirection.Horizontal)Flex({direction: FlexDirection.Row,justifyContent: FlexAlign.SpaceBetween,alignContent: FlexAlign.SpaceBetween}) {Text('即将上映').fontWeight(FontWeight.Bold)Text('加载更多 >>').fontSize(14).fontColor(Color.Black) .onClick(() => {this.pageStack.pushDestinationByName("MovieMorePage", {types:1}).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})}.padding(10)Scroll() {Row({ space: 5 }) {ForEach(this.soonMvList, (item: MovieItem) => {Column({ space: 0 }) {Image(item.cover).objectFit(ImageFit.Auto).height(160).borderRadius(5).onClick(() => {this.pageStack.pushDestinationByName("MovieDetailPage", { id:item.id }).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})Text(item.title).alignSelf(ItemAlign.Center).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }).width(100).fontSize(14).fontWeight(FontWeight.Bold).padding(10)}.justifyContent(FlexAlign.Center)}, (itm: MovieItem, idx) => itm.id)}}.scrollable(ScrollDirection.Horizontal)Flex({direction: FlexDirection.Row,justifyContent: FlexAlign.SpaceBetween,alignContent: FlexAlign.SpaceBetween}) {Text('热映电影').fontWeight(FontWeight.Bold)Text('加载更多 >>').fontSize(14).fontColor(Color.Black) .onClick(() => {this.pageStack.pushDestinationByName("MovieMorePage", {types:2}).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})}.padding(10)Scroll() {Row({ space: 5 }) {ForEach(this.hotMvList, (item: MovieItem) => {Column({ space: 0 }) {Image(item.cover).objectFit(ImageFit.Auto).height(160).borderRadius(5).onClick(() => {this.pageStack.pushDestinationByName("MovieDetailPage", { id:item.id }).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})Text(item.title).alignSelf(ItemAlign.Center).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }).width(100).fontSize(14).fontWeight(FontWeight.Bold).padding(10)}.justifyContent(FlexAlign.Center)}, (itm: MovieItem, idx) => itm.id)}}.scrollable(ScrollDirection.Horizontal)// Flex({//   direction: FlexDirection.Row,//   justifyContent: FlexAlign.SpaceBetween,//   alignContent: FlexAlign.SpaceBetween// }) {//   Text('热门资讯').fontWeight(FontWeight.Bold)//   Text('加载更多 >>').fontSize(14).fontColor(Color.Black) .onClick(() => {////   })// }.padding(10)Flex({direction: FlexDirection.Row,justifyContent: FlexAlign.SpaceBetween,alignContent: FlexAlign.SpaceBetween}) {Text('热门剧集').fontWeight(FontWeight.Bold)Text('加载更多 >>').fontSize(14).fontColor(Color.Black) .onClick(() => {this.pageStack.pushDestinationByName("MovieMorePage", {types:3}).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})}.padding(10)Scroll() {Row({ space: 5 }) {ForEach(this.hotTvList, (item: MovieItem) => {Column({ space: 0 }) {Image(item.cover).objectFit(ImageFit.Auto).height(160).borderRadius(5).onClick(() => {this.pageStack.pushDestinationByName("MovieDetailPage", { id:item.id }).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})Text(item.title).alignSelf(ItemAlign.Center).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }).width(100).fontSize(14).fontWeight(FontWeight.Bold).padding(10)}.justifyContent(FlexAlign.Center)}, (itm: MovieItem, idx) => itm.id)}}.scrollable(ScrollDirection.Horizontal)Flex({direction: FlexDirection.Row,justifyContent: FlexAlign.SpaceBetween,alignContent: FlexAlign.SpaceBetween}) {Text('豆瓣排行榜').fontWeight(FontWeight.Bold)Text('加载更多 >>').fontSize(14).fontColor(Color.Black) .onClick(() => {this.pageStack.pushDestinationByName("MovieMorePage", {types:4}).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})}.padding(10)Scroll() {Row({ space: 5 }) {ForEach(this.topMvList, (item: MovieItem) => {Column({ space: 0 }) {Image(item.cover).objectFit(ImageFit.Auto).height(160).borderRadius(5).onClick(() => {this.pageStack.pushDestinationByName("MovieDetailPage", { id:item.id }).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})Text(item.title).alignSelf(ItemAlign.Center).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }).width(100).fontSize(14).fontWeight(FontWeight.Bold).padding(10)}.justifyContent(FlexAlign.Center)}, (itm: MovieItem, idx) => itm.id)}}.scrollable(ScrollDirection.Horizontal)Flex({direction: FlexDirection.Row,justifyContent: FlexAlign.SpaceBetween,alignContent: FlexAlign.SpaceBetween}) {Text('北美票房榜').fontWeight(FontWeight.Bold)Text('加载更多 >>').fontSize(14).fontColor(Color.Black) .onClick(() => {this.pageStack.pushDestinationByName("MovieMorePage", {types:5}).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})}.padding(10)Scroll() {Row({ space: 5 }) {ForEach(this.usMvList, (item: MovieItem) => {Column({ space: 0 }) {Image(item.cover).objectFit(ImageFit.Auto).height(160).borderRadius(5).onClick(() => {this.pageStack.pushDestinationByName("MovieDetailPage", { id:item.id }).catch((e:Error)=>{// 跳转失败,会返回错误码及错误信息console.log(`catch exception: ${JSON.stringify(e)}`)}).then(()=>{// 跳转成功});})Text(item.title).alignSelf(ItemAlign.Center).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }).width(100).fontSize(14).fontWeight(FontWeight.Bold).padding(10)}.justifyContent(FlexAlign.Center)}, (itm: MovieItem, idx) => itm.id)}}.scrollable(ScrollDirection.Horizontal)}.width('100%')}.width('100%').height('100%').scrollable(ScrollDirection.Vertical)}
}

作者介绍

作者:csdn猫哥

原文链接:https://blog.csdn.net/yyz_1987

团队介绍

坚果派团队由坚果等人创建,团队拥有12个华为HDE带领热爱HarmonyOS/OpenHarmony的开发者,以及若干其他领域的三十余位万粉博主运营。专注于分享HarmonyOS/OpenHarmony、ArkUI-X、元服务、仓颉等相关内容,团队成员聚集在北京、上海、南京、深圳、广州、宁夏等地,目前已开发鸿蒙原生应用和三方库60+,欢迎交流。

版权声明

本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。


http://www.ppmy.cn/news/1563558.html

相关文章

CSS的小知识

一、子选择器 (>) 让 CSS 样式只作用于子级和孙级元素&#xff0c;而不影响其他元素 有>是只对其子级有效&#xff0c;子选择器只会影响直接的子级元素&#xff0c;而不会影响更深层次的孙级元素 无>时是对子级、孙级、曾孙级等所有后代都有效

我在2025年自学网络安全(黑客)

当我们谈论网络安全时&#xff0c;我们正在讨论的是保护我们的在线空间&#xff0c;这是我们所有人的共享责任。网络安全涉及保护我们的信息&#xff0c;防止被未经授权的人访问、披露、破坏或修改。 一、网络安全的基本概念 网络安全是一种保护&#xff1a;它涉及保护我们的…

栈算法篇——LIFO后进先出,数据与思想的层叠乐章(上)

文章目录 前言第一章&#xff1a;栈的基础知识回顾1.1 栈的结构与实现1.2 栈的应用第二章&#xff1a;删除字符串中的所有相邻重复项2.1 题目链接&#xff1a;https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/description/2.2 题目分析&#xff1a;2.3…

刷题记录 回溯算法-13:90. 子集 II

题目&#xff1a;90. 子集 II 给你一个整数数组 nums &#xff0c;其中可能包含重复元素&#xff0c;请你返回该数组所有可能的 子集 &#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。返回的解集中&#xff0c;子集可以按 任意顺序 排列。 示例 1&#xff1a; …

钉钉消息推送()

记录一下java实现消息推送 1. 首先添加依赖 <dependencies><dependency><groupId>com.aliyun</groupId><artifactId>alibaba-dingtalk-service-sdk</artifactId><version>2.0.0</version></dependency><dependency&…

Python Chardet 库详解:字符编码检测的利器

Python Chardet 库详解&#xff1a;字符编码检测的利器 在处理文本数据时&#xff0c;字符编码问题是一个常见的挑战。如果编码不正确&#xff0c;可能会导致乱码问题。而 Chardet 是 Python 中非常实用的一个库&#xff0c;可以帮助我们快速检测文件或字符串的编码格式。 1.…

【微服务】面试 2、服务雪崩

服务雪崩概念 主要内容&#xff1a;在微服务项目中&#xff0c;微服务间存在远程调用。若某一服务&#xff08;如服务 d&#xff09;出现故障&#xff0c;调用它的服务&#xff08;如服务 a&#xff09;会失败。若调用方持续向故障服务发起请求&#xff0c;由于服务连接数有限且…

2025Paypal取消到期自动续费(循环付款)教程

今天订阅了PixivFanbox&#xff0c;怎么取消自动订阅&#xff0c;防止大家被坑&#xff0c;就开个帖子&#xff0c;即便在Fanbox取消订阅&#xff0c;发现Paypal的自动订阅还在&#xff0c;防止万一还是两边都取消掉。 打开paypal>>找到工具>>找到批准付款 显示的…