如何使用ArkUI从0-1写一个开发购物应用程序(下)

接下来我们继续学习如何用ArkUI来开发一个购物应用程序(下半部分)

底部组件是由一个横向的图片列表组成,iconPath是底部初始状态下的3张图片路径数组。遍历iconPath数组,使用Image组件设置图片路径并添加到List中,给每个Image组件设置点击事件,点击更换底部3张图片。在HomeBottom中,iconPath使用的是@State修饰,当iconPath数组内容变化时,页面组件有使用到的地方都会随之发生变化。

在MyPage.ets文件中新建MyTransList组件和MoreGrid组件,MyTransList组件代码如下:

@Component
struct MyTransList {private imageItems: ImageItem[] = getTrans()build() {Column() {Text('My Transaction').fontSize(20).margin({ left: 10 }).width('100%').height(30)Row() {List() {ForEach(this.imageItems, item => {ListItem() {DataItem({ imageItem: item })}}, item => item.id.toString())}.height(70).width('100%').align(Alignment.Top).margin({ top: 5}).listDirection(Axis.Horizontal)}}.height(120)}
}

MoreGrid组件代码如下:

@Component
struct MoreGrid {private gridRowTemplate: string = ''private imageItems: ImageItem[] = getMore()private heightValue: numberaboutToAppear() {var rows = Math.round(this.imageItems.length / 3);this.gridRowTemplate = '1fr '.repeat(rows);this.heightValue = rows * 75 ;}build() {Column() {Text('More').fontSize(20).margin({ left: 10 }).width('100%').height(30)Scroll() {Grid() {ForEach(this.imageItems, (item: ImageItem) => {GridItem() {DataItem({ imageItem: item })}}, (item: ImageItem) => item.id.toString())}.rowsTemplate(this.gridRowTemplate).columnsTemplate('1fr 1fr 1fr').columnsGap(8).rowsGap(8).height(this.heightValue)}.padding({ left: 16, right: 16 })}.height(400)}
}

在MyTransList和MoreGrid组件中都包含子组件DataItem,为避免的重复代码,可以把多次要用到的结构体组件化,这里的结构体就是图片加上文本的上下结构体,DataItem组件内容如下:

@Component
struct MenuItem {private menu: Menubuild() {Column() {Text(this.menu.title).fontSize(15)Text(this.menu.num+'').fontSize(13)}.height(50).width(80).margin({left: 8,right:8}).alignItems(HorizontalAlign.Start).backgroundColor(Color.White)}
}

实现购物车页签

主界面购物车页签主要由下面三部分组成:

  • 顶部的Text组件。
  • 中间的List组件,其中List组件的item是一个水平的布局内包含一个toggle组件,一个Image组件和一个垂直布局,其item中的垂直布局是由2个Text组件组成。
  • 底部一个水平布局包含两个Text组件。

构建一个购物车页签,给商品列表的每个商品设置一个单选框,可以选中与取消选中,底部Total值也会随之增加或减少,点击Check Out时会触发弹窗。下面我们来完成ShoppingCart页签。

在pages目录下面新建一个Page ,命名为ShoppingCart.。在ShoppingCart.ets文件中添加入口组件(ShoppingCart),并导入需要使用到的数据实体类、方法和组件。ShoppingCart组件代码如下:

@Entry
@Component
export struct ShoppingCart {@Provide totalPrice : number =0private goodsItems: GoodsData[] = initializeOnStartup()build() {Column() {Column() {Text('ShoppingCart').fontColor(Color.Black).fontSize(25).margin({ left: 60,right:60 }).align(Alignment.Center)}.backgroundColor('#FF00BFFF').width('100%').height(30)ShopCartList({ goodsItems: this.goodsItems });ShopCartBottom()}.alignItems(HorizontalAlign.Start)}
}

新建ShopCartList组件用于存放购物车商品列表,ShopCartList组件代码如下

@Component
struct ShopCartList {private goodsItems: GoodsData[]build() {Column() {List() {ForEach(this.goodsItems, item => {ListItem() {ShopCartListItem({ goodsItem: item })}}, item => item.id.toString())}.height('100%').width('100%').align(Alignment.Top).margin({top: 5})}.height(570)}
}

ShopCartListItem组件代码如下:

@Component
struct ShopCartListItem {@Consume totalPrice: numberprivate goodsItem: GoodsDatabuild() {Row() {Toggle({type: ToggleType.Checkbox}).width(10).height(10).onChange((isOn:boolean) => {if(isOn){this.totalPrice +=parseInt(this.goodsItem.price+'',0)}else{this.totalPrice -= parseInt(this.goodsItem.price+'',0)}})Image(this.goodsItem.imgSrc).objectFit(ImageFit.ScaleDown).height(100).width(100).renderMode(ImageRenderMode.Original)Column() {Text(this.goodsItem.title).fontSize(14)Text('¥' + this.goodsItem.price).fontSize(14).fontColor(Color.Red)}}.height(100).width(180).margin({left: 20}).alignItems(VerticalAlign.Center).backgroundColor(Color.White)}
}

在ShopCartListItem中使用Toggle的单选框类型来实现每个item的选择和取消选择,在Toggle的onChage事件中来改变totalPrice的数值。

新建ShopCartBottom组件,ShopCartBottom组件代码如下:

@Component
struct ShopCartBottom {@Consume totalPrice: numberbuild() {Row() {Text('Total:  ¥'+this.totalPrice).fontColor(Color.Red).fontSize(18).margin({left:20}).width(150)Text('Check Out').fontColor(Color.Black).fontSize(18).margin({right:20,left:100}).onClick(()=>{prompt.showToast({message: 'Checking Out',duration: 10,bottom:100})})}.height(30).width('100%').backgroundColor('#FF7FFFD4').alignItems(VerticalAlign.Bottom)}
}

实现我的页签

我的页签主要由下面四部分组成:

  • 顶部的水平布局。
  • 顶部下面的文本加数字的水平List。
  • My Transactio模块,图片加文本的水平List。
  • More模块,图片加文本的Grid。

构建主页我的页签,主要可以划分成下面几步:

  • 在pages目录下面新建一个Page 命名为MyPage
  • 在MyPage.ets文件中添加入口组件(MyInfo)

MyInfo组件内容如下:

import {getMenu,getTrans,getMore} from '../model/GoodsDataModels'
import {Menu, ImageItem} from '../model/Menu'
@Entry
@Component
export struct MyInfo {build() {Column() {Row(){Image($rawfile('nav/icon-user.png')).margin({left:20}).objectFit(ImageFit.Cover).height(50).width(50).renderMode(ImageRenderMode.Original).margin({left:40,right:40})Column(){Text('John Doe').fontSize(15)Text('Member Name : John Doe                     >')}.height(60).margin({left:40,top:10}).alignItems(HorizontalAlign.Start)}TopList()MyTransList()MoreGrid()}.alignItems(HorizontalAlign.Start).width('100%').flexGrow(1)}
}

入口组件中还包含TopList,MyTransList和MoreGrid三个子组件。代码如下:

@Component
struct TopList {private menus: Menu[] = getMenu()build() {Row() {List() {ForEach(this.menus, item => {ListItem() {MenuItem({ menu: item })}}, item => item.id.toString())}.height('100%').width('100%').margin({top: 5}).edgeEffect(EdgeEffect.None).listDirection(Axis.Horizontal)}.width('100%').height(50)}
}
@Component
struct MyTransList {private imageItems: ImageItem[] = getTrans()build() {Column() {Text('My Transaction').fontSize(20).margin({ left: 10 }).width('100%').height(30)Row() {List() {ForEach(this.imageItems, item => {ListItem() {DataItem({ imageItem: item })}}, item => item.id.toString())}.height(70).width('100%').align(Alignment.Top).margin({ top: 5}).listDirection(Axis.Horizontal)}}.height(120)}
}
@Component
struct MoreGrid {private gridRowTemplate: string = ''private imageItems: ImageItem[] = getMore()private heightValue: numberaboutToAppear() {var rows = Math.round(this.imageItems.length / 3);this.gridRowTemplate = '1fr '.repeat(rows);this.heightValue = rows * 75 ;}build() {Column() {Text('More').fontSize(20).margin({ left: 10 }).width('100%').height(30)Scroll() {Grid() {ForEach(this.imageItems, (item: ImageItem) => {GridItem() {DataItem({ imageItem: item })}}, (item: ImageItem) => item.id.toString())}.rowsTemplate(this.gridRowTemplate).columnsTemplate('1fr 1fr 1fr').columnsGap(8).rowsGap(8).height(this.heightValue)}.padding({ left: 16, right: 16 })}.height(400)}
}

实现商品详情页面

商品详情页面主要由下面五部分组成:

  • 顶部的返回栏。
  • Swiper组件。
  • 中间多个Text组件组成的布局。
  • 参数列表。
  • 底部的Buy。

把上面每一部分都封装成一个组件,然后再放到入口组件内,当点击顶部返回图标时返回到主页面的商品列表页签,点击底部Buy时,会触发进度条弹窗。

在pages目录下面新建一个Page, 命名为ShoppingDetail。在ShoppingDetail.ets文件中创建入口组件,组件内容如下:

import router from '@system.router';
import {ArsData} from '../model/ArsData'
import {getArs,getDetailImages} from '../model/GoodsDataModels'
import prompt from '@system.prompt';
@Entry
@Component
struct ShoppingDetail {private arsItems: ArsData[] =  getArs()private detailImages: string[] = getDetailImages()build() {Column() {DetailTop()Scroll() {Column() {SwiperTop()DetailText()DetailArsList({ arsItems: this.arsItems })Image($rawfile('computer/computer1.png')).height(220).width('100%').margin({top:30})Image($rawfile('computer/computer2.png')).height(220).width('100%').margin({top:30})Image($rawfile('computer/computer3.png')).height(220).width('100%').margin({top:30})Image($rawfile('computer/computer4.png')).height(220).width('100%').margin({top:30})Image($rawfile('computer/computer5.png')).height(220).width('100%').margin({top:30})Image($rawfile('computer/computer6.png')).height(220).width('100%').margin({top:30})}.width('100%').flexGrow(1)}.scrollable(ScrollDirection.Vertical)DetailBottom()}.height(630)}
}

顶部DetailTop组件代码如下:

@Component
struct DetailTop{build(){Column(){Row(){Image($rawfile('detail/icon-return.png')).height(20).width(20).margin({ left: 20, right: 250 }).onClick(() => {router.push({uri: "pages/HomePage"})})}.width('100%').height(25).backgroundColor('#FF87CEEB')}.width('100%').height(30)}
}

SwiperTop组件代码如下:

@Component
struct SwiperTop{build() {Column() {Swiper() {Image($rawfile('computer/computer1.png')).height(220).width('100%')Image($rawfile('computer/computer2.png')).height(220).width('100%')Image($rawfile('computer/computer3.png')).height(220).width('100%')Image($rawfile('computer/computer4.png')).height(220).width('100%')Image($rawfile('computer/computer5.png')).height(220).width('100%')Image($rawfile('computer/computer6.png')).height(220).width('100%')}.index(0).autoPlay(true).interval(3000).indicator(true).loop(true).height(250).width('100%')}.height(250).width('100%')}
}

DetailText组件代码如下:

@Component
struct DetailText{build() {Column() {Row(){Image($rawfile('computer/icon-promotion.png')).height(30).width(30).margin({left:10})Text('Special Offer: ¥9999').fontColor(Color.White).fontSize(20).margin({left:10})}.width('100%').height(35).backgroundColor(Color.Red)Column(){Text('New Arrival: HUAWEI MateBook X Pro 2021').fontSize(15).margin({left:10}).alignSelf(ItemAlign.Start)Text('13.9-Inch, 11th Gen Intel® Core™ i7, 16 GB of Memory, 512 GB of Storage, Ultra-slim Business Laptop, 3K FullView Display, Multi-screen Collaboration, Emerald Green').fontSize(10).margin({left:10})Row(){Image($rawfile('nav/icon-buy.png')).height(15).width(15).margin({left:10})//TODO 暂不支持跑马灯组件,用Text代替Text('Limited offer').fontSize(10).fontColor(Color.Red).margin({left:100})}.backgroundColor(Color.Pink).width('100%').height(25).margin({top:10})Text(' Shipment:         2-day shipping').fontSize(13).fontColor(Color.Red).margin({left:10,top:5}).alignSelf(ItemAlign.Start)Text('    Ship To:         Hubei,Wuhan,China').fontSize(13).fontColor(Color.Red).margin({left:10,top:5}).alignSelf(ItemAlign.Start).onClick(()=>{prompt.showDialog({title:'select address',})})Text('Guarantee:         Genuine guaranteed').fontSize(13).margin({left:10,top:5}).alignSelf(ItemAlign.Start)}.height(150).width('100%')}.height(160).width('100%')}
}

DetailArsList组件代码如下:

@Component
struct DetailArsList{private arsItems: ArsData[]build() {Scroll() {Column() {List() {ForEach(this.arsItems, item => {ListItem() {ArsListItem({ arsItem: item })}}, item => item.id.toString())}.height('100%').width('100%').margin({ top: 5 }).listDirection(Axis.Vertical)}.height(200)}}
}

ArsListItem组件代码如下:

@Component
struct ArsListItem {private arsItem: ArsDatabuild() {Row() {Text(this.arsItem.title+" :").fontSize(11).margin({left:20}).flexGrow(1)Text( this.arsItem.content).fontSize(11).margin({right:20})}.height(14).width('100%').backgroundColor(Color.White)}
}

DetailBottom组件代码如下:

@Component
struct DetailBottom{@Provideprivate value : number=1dialogController : CustomDialogController = new CustomDialogController({builder: DialogExample({action: this.onAccept}),cancel: this.existApp,autoCancel: true});onAccept() {}existApp() {}build(){Column(){Text('Buy').width(40).height(25).fontSize(20).fontColor(Color.White).onClick(()=>{this.value=1this.dialogController.open()})}.alignItems(HorizontalAlign.Center).backgroundColor(Color.Red).width('100%').height(40)}
}

DialogExample自定义弹窗组件代码如下:

@CustomDialog
struct DialogExample {@Consumeprivate value : numbercontroller: CustomDialogController;action: () => void;build() {Column() {Progress({value: this.value++ >=100?100:this.value, total: 100, style: ProgressStyle.Eclipse}).height(50).width(100).margin({top:5})}.height(60).width(100)}
}

添加资源文件

程序中所用到的资源文件都放置到resources\rawfile目录下。

删除index.ets

因为程序的入口文件已经改为了HomePage.ets文件,因此需要删除Index.ets文件。

HomePage.ets文件重新命名

把HomePage.ets文件重新命名为Index.ets文件。

程序运行效果

以上内容是介绍了如何用ArkUI来开发一个购物应用程序全部教程

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了几套最新版的HarmonyOS NEXT学习资源

获取完整版高清学习路线,请点击→《HarmonyOS教学视频

HarmonyOS教学视频

鸿蒙语法ArkTS、TypeScript、ArkUI等…视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取白皮书:请点击→《鸿蒙生态应用开发白皮书V2.0PDF

在这里插入图片描述

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. .……

在这里插入图片描述


二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

在这里插入图片描述

三、如何快速入门?《鸿蒙基础入门学习指南》

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. .……

在这里插入图片描述


四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. .……

在这里插入图片描述


五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 7.网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. .……

在这里插入图片描述


更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册

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

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

相关文章

【RabbitMQ】【Docker】基于docker-compose构建rabbitmq容器

本文通过docker-compose构建一个单体的rabbtimq容器。 1,docker、docker-compose环境 首先需要有docker和docker-compose环境,docker安装[1],docker-compose安装[2]。 通过下列命令确定docker、docker-compose是否安装成功。 [root192 ge…

【大屏设计】如何进行软件系统网站大屏页面设计?不限于智慧城市、物联网、电商、园区领域

【大屏设计】如何进行软件系统网站大屏页面设计?不限于智慧城市、物联网、电商、园区领域 一、什么是网站大屏设计二、网站大屏设计原型素材三、网站大屏设计设计素材四、他山之石 一、什么是网站大屏设计 网站大屏设计是网站设计中至关重要的一部分,因…

8种Kubernetes集群中Pod处于 Pending状态的故障排除方法

文章目录 一、Pod与容器二、Pod的阶段(状态)三、Pod 状态故障排除3.1 检查 Pod 事件3.2 检查资源可用性3.3 检查污点和容忍度3.4 检查节点亲和性设置3.5 检查持久卷声明3.6 检查配额和限制3.7 验证 Pod 和容器映像3.8 分析调度程序日志 四、用于排查 Pen…

Django动态路由实例

Django动态路由实例 先说需求&#xff1a; 比如我前端有两个按钮&#xff0c;点击按钮1跳转到user1的用户信息页面&#xff0c;按钮2跳转user2用户信息页面&#xff0c;但是他俩共用同一个视图层 直接上代码 路由层 urlpatterns [path(user/<str:username>/, views…

Swift 结构化并发之全局 Actor 趣谈

概览 在 Swift 结构化并发构成的体系中,一个称为“演员”(Actor)的成员扮演了非常重要的角色,它被用来隔离和同步执行中的数据。 除了普通 Actor 以外,还有一个全局“演员”(Global Actor)的概念,它是做什么的?又有什么与众不同的长处呢? 在本篇博文中,您将学到如…

通过ETL工具快速实现单据同步

ETLCloud介绍 ETLCloud是一款旨在解决企业数据集成挑战的最新一代平台&#xff0c;它集成了离线数据集成ETL、ELT、CDC实时数据集成、编排调度和数据服务API等功能&#xff0c;形成了一体化的DataOps数据集成平台。该平台提供私有化部署以及云原生架构&#xff0c;能够满足企业…

设计模式深度解析:适配器模式与桥接模式-灵活应对变化的两种设计策略大比拼

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 适配器模式与桥接模式-灵活应对变化的两种设计策略大比拼 探索设计模式的魅力&#xff1a;深入了…

ElasticSearch - 基本操作

前言 本文记录 ES 的一些基本操作&#xff0c;就是对官方文档的一些整理&#xff0c;按自己的习惯重新排版&#xff0c;凑合着看。官方的更详细&#xff0c;建议看官方的。 下文以 books 为索引名举例。 新增 添加单个文档 (没有索引会自动创建) POST books/_doc {"n…

Linux--Ubuntu安装

Linux操作系统时程序员必须要学的操作系统。接下来我们就来看一下Linux操作系统是如何安装的 我们在 Vmware 虚拟机中安装 linux 系统&#xff0c;所以需要先安装 vmware 软件&#xff0c;然后再 安装 Linux 系统。 一.所需安装文件&#xff1a; Vmware 下载地址(现在最新版的…

羊大师揭秘,孩子适不适合喝羊奶?

羊大师揭秘&#xff0c;孩子适不适合喝羊奶&#xff1f; 羊奶&#xff0c;这个古老而珍贵的营养饮品&#xff0c;近年来在家长们中间逐渐走红。它以其独特的营养价值和口感受到了众多家庭的青睐。但是&#xff0c;面对市面上琳琅满目的羊奶产品&#xff0c;家长们常常陷入选择…

三连杆滑块机构运动学仿真 | 【Matlab源码+理论公式文本】|曲柄滑块 | 曲柄连杆 | 机械连杆

【程序简介】&#x1f4bb;&#x1f50d; 本程序通过matlab实现了三连杆滑块机构的运动学仿真编程&#xff0c;动态展现了三连杆机构的运动动画&#xff0c;同时给出了角位移、角速度和角加速度的时程曲线&#xff0c;除了程序本身&#xff0c;还提供了机构运动学公式推导文档…

网络——入门基础

目录 协议 网络协议 OSI七层模型 网络传输基本流程 网络传输流程图 局域网通信 数据包的封装和解包 广域网通信 网络地址管理 IP地址 MAC地址 协议 关于什么是局域网&#xff0c;什么是广域网&#xff0c;我这里就不过多赘述了&#xff0c;我们直接来谈一下什么…

【链表】Leetcode 24. 两两交换链表中的节点【中等】

两两交换链表中的节点 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例1: 输入&#xff1a;head [1,2,3,4] 输出&#…

用连续自然数之和来表达整数 - 华为OD统一考试(C卷)

OD统一考试(C卷) 分值: 100分 题解: Java / Python / C++ 题目描述 一个整数可以由连续的自然数之和来表示。给定一个整数,计算该整数有几种连续自然数之和的表达式,且打印出每种表达式。 输入描述 一个目标整数T (1 <=T<= 1000) 输出描述 该整数的所有表达式…

java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics

今天在使用springBoot连接influxdb报错 java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics 详细报错如下&#xff0c;提出我们缺少一个依赖 原因是由于创建influxdb客户端缺少Kotlin运行时库 解决办法就是 1.显示的添加okhttp的依赖 <dependency>…

my2sql —— go语言版binlog解析及闪回工具

之前学习过python语言版binlog解析及闪回工具 MySQL闪回工具简介 及 binlog2sql工具用法 最近听同事介绍有了新的go语言版的my2sql。优点是不需要安装一大堆依赖包&#xff0c;直接可以安装使用&#xff0c;并且解析更高效&#xff0c;试用一下。 一、 下载安装 1. 软件下载 …

5分钟教你使用idea调试SeaTunnel自定义插件

在用Apache SeaTunnel研发SM2加密组件过程中&#xff0c;发现社区关于本地调试SeaTunnel文章过于简单&#xff0c;很多情况没有说明&#xff0c;于是根据自己遇到问题总结这篇文档。SeaTunnel本地调试官方文档&#xff0c;希望对大家有所帮助&#xff01; 使用的引擎为Flink(不…

极路由4获取不到local_token和uuid的解决方案

今天淘了个二手极路由4(HC5962)&#xff0c;想刷个Openwrt系统来着&#xff0c;就按着网上的教程来进行。 打开极路由ROOT local-ssh利用工具 (hiwifi.wtf)这个网站&#xff0c;然后第一步获取local_token就出问题了&#xff0c;显示的字是"找不到文件..."&#xff…

C/C++炸弹人游戏

参考书籍《啊哈&#xff0c;算法》&#xff0c;很有意思的一本算法书&#xff0c;小白也可以看懂&#xff0c;详细见书&#xff0c;这里只提供代码和运行结果。 这里用到的是枚举思想&#xff0c;还有更好地搜索做法。 如果大家有看不懂的地方或提出建议&#xff0c;欢迎评论区…

前端基础篇-深入了解 Ajax 、Axios

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Ajax 概述 2.0 Axios 概述 3.0 综合案例 1.0 Ajax 概述 通过 Ajax 可以给服务器发送请求&#xff0c;并获取服务器响应的数据。异步交互是指&#xff0c;可以在不…