装饰器
@Entry(入口)
@Entry 装饰的 @Component 将作为 UI 页面的入口
在单个 UI 页面中,最多可以使用@Entry 装饰一个自界说组件
- @Entry
- @Component
- struct Index {
- }
复制代码 @Component(组件)
自界说组件,@Component 功能更加多样,有自己的生命周期,还能支持预览结果
- @Component 装饰了 struct 关键字声明的类 Index
- Index 被 @Component 装饰后具备组件化的本领,通过实现 build 方法描述 UI
- @Component 装饰的 struct 类必须添加 @Component 装饰器,开发工具有提示
- @Component
- struct Index {
-
- build() {
-
- }
- }
复制代码 @Builder(构建)
自界说构建函数,@Builder 更加轻量,能满足底子的组件封装,性能更好,但是不支持预览。
- 留意:如需更好的性能,建议采用 @Builder 方式进行组件界说封装
- @Builder
- CustomBuilderXXX(paramxx: string) {
- Row() {
- Image($r(paramxx))
- .width(20)
- .height(20)
- }
- .width('100%')
- .height(64)
- .alignItems(VerticalAlign.Center)
- }
复制代码 @State(状态)
传值
文本信息由 @State 装饰器装饰的状态变量 message 驱动
- @State message: string = 'HarmonyOS 速记';
复制代码 @Prop(属性)
@Prop 装饰器,用于从父组件吸取数据
- 留意:参加 @Prop 后,Previewer 会失效
@StorageProp
获取全局断点值,自动更新断点值
@Link(属性)
传值
@StorageLink
获取全局断点值,自动更新断点值
@Consume(消费)
拿到路由栈
@Preview(预览)
Previewer
- Previewer 可以直接预览 @Entry 装饰的整个页面
也可以预览由 @Preview 装饰的单独组件
- 预览 @Entry 装饰的整个页面时,需要选中 @Entry 所在的文件,Previewer 才能顺利打开
- 将 Previewer 调解至 ComponentMode,便可以单独预览组件视图
- 假如修改的是文本内容,则需要手动保存(即 ctrl+s)后,Previewer 才会更新
假如修改的是相关属性,则不需要手动保存,Previewer 也会实时更新
- 留意:此时的 Inspector 是不可用状态
Inspector
开启 Previewer 工具栏的 Inspector 工具,可以观察到当前组件树,并与 Previewer 交互
布局体
struct
界说组件布局体
- @Component 装饰的 struct 类必须添加 @Component 装饰器,开发工具有提示
- @Component 装饰的 struct 类必须重写 build 函数,开发工具有提示
build
组件通过 build 函数用于描述 UI
- @Component 装饰的 struct 类必须重写 build 函数,开发工具有提示
- builder 下只能有一个根节点
自界说组件
- @Component
- struct Custom {
- build() {
-
- }
- }
复制代码 自界说 Custom 组件
- @Preview // 用于组件预览
- @Component // 定义组件
- struct Custom { // 组件名
- build() {
- Image($r('app.media.banner_pic1')) // 图片
- .width('100%') // 宽度
- .padding({ // 内边距
- left: 16,
- top: 10,
- right: 16,
- bottom: 10
- })
- .borderRadius(16) // 圆角
- .objectFit(ImageFit.Contain) // 缩放模式
- }
- }
复制代码 使用 Previewer 查看结果
export(导出) & import(导入)
独立界说的 Model/View,需要提供给外部使用,则需要 export 关键字修饰
在需要使用到文件,通过 import { XXX } from ‘…/model/XXX’; 导入后使用
- // export 导出
- export class BannerClass {
- id: string = '';
- imageSrc: ResourceStr = '';
- url: string = '';
-
- constructor(id: string, imageSrc: ResourceStr,url: string) {
- this.id = id;
- this.imageSrc = imageSrc;
- this.url = url;
- }
- }
- import {BannerClass} from '../model/BannerClass';
- @Component
- struct Banner {
- @State banner: BannerClass;
- // ...
- }
复制代码 Page(页面)
生命周期
aboutToAppear
aboutToAppear 函数在创建自界说组件的新实例后,且在执行其 build 函数之前执行
Navigation(导航栏)
Navigation
NavDestination
Tabs(标签栏)
Tabs
TabContent
自界说导航页签栏
Navigation & Tabs
数据
Array(数组/集合)
- // 方式一:
- list: Array<XXXClass> = [
- new XXXClass('01', 'zhangsan'),
- new XXXClass('02', 'lisi')
- ];
- // 方式二:(推荐)
- list: XXXClass[] = [
- {
- id: '01',
- name: 'zhangsan'
- },
- {
- id: '02',
- name: 'lisi'
- }
- ];
- export class XXXClass {
- id: string = '';
- name: string = '';
- constructor(id: string, name: string) {
- this.id = id;
- this.name = name;
- }
- }
复制代码 Map(映射)
界说映射关系,即<key, value>,可以使用 Record 类型来进行映射,也可以使用 Map 进行映射,通过 TypeMapIcon[key] 的方式来获取 value
- // Record 类型
- const TypeMapIcon: Record<string, string> = {
- '指南': 'app.media.ic_guide',
- '准备': 'app.media.ic_prepare',
- '学习与获取证书': 'app.media.ic_medals',
- '视频教程': 'app.media.ic_video',
- }
复制代码 容器(字典顺序)
Grid(网格容器)
网格容器,由“行”和“列”分割的单元格所组成,此中容器内各条目对应一个 GridItem 组件
假如仅设置行、列数目与占比中的一个,则网格单元将按照设置的方向排列
设置单行表现,则可以横向滑动
网格布局具有较强的页面均分本领,子组件占比控制本领,是一种重要自顺应布局
Grid 是与 GridItem 搭配使用的
- 通过 ForEach 创建 GridItem,
- 在 GridItem 中参加自界说的 item 布局
- 自界说 item 布局中通过 @Prop 装饰器来吸取外部传入的数据源
List(列表)
List 是与 ListItem 搭配使用的
- 通过 ForEach 创建 ListItem,
- 在 ListItem 中参加自界说的 item 布局
- 自界说 item 布局中通过 @Prop 装饰器来吸取外部传入的数据源
- lanes 属性控制列表组件的表现列数以及列间距
- // List 列表布局
- List({ space: 12 }) { // item 列间隔
- ForEach(
- this.tutorialList,
- (item: ArticleClass, index: number) => {
- ListItem(){
- TutorialItem({
- tutorialItem: item
- })
- }
- },
- (item: ArticleClass, index: number) => item.id
- )
- }
- .padding({
- left: 16,
- right: 16
- })
- .scrollBar(BarState.Off)
- .divider({ // item 分割线样式
- strokeWidth: 2,
- startMargin: 38,
- endMargin: 0,
- color: Color.Orange
- })
复制代码 margin(外边距) & padding(内边距)
外边距
- Text(this.message)
- // .margin(12)
- .margin({
- left: 20,
- top: 20,
- right: 20,
- bottom: 20
- })
复制代码 内边距
- Text(this.message)
- // .padding(12)
- .padding({
- left: 20,
- top: 20,
- right: 20,
- bottom: 20
- })
复制代码 Row(行) & Column(列)
- Row() {
- Column() {
- Text(this.message)
- .fontSize(20)
- .fontWeight(FontWeight.Bold)
- }
- .width('100%')
- }
- .height('100%')
复制代码 RelativeContainer(相对布局容器)
alignRules 在 RelativeContainer 中设置对齐规则(位置:上中下、左中右)
- top、center、bottom 上中下
- left、middle、right 左中右
注:alignRules 属性在 Row & Column 容器中无效
- // 水平、竖直居中
- RelativeContainer() {
- Text(this.message)
- .fontSize(20)
- .fontWeight(FontWeight.Bold)
- .alignRules({ // 对齐规则
- center: {
- anchor: '__container__',
- align: VerticalAlign.Center
- },
- middle: {
- anchor: '__container__',
- align: HorizontalAlign.Center
- }
- })
- }
- .width('100%')
- .height('100%')
复制代码
函数 alignRules 声明
- alignRules(value: AlignRuleOption): T;
复制代码 参数 AlignRuleOption 源码
- declare interface AlignRuleOption {
- top?: { // 上
- anchor: string;
- align: VerticalAlign;
- };
- center?: { // 中
- anchor: string;
- align: VerticalAlign;
- };
- bottom?: { // 下
- anchor: string;
- align: VerticalAlign;
- };
-
- left?: { // 左
- anchor: string;
- align: HorizontalAlign;
- };
- middle?: { // 中
- anchor: string;
- align: HorizontalAlign;
- };
- right?: { // 右
- anchor: string;
- align: HorizontalAlign;
- };
- bias?: Bias;
- }
复制代码 结论
top、center、bottom、left、middle、right
- 对应着 设置子控件的基线,即以子控件的哪个位置作为对齐的基准点
VerticalAlign#Top、Center、Bottom & HorizontalAlign#Start、Center、End
- 这些属性才是对应着 设置子控件相对于父布局的对齐规则,但需要配合上面的基准来使用才会得到想要的正确结果
Scroll(滑动布局)
Scroll 组件需要留意下面两种情况:
- 列表的数据数目过多时,将导致内容会超过界面
- 列表的数据数目不敷时,将导致Scroll组件滚动时出现空白区域
- 解决方法:以是此处要在最外层包裹一个Scroll组件
- constraintSize 属性,用于设置束缚大小
- 设置 minHeight 为 100%,可以解决当内容条数不敷时,Scroll组件滚动时会出现空白区域的错误结果
- EdgeEffect.None 表示设置为没有结果
- EdgeEffect.Fade 表示设置为淡入淡出结果
- EdgeEffect.Spring 表示设置为弹性物理动效。该结果滑动到边缘后可以根据初始速度或通过触摸事故继承滑动一段距离,放手后回弹
- ScrollDirection.Vertical 表示答应纵向滚动
- ScrollDirectionHorizontal 表示答应横向滚动
- scrollBar 属性,用于设置以何种方式表现滚动条
- BarState.On 一直表现
- BarState.Off 不表现
- BarState.Auto 滑动时表现
- Scroll() {
- Column() {
- ...
- }
- ...
- }
- .backgroundColor('#F1F3F5')
- .align(Alignment.TopStart)
- .constraintSize({ // 解决内容不足时,会出现空白区域的现象
- minHeight: '100%'
- })
- .edgeEffect(EdgeEffect.Spring) // EdgeEffect.Spring 弹性效果
复制代码 Swiper(轮播图)
使用Swiper构建轮播图
- displayCount 属性来控制一页内的元素表现数目
- nextMargin 属性控制未完全表现的部分的宽度
- indicator 控制导航点指示器是否表现与表现结果
- @Entry@Componentstruct Index { @State message: string = 'HarmonyOS 速记';
- build() { Column() { // Title Text(this.message) .padding({ left: 16, top: 10, right: 16, bottom: 10 }) .width('100%') .textAlign(TextAlign.Start) .fontWeight(FontWeight.Bold) // Banner Banner() .margin({ left: 16, right: 16 }) } .height('100%') .width('100%') .backgroundColor('#F1F3F5') }}@Preview@Componentstruct Banner { // Banner 数据源 @State banners: Array<BannerBean> = [ new BannerBean('pic0', $r('app.media.banner_pic0'), 'https://developer.huawei.com/consumer/cn/training/course/video/C101718352529709527'), new BannerBean('pic1', $r('app.media.banner_pic1'), 'https://developer.huawei.com/consumer/cn/'), new BannerBean('pic2', $r('app.media.banner_pic2'), 'https://developer.huawei.com/consumer/cn/deveco-studio/'), new BannerBean('pic3', $r('app.media.banner_pic3'), 'https://developer.huawei.com/consumer/cn/arkts/'), new BannerBean('pic4', $r('app.media.banner_pic4'), 'https://developer.huawei.com/consumer/cn/arkui/'), new BannerBean('pic5', $r('app.media.banner_pic5'), 'https://developer.huawei.com/consumer/cn/sdk') ]; build() { Swiper() { // 轮播图 ForEach( this.banners, // 数据源 (item: BannerBean, index: number) => { // 用于生成 item 组件 Image(item.imageSrc) .width('100%') .borderRadius( 10 ) // 设置图片的圆角,不是 Banner 的圆角,以是感觉有点怪异 .objectFit(ImageFit.Contain) }, (item: BannerBean, index: number) => item.id // 用于 item 增量更新,以是需要 id ) } .autoPlay(true) // 开启自动播放 .loop(true) // 开启轮训 // .interval(1000) // 时间间隔 // .indicator(true) // 使用默认的指示器 .indicator( // 配置指示器 new DotIndicator() .color('#1a000000') .selectedColor('#0A59F7') ) }}/** * Banner 布局体 */class BannerBean { id: string = ''; imageSrc: ResourceStr = ''; url: string = ''; constructor(id: string, imageSrc: ResourceStr, url: string) { this.id = id; this.imageSrc = imageSrc; this.url = url; }}
复制代码
组件(字典顺序)
Blank()
该组件可以自动添补主轴方向的空余空间
- Row() {
- Text(this.navBarItem.order)
- ...
- Text(this.navBarItem.title)
- ...
- Blank() // 通过 Blank 组件,来自动填充主轴方向的剩余空间
- Image($r('app.media.ic_arrow'))
- .width(12)
- .height(24)
- }
复制代码 Image(图片)
用于表现图片
- Image($r('app.media.banner_pic1')) // 设置图片资源
- .width('100%') // 宽度
- .padding({ // 内边距
- left: 16,
- top: 10,
- right: 16,
- bottom: 10
- })
- .borderRadius(16) // 圆角
- .objectFit(ImageFit.Contain) // 缩放模式
复制代码 方法一
通过 $r(‘app.media. 文件名字’) 将 media 文件夹下的本地图片读取到 Image 组件
- Image($r('app.media.image_path'))
复制代码 方法二
界说 ResourceStr 变量,值为 media 文件夹下的本地图片路径,通过 $r(上面界说的 ResourceStr 变量) 将 media 文件夹下的本地图片读取到 Image 组件
- private path: ResourceStr = 'app.media.image_path';
- Image($r(path))
复制代码 方法三
- 通过 rawfile 目录中配置的 JSON 文件来配置本地图片的路径,这种情况时图片的路径为 string 类型、非 ResourceStr 类型,以是需要界说 string 类型、非 ResourceStr 类型 的变量来吸取 JSON 中界说的图片路径,然后直接通过 Image 组件加载图片即可。(详细解析代码详见当前页面内容 Project 工程布局#rawfile)
- 由于 json 文件解析限定,当前不支持 Previewer 预览器模式,应选择模仿器或真机进行调试。
图片的添补模式
.objectFit(ImageFit.Contain)
设置图片的添补模式
- Contain 模式,即保持宽高比进行缩小或者放大,使得图片完全表如今表现边界内
- Cover 模式,即保持宽高比进行缩小或者放大,使得图片两边都大于或等于表现边界。
Text(文本)
组件:左上角对齐
- Text(this.message) // 默认宽度 wrap_content
- .id('HelloWorld')
- .fontSize(20)
- .fontWeight(FontWeight.Bold)
- .fontStyle(FontStyle.Italic)
- .lineHeight(55)
- .alignRules({ // 对齐规则:左上角(top、left) 为 对其基准点
- top: { // 上边缘 为 对其基准点
- anchor: '__container__',
- align: VerticalAlign.Top // 上对齐
- },
- left: { // 左边缘 为 对其基准点
- anchor: '__container__',
- align: HorizontalAlign.Start // 左对齐
- }
- })
复制代码 笔墨:左对齐
- Text(this.message)
- .width('100%') // 设置宽度 match_parent
- .textAlign(TextAlign.Start) // 设置文字朝向 居左
复制代码 WebView
加载网络资源
- 创建ArkTS侧代码。在 ets/pages/ 中创建 CourseLearning.ets 文件,新增底子的代码框架
- 添加网络权限 ohos.permission.INTERNET
- 创建 webviewController,开发者后续可以通过该Controller控制Web组件加载的界面
加载本地资源
- 将本地 Web 资源包 course_learning 目录放入 resources/rawfile/ 目录下
- 创建ArkTS侧代码。在 ets/pages/ 中创建 CourseLearning.ets 文件,新增底子的代码框架
- 创建 webviewController,开发者后续可以通过该Controller控制Web组件加载的界面
- 加载本地界面,修改 Web 组件的 src 属性,使用 $rawfile 加载刚刚放入 rawfile 目录下的 course_learning 资源。
- 留意:需要在真机或者模仿器上运行代码,Previewer 预览器暂不支持 Web 组件的预览结果
- import { webview } from '@kit.ArkWeb'
- @Component
- struct CourseLearning {
- private webviewController: webview.WebviewController = new webview.WebviewController();
- build() {
- Column() {
- // 加载网络 Web 资源
- Web({ src: 'http://www.huawei.com', controller: this.webviewController })
- .domStorageAccess(true)
- // 加载本地 Web 资源
- // Web({ src: $rawfile('course_learning/index.html'), controller: this.webviewController })
- // .domStorageAccess(true)
- }
- }
- }
复制代码 Tips
像素单位
鸿蒙方舟框架为开发者提供了4种像素单位,即:px、vp、fp、lpx
框架采用 vp 为基准数据单位
vp
vp 是 virtual pixel(虚拟像素)的缩写,是常用的长度单位
权限
requestPermissions
- name:申请的权限名称,必填,此处由于需要申请分布式数据同步的权限,以是填入" ohos.permission.DISTRIBUTED_DATASYNC"
- reason:申请权限的原因,在之后的向用户申请权限的弹窗中会用到,此处只能写成 s t r i n g 的形式,配合刚刚配置的申请原因,我们写为 " string 的形式,配合刚刚配置的申请原因,我们写为 " string的形式,配合刚刚配置的申请原因,我们写为"string:distributed_data_sync"
- usedScene:描述权限使用的场景和时机。场景类型如下两种:
- ability:ability的名称,可配置多个。此处我们配置为快速入门案例的 ability 名称,即 EntryAbility
- when:调用时机,可填的值有 inuse(使用时需要此权限)、always( 全部时间都需要此权限),默认值为 inuse
ohos.permission.INTERNET
ohos.permission.DISTRIBUTED_DATASYNC
user_grant权限类型,为需要用户授权的类型,该类型权限申请时需要写明申请原因和使用场景,且原因字段只支持使用$string的方式进行引用
该类型权限不但需要在安装包中申请权限,还需要在应用动态运行时哀求用户授权。在用户手动答应授权后,应用才会真正获取相应权限,从而成功访问操纵目的对象
- async checkPermissions(): Promise<void> {
- const permissions: Array<Permissions> = ['ohos.permission.DISTRIBUTED_DATASYNC'];
- const accessManager = abilityAccessCtrl.createAtManager();
- try {
- const bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION;
- const bundleInfo = await bundleManager.getBundleInfoForSelf(bundleFlags);
- const grantStatus = await accessManager.checkAccessToken(bundleInfo.appInfo.accessTokenId, permissions[0]);
- if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) {
- accessManager.requestPermissionsFromUser(this.context, permissions);
- }
- } catch (err) {
- console.error('EntryAbility', 'checkPermissions', `Catch err: ${err}`);
- return;
- }
- }
复制代码 架构
MVVM
ArkUI 采取 MVVM = Model + View + ViewModel 模式,此中 状态管理模块 起到的就是ViewModel 的作用,将数据(Model)与视图(View)绑定在一起,数据更新 会直接 更新视图。
- Model 为我们界说的数据布局和数据泉源,通过 @State 等装饰器来装饰对应的数据,就提供了响应式本领,Model 数据的变化就可以或许触发 UI 的更新。
- MVVM 的目录组织方式,一样平常实用于单个模块内文件组织
三层架构设计
为了更好地适配复杂应用的开发,建议采用三层架构的方式对整个应用的功能进行模块化,实现高内聚、低耦合开发。
三层工程布局如下:
- commons(公共本领层):用于存放公共底子本领集合(如工具库、公共配置等)。commons层可编译成一个或多个HAR包或HSP包,只可以被products和features依靠,不可以反向依靠。
- features(底子特性层):用于存放底子特性集合(如应用中相对独立的各个功能的UI及业务逻辑实现等)。各个feature高内聚、低耦合、可定制,供产品灵活摆设。不需要单独摆设的feature通常编译为HAR包或HSP包,供products或别的feature使用。需要单独摆设的feature通常编译为Feature类型的HAP包,和products下Entry类型的HAP包进行组合摆设。features层可以横向调用及依靠common层,同时可以被products层不同设备形态的HAP所依靠,但是不能反向依靠products层。
- products(产品定制层):用于针对不同设备形态进行功能和特性集成。products层各个子目录各自编译为一个Entry类型的HAP包,作为应用主入口。products层不可以横向调用。
三层架构工程目录迁移
一次开发、多端摆设(简称“一多”)
单屏
折叠屏
平板
通过使用“断点”,进行「一多」适配
断点
断点本质上就是将不同的应用窗口宽度分别为不同的范围,这样既能减少在进行界面设计时考虑的因素,也简化了「一多」的开发
原生互联:分布式流转
流转的条件条件
- 双端设备需要登录同一华为帐号
- 双端设备需要打开Wi-Fi和蓝牙开关
- 条件答应时,建议双端设备接入同一个局域网,可提升数据传输的速度
- 应用接续只能在同应用(UIAbility)之间触发,双端设备都需要有该应用
接续流程
Project 工程布局
.hvigor/
生成文件
.idea/
生成文件
AppScope/
resources/
base/element/
base/media/
- 放置 base 图片资源
- app_icon.png
app.json5
app 底子信息配置文件
- // app.json5
- {
- "app": {
- "bundleName": "com.villen.hm", // 包名
- "vendor": "example", // 提供商
- "versionCode": 1000000, // version code
- "versionName": "1.0.0", // 版本号
- "icon": "$media:app_icon", // 应用图标
- "label": "$string:app_name" // 应用名称
- }
- }
复制代码 entry/
.preview/
- 生成文件,雷同 android 中的 build 目录
src/
entry/src/
main/
entry/src/main/
ets/
entry/src/main/ets/
源代码
resources/
entry/src/main/resources/
资源
base/
entry/src/main/resources/base/
base 资源
- element/ -> 资源文件
- media/ -> 资源图片
- profile/ -> 资源图片
- backup_config.json -> 描述 备份相关配置
- main_pages.json -> 描述 路由信息 或界说 窗口相关配置
en_US/
entry/src/main/resources/en_US/
英文资源
zh_CN/
entry/src/main/resources/zh_CN/
中文资源
rawfile/
entry/src/main/resources/rawfile/
该目录用于存放 json 数据资源、Web 资源等本地资源文件。
- 该目录中的资源文件会被直接打包进应用,不经过编译,也不会被赋予资源文件ID。通过指定文件路径和文件名引用。
- 由于 json 文件解析限定,当前不支持 Previewer 预览器模式,应选择模仿器或真机进行调试。
- 读取 json 文件内容,需要使用到 ResourceManager 的 getRawfileContent 方法,从 rawfile 目录中读取对应的 JSON 文件
- 转换内容需要两个步骤:
- 由于 ResourceManager 获取到的是 ArrayBufferLike 类型的内容,以是需要将对应的内容转换为字符串,并将字符串解析为对应的数据布局。
- 考虑到其他的文件也会使用这个公共方法,可以新建一个 util 文件夹,并创建一个 BufferUtil 文件,实现这个字符串转换方法。
- 该功能可以用于临时 mock 数据
- // BufferUtil.ets
- import { util } from '@kit.ArkTS';
- /**
- * buffer 转 string
- * 用于从 rawfile 中读取 JSON 数据
- *
- * @param buffer
- * @returns
- */
- export function bufferToString(buffer: ArrayBufferLike): string {
- let textDecoder = util.TextDecoder.create('utf-8', {
- ignoreBOM: true
- });
- let resultPut = textDecoder.decodeWithStream(new Uint8Array(buffer), {
- stream: true
- });
- return resultPut;
- }
复制代码 module.json5
entry/src/main/module.json5
清单文件,雷同 android 中的 AndroidManifest.xml
- // 权限申请,位于 module 节点下
- "requestPermissions": [
- {
- "name": "ohos.permission.INTERNET",
- "reason": "$string:apply_for_network"
- }
- ]
复制代码 ohosTest/
测试
test/
测试
.gitignore(module目录)
忽略文件
build-profile.json5(module目录)
hvigorfile.ts(module目录)
obfuscation-rules.txt(module目录)
oh-package.json5(module目录)
配置依靠项,配置完后,会提示需要安装依靠,可以通过 Run “ohpm install” 执行安装过程。
- "dependencies": {
- "@ohos/learning": "file:../../features/learning",
- "@ohos/map": "file:../../features/map",
- "@ohos/quickstart": "file:../../features/quickstart"
- }
复制代码 hvigor/
hvigor-config.json5
oh_modules/
生成文件
.gitignore
忽略文件
build_profile.json5(根目录)
code-linter.json5
hvigorfile.ts
local.properties
oh-package.json5
oh-package-lock.json5
生成文件
参考
HarmonyOS应用开发快速入门
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |