Arkts應用全局UI狀態存儲和持久化V2(AppStorageV2、PersistenceV2和@Type)

目錄

應用全局UI狀態存儲和持久化V2版本

AppStorageV2

connect

remove

keys

示例

使用限制

PersistenceV2

connect

remove

keys

save

notifyOnError

?示例

使用限制

@Type

?使用限制


應用全局UI狀態存儲和持久化V2版本

以下實例AppStorageV2、PersistenceV2和裝飾器@Type都需要搭配@ComponentV2使用。

AppStorageV2

AppStorageV2是在應用UI啟動時會被創建的單例。它的目的是為了提供應用狀態數據的中心存儲,這些狀態數據在應用級別都是可訪問的。AppStorageV2將在應用運行過程保留其數據。數據通過唯一的鍵字符串值訪問。

AppStorageV2支持應用的主線程內多個UIAbility實例間的狀態共享

connect

用于在AppStorageV2實例中創建鍵值對數據或者獲取實例中key對應的值,返回創建或獲取的值(類實例|undefinded)。返回的不為undefined情況下,該值改變,對應AppStorageV2存儲中的值也會改變。

AppStorageV2.connect<T extends object>(type: TypeConstructorWithArgs<T>, keyOrDefaultCreator?: string | StorageDefaultCreator<T>, defaultCreator?: StorageDefaultCreator<T>): T | undefined;
參數名類型必填說明
typeTypeConstructorWithArgs<T>指定的類型,若未指定key,則使用type的name作為key。
keyOrDefaultCreatorstring |?StorageDefaultCreator<T>指定的key,或者是獲取默認值的構造器。
defaultCreatorStorageDefaultCreator<T>獲取默認值的構造器。

有4種形式入參:

AppStorageV2.connect(Sample)

1個參數,類名。相當于AppStorageV2.connect(Sample,"Sample")。

AppStorageV2.connect(Sample,"Sample1")

2個參數,類名+字符串。表示獲取AppStorageV2中"Sample1"對應的值,該值的類型為Sample,獲取不到返回undefined。

AppStorageV2.connect(Sample,()=>new Sample())

2個參數,類名+默認值構造器。相當于AppStorageV2.connect(Sample,"Sample",()=>new Sample)

AppStorageV2.connect(Sample,"Sample2",()=>new Sample())

3個參數,類名+字符串+默認值構造器。先獲取AppStorageV2中"Sample2"對應的值,如果獲取不到,則通過調用默認值構造器,將結果存入AppStorageV2值中,key為"Sample2"。

注意:使用時,該方法可能返回undefined,故在給@Local等裝飾器修飾的變量賦值時需要在最后加上感嘆號!,用來避過undefined的類型檢測,表示我確認不會返回undefined。

?

remove

用于刪除AppStorageV2實例中指定的鍵值對數據,返回undefined。

AppStorageV2.remove<T>(keyOrType: string | TypeConstructorWithArgs<T>): void
參數名類型必填說明
keyOrTypestring | TypeConstructorWithArgs<T>需要刪除的key;如果指定的是type類型,刪除的key為type的name。

只有一種入參方式,可以傳類名或者字符串。傳類名表示直接刪除類名對應字符串后的鍵值對。?

注意:刪除AppStorageV2中不存在的key會有Warning提示The key to be deleted does not exist。

keys

AppStorageV2.keys(): Array<string>

返回AppStorageV2實例中的所有key(Array<string>)。

示例

Navigation組件跳轉頁面時,首頁不會重復渲染,返回不會重復渲染,pushPathByName會重新渲染新頁面,故下例中首頁只會渲染一次,每次跳到page2頁面都會渲染一個新的。

1.點擊Page1 p1、Page2 p2,p1數字會變動,p2不會,由于@Trace只裝飾了p1,p2的實際值增加了,但是由于UI沒刷新(在第2步中可以看出來)。

2.點擊跳轉page2,p1、p2的數字都同步過去了,由于都是在AppStorageV2實例中獲取的Sample鍵值對。

3.點擊Page2中按鈕,在AppStorageV2中創建一個新的鍵值對Sample1,當前頁面p1、p2的值會還原。

4.點擊返回,由于首頁不會刷新,這時無變化。

5.點擊all keys in AppStorage,觸發該段文字ui刷新,發現多了一個Sample1的key。

6.點擊remove key按鈕AppStorageV2中的Sample鍵值對刪除了。

7.點擊跳轉page2,發現應用直接報錯了,這是由于page2頁面重新渲染,其中下面代碼AppStorageV2.connect(Sample)返回undefined,@Local不能初始化值傳入undefined。

@Local prop: Sample = AppStorageV2.connect(Sample)!;

注意:需要在真機環境運行,在預覽環境會報錯。

Index.ets頁面

// Index.ets
import { AppStorageV2 } from '@kit.ArkUI';// 數據中心
@ObservedV2
export class Sample {@Trace p1: number = 0;p2: number = 10;
}@Entry
@ComponentV2
struct Page1 {// 在AppStorageV2中創建一個key為Sample的鍵值對(如果存在,則返回AppStorageV2中的數據),并且和prop關聯@Local prop: Sample = AppStorageV2.connect(Sample,'Sample',()=>new Sample())!;@Local prop1: String = "1"pageStack: NavPathStack = new NavPathStack();fontSize(){console.log("all keys in AppStorage:渲染了一次")return 30}build() {Navigation(this.pageStack) {Column() {Button('Go to page2').onClick(() => {this.pageStack.pushPathByName('Page2', null);})Button('Page1 connect the key Sample').onClick(() => {// 在AppStorageV2中創建一個key為Sample的鍵值對(如果存在,則返回AppStorageV2中的數據),并且和prop關聯this.prop = AppStorageV2.connect(Sample,()=>new Sample())!;})Button('Page1 remove the key Sample').onClick(() => {// 從AppStorageV2中刪除后,prop將不會再與key為Sample的值關聯AppStorageV2.remove(Sample);})Text(`Page1 p1: ${this.prop.p1}`).fontSize(30).onClick(() => {this.prop.p1++;})Text(`Page1 p2: ${this.prop.p2}`).fontSize(30).onClick(() => {// 頁面不刷新,但是p2的值改變了this.prop.p2++;})// 獲取當前AppStorageV2里面的所有keyText(`${this.prop1}all keys in AppStorage: ${AppStorageV2.keys()}`).fontSize(this.fontSize()).onClick(() => {// 頁面不刷新,但是p2的值改變了this.prop1 = this.prop1+'1'})}}}
}

Index2.ets頁面

// Page2.ets
import { AppStorageV2 } from '@kit.ArkUI';
import { Sample } from './Index';@Builder
export function Page2Builder() {Page2()
}@ComponentV2
struct Page2 {// 在AppStorageV2中創建一個key為Sample的鍵值對(如果存在,則返回AppStorageV2中的數據),并且和prop關聯@Local prop: Sample = AppStorageV2.connect(Sample)!;pathStack: NavPathStack = new NavPathStack();fontSize(){console.log("渲染了一次11")return 30}build() {NavDestination() {Column() {Button('Page2 connect the key Sample1').onClick(() => {// 在AppStorageV2中創建一個key為Sample1的鍵值對(如果存在,則返回AppStorageV2中的數據),并且和prop關聯this.prop = AppStorageV2.connect(Sample,"Sample1",()=>new Sample())!;})Text(`Page2 p1: ${this.prop.p1}`).fontSize(30).onClick(() => {this.prop.p1++;})Text(`Page2 p2: ${this.prop.p2}`).fontSize(this.fontSize()).onClick(() => {// 頁面不刷新,但是p2的值改變了;只有重新初始化才會改變this.prop.p2++;})// 獲取當前AppStorageV2里面的所有keyText(`all keys in AppStorage: ${AppStorageV2.keys()}`).fontSize(30)}}.onReady((context: NavDestinationContext) => {this.pathStack = context.pathStack;})}
}

使用Navigation組件時,需要添加配置系統路由表文件,先在module.json5中添加:"routerMap": "$profile:route_map",表示使用src/main/resources/base/profile目錄下的route_map.json文件作為路由表。故在該目錄下創建文件route_map.json。

{"routerMap": [{"name": "Page2","pageSourceFile": "src/main/ets/pages/Index2.ets","buildFunction": "Page2Builder","data": {"description" : "AppStorageV2 example"}}]
}

使用限制

1、需要配合UI使用(UI線程),不能在其他線程使用,如不支持@Sendable。

2、不支持collections.Set、collections.Map等類型。

3、不支持非buildin類型,如PixelMap、NativePointer、ArrayList等Native類型。

?

PersistenceV2

PersistenceV2是在應用UI啟動時會被創建的單例,用于儲存持久化的數據。不同于AppStorageV2它會將最新數據儲存在設備磁盤上(持久化)。這意味著,應用退出再次啟動后,依然能保存之前的數據。

支持應用的主線程內多個UIAbility實例間的狀態共享。

注意:由于將數據存儲在設備磁盤上,需要將數據進行序列化(數據轉為某種固定的格式進行存儲,例如全部轉為二進制數據)后進行存儲

connect

remove

keys

PersistenceV2類型上繼承了AppStorageV2,在AppStorageV2的基礎上多實現了save和notifyOnError方法,所以上面3個方法使用同AppStorageV2。

save

PersistenceV2.save<T>(keyOrType: string | TypeConstructorWithArgs<T>): void;

對于與PersistenceV2關聯的@ObservedV2對象,該對象的@Trace屬性的變化,會觸發整個關聯對象的自動持久化;非@Trace屬性的變化則不會,這時需要通過該方法進行手動持久化。

save說明
參數keyOrType:需要手動持久化的key;如果指定的是type類型,key為type的name。
返回值無。

入參字符串或者類名。傳類名表示對類名對應字符串后的鍵值對進行持久化處理。?

notifyOnError

PersistenceV2.notifyOnError(callback: PersistenceErrorCallback | undefined): void;

將數據存入磁盤時,需要對數據進行序列化;當某個key序列化失敗時,錯誤是不可預知的;可調用該接口捕獲異常。

notifyOnError說明
參數callback:當序列化或者反序列化失敗時,執行該回調;若傳入undefined,取消該回調。
返回值無。

?示例

注意:需要在真機環境運行,在預覽環境會報錯。

這里示例和AppStorageV2的示例效果類似。不同在于:

1.退出應用后再次打開應用p1的值不會重置,因為使用的PersistenceV2并被@Trace修飾了,會自動持久化數據。

2.p2的值需要點擊Page1 save the key Sample按鈕后才會被持久化。這時退出后再打開p2的值會同步。

Index.ets頁面

import { Type } from '@kit.ArkUI';
import { PersistenceV2 } from '@kit.ArkUI';// 數據中心
@ObservedV2
class SampleChild {@Trace p1: number = 0;p2: number = 10;
}@ObservedV2
export class Sample {// 對于復雜對象需要@Type修飾,確保序列化成功@Type(SampleChild)@Trace f: SampleChild = new SampleChild();
}
// 接受序列化失敗的回調
PersistenceV2.notifyOnError((key: string, reason: string, msg: string) => {console.error(`error key: ${key}, reason: ${reason}, message: ${msg}`);
});@Entry
@ComponentV2
struct Page1 {// 在PersistenceV2中創建一個key為Sample的鍵值對(如果存在,則返回PersistenceV2中的數據),并且和prop關聯// 對于需要換connect對象的prop屬性,需要加@Local修飾(不建議對屬性換connect的對象)@Local prop: Sample = PersistenceV2.connect(Sample, () => new Sample())!;pageStack: NavPathStack = new NavPathStack();build() {Navigation(this.pageStack) {Column() {Button('Go to page2').onClick(() => {this.pageStack.pushPathByName('Page2', null);})Button('Page1 connect the key Sample').onClick(() => {// 在PersistenceV2中創建一個key為Sample的鍵值對(如果存在,則返回PersistenceV2中的數據),并且和prop關聯// 不建議對prop屬性換connect的對象this.prop = PersistenceV2.connect(Sample, 'Sample', () => new Sample())!;})Button('Page1 remove the key Sample').onClick(() => {// 從PersistenceV2中刪除后,prop將不會再與key為Sample的值關聯PersistenceV2.remove(Sample);})Button('Page1 save the key Sample').onClick(() => {// 如果處于connect狀態,持久化key為Sample的鍵值對PersistenceV2.save("Sample");})Text(`Page1 add 1 to prop.p1: ${this.prop.f.p1}`).fontSize(30).onClick(() => {this.prop.f.p1++;})Text(`Page1 add 1 to prop.p2: ${this.prop.f.p2}`).fontSize(30).onClick(() => {// 頁面不刷新,但是p2的值改變了this.prop.f.p2++;})// 獲取當前PersistenceV2里面的所有keyText(`all keys in PersistenceV2: ${PersistenceV2.keys()}`).fontSize(30)}}}
}

Index2.ets?

import { PersistenceV2 } from '@kit.ArkUI';
import { Sample } from './Index';@Builder
export function Page2Builder() {Page2()
}@ComponentV2
struct Page2 {// 在PersistenceV2中創建一個key為Sample的鍵值對(如果存在,則返回PersistenceV2中的數據),并且和prop關聯// 對于需要換connect對象的prop屬性,需要加@Local修飾(不建議對屬性換connect的對象)@Local prop: Sample = PersistenceV2.connect(Sample, () => new Sample())!;pathStack: NavPathStack = new NavPathStack();build() {NavDestination() {Column() {Button('Page2 connect the key Sample1').onClick(() => {// 在PersistenceV2中創建一個key為Sample1的鍵值對(如果存在,則返回PersistenceV2中的數據),并且和prop關聯// 不建議對prop屬性換connect的對象this.prop = PersistenceV2.connect(Sample, 'Sample1', () => new Sample())!;})Text(`Page2 add 1 to prop.p1: ${this.prop.f.p1}`).fontSize(30).onClick(() => {this.prop.f.p1++;})Text(`Page2 add 1 to prop.p2: ${this.prop.f.p2}`).fontSize(30).onClick(() => {// 頁面不刷新,但是p2的值改變了;只有重新初始化才會改變this.prop.f.p2++;})// 獲取當前PersistenceV2里面的所有keyText(`all keys in PersistenceV2: ${PersistenceV2.keys()}`).fontSize(30)}}.onReady((context: NavDestinationContext) => {this.pathStack = context.pathStack;})}
}

?使用Navigation組件時,需要添加配置系統路由表文件,先在module.json5中添加:"routerMap": "$profile:route_map",表示使用src/main/resources/base/profile目錄下的route_map.json文件作為路由表。故在該目錄下創建文件route_map.json。

{"routerMap": [{"name": "Page2","pageSourceFile": "src/main/ets/pages/Index2.ets","buildFunction": "Page2Builder","data": {"description" : "AppStorageV2 example"}}]
}

使用限制

1、需要配合UI使用(UI線程),不能在其他線程使用,如不支持@Sendable。

2、不支持collections.Set、collections.Map等類型。

3、不支持非buildin類型,如PixelMap、NativePointer、ArrayList等Native類型。

4、單個key支持數據大小約8k,過大會導致持久化失敗。

5、持久化的數據必須是class對象,不能是容器(如Array、Set、Map),不能是buildin的構造對象(如Date、Number)。

6、不支持循環引用的對象。

7、只有@Trace的數據改變會觸發自動持久化,如V1狀態變量、@Observed對象、普通數據的改變不會觸發持久化。

8、不宜大量持久化數據,可能會導致頁面卡頓。

@Type

在持久化數據時,為了實現序列化類時不丟失屬性的復雜類型,可以使用@Type裝飾器裝飾類屬性。

@Type裝飾器說明
裝飾器參數type:類型。
可裝飾的類型Object class以及Array、Date、Map、Set等內嵌類型。

class Sample {data: number = 0;
}
// Info會在PersistenceV2中使用。
//@Local prop: Info = PersistenceV2.connect(Info , () => new Info ())!;
@ObservedV2
class Info {@Type(Sample)@Trace sample: Sample = new Sample(); // 正確用法
}

?使用限制

1、只能用在@ObservedV2裝飾的類中,不能用在自定義組件中。

2、不支持collections.Set、collections.Map等類型。

3、不支持非buildin類型,如PixelMap、NativePointer、ArrayList等Native類型。

4、不支持簡單類型,如string、number、boolean等。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76194.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76194.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76194.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

最大子序和問題——動態規劃/貪心算法解決

目錄 一&#xff1a;問題描述 二&#xff1a;解決思路1——動態規劃思想 三&#xff1a;C 語言代碼實現 四&#xff1a;復雜度分析 五&#xff1a;解決思路2——貪心算法思想 六&#xff1a;具體步驟 七: C語言代碼實現 八&#xff1a;復雜度分析 一&#xff1a;問題描述 …

【Python入門】文件讀取全攻略:5種常用格式(csv/excel/word/ppt/pdf)一鍵搞定 | 附完整代碼示例

大家好&#xff0c;我是唐叔&#xff01;今天給大家帶來一篇Python文件讀取的終極指南。無論是數據分析、辦公自動化還是爬蟲開發&#xff0c;文件讀取都是Python程序員必須掌握的核心技能。本文將詳細介紹Python處理5大常用文件格式的方法&#xff0c;包含完整可運行的代碼示例…

四、小白如何用Pygame制作一款跑酷類游戲(頁面暫停和主角跑步動作的實現)

四、小白如何用Pygame制作一款跑酷類游戲&#xff08;頁面暫停和主角跑步動作的實現&#xff09; 提示&#xff1a;寫完文章后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 四、小白如何用Pygame制作一款跑酷類游戲&#xff08;頁面暫停和主…

《基于 RNN 的股票預測模型代碼優化:從重塑到直接可視化》

在深度學習領域&#xff0c;使用循環神經網絡&#xff08;RNN&#xff09;進行股票價格預測是一個常見且具有挑戰性的任務。本文將圍繞一段基于 RNN 的股票預測代碼的改動前后差別展開&#xff0c;深入剖析代碼的優化思路和效果。 原始代碼思路與問題 原始代碼實現了一個完整…

Lambda 函數與 peek 操作的使用案例

Lambda 函數和 peek 操作是 Java 8 Stream API 中非常有用的特性&#xff0c;下面我將介紹它們的使用案例。 Lambda 函數使用案例 Lambda 表達式是 Java 8 引入的一種簡潔的匿名函數表示方式。 集合操作 List<String> names Arrays.asList("Alice", "B…

Docker私有倉庫頁面訪問實現

通過 docker run -d -p 5000:5000 --name registry registry:2 命令搭建的Docker私有倉庫默認不提供網頁訪問界面。它是一個基于API的后端服務&#xff0c;主要用于鏡像的存儲和管理。但可以通過以下兩種方式實現網頁訪問&#xff1a; 一、通過第三方Web UI工具擴展 1. 使用 D…

[王陽明代數講義]語言模型核心代碼調研

語言模型核心代碼調研 基于Consciciteation?的才氣張量持續思考綜述將文本生成建模為才氣張量網絡擴散過程&#xff0c;實現非自回歸推理通過才氣張量的群-拓撲流形交叉注意力實現多模態推理&#xff0c;將輸入壓縮到低維空間持續迭代提出「條件計算提前終止」機制&#xff0c…

flink jobmanager離奇的heap oom

文章目錄 現象描述開始分析1.初步分析dump文件2.AI分析引用關系分析方向2.1 flink BlobServer bug分析方向2.2 和運行環境有關分析方向2.3 和任務有關 回到問題本身&#xff0c;思考一下1. seatunnel到底有沒有問題2.再次分析zipfile對象3.分析seatunnel es connector 源碼4 懷…

APP動態交互原型實例|墨刀變量控制+條件判斷教程

引言 不同行業的產品經理在繪制原型圖時&#xff0c;擁有不同的呈現方式。對于第三方軟件技術服務公司的產品經理來說&#xff0c;高保真動態交互原型不僅可以在開發前驗證交互邏輯&#xff0c;還能為甲方客戶帶來更直觀、真實的體驗。 本文第三部分將分享一個實戰案例&#…

AI 驅動下的后端開發架構革命:從智能協同體系

AI 驅動下的后端開發架構革命&#xff1a;從智能協同體系 一、引言&#xff1a;AI 重構后端開發范式 在 2025 年的企業級技術演進中&#xff0c;人工智能正從輔助工具升級為核心架構要素。根據 Gartner《2025 智能技術棧成熟度報告》&#xff0c;傳統 "人力編碼 硬規則…

安卓基礎(生命周期)

創建階段&#xff1a;onCreate方法被調用&#xff0c;用于初始化 Activity&#xff0c;如設置布局等。啟動階段&#xff1a;依次調用onStart和onResume方法&#xff0c;讓 Activity 變得可見并可與用戶交互。暫停與恢復階段&#xff1a;當 Activity 失去焦點但可見時&#xff0…

Uniapp: 下拉選擇框 ba-tree-picker

目錄 1、效果展示2、如何使用2.1 插件市場2.2 引入插件 3、參數配置3.1 屬性3.2 方法 4、遇見的問題4.1、設置下拉樹的樣式 1、效果展示 2、如何使用 2.1 插件市場 首先從插件市場中將插件導入到項目中 2.2 引入插件 在使用的頁面引入插件 <view click"showPicke…

Spring Boot實戰:基于策略模式+代理模式手寫冪等性注解組件

一、為什么需要冪等性&#xff1f; 核心定義&#xff1a;在分布式系統中&#xff0c;一個操作無論執行一次還是多次&#xff0c;最終結果都保持一致。 典型場景&#xff1a; 用戶重復點擊提交按鈕網絡抖動導致的請求重試消息隊列的重復消費支付系統的回調通知 不處理冪等的風…

如何恢復極狐GitLab?

極狐GitLab 是 GitLab 在中國的發行版&#xff0c;關于中文參考文檔和資料有&#xff1a; 極狐GitLab 中文文檔極狐GitLab 中文論壇極狐GitLab 官網 恢復極狐GitLab (BASIC SELF) 極狐GitLab 提供了一個命令行界面來恢復整個安裝&#xff0c;足夠靈活以滿足您的需求。 恢復…

面試高階問題:android后臺任務(如數據同步、定位)消耗過多電量,導致用戶投訴。你會如何分析和優化后臺任務的執行?

在現代移動設備生態中,安卓系統以其開放性和靈活性占據了全球智能手機市場的絕大部分份額。作為一款功能強大的操作系統,安卓允許應用程序在后臺執行各種任務,例如數據同步、定位服務、消息推送以及其他周期性更新。這些后臺任務在提升用戶體驗方面扮演了不可或缺的角色——…

最近在學習web搞大屏看板

人到中年&#xff0c;delphi發展越來越不行&#xff0c;就業環境是真差啊&#xff0c;沒辦法&#xff0c;學唄 中國地圖&#xff1a; // 中國地圖function getChinaMapChart() {// 初始化echarts實例var myEcharts echarts.init(document.getElementById("china_box"…

117.在 Vue 3 中使用 OpenLayers 實現 CTRL 控制拖拽和滾動縮放

? 前言 在使用 OpenLayers 開發地圖類項目時,我們有時會希望用戶必須按下 CTRL(或 Mac 的 Command ? 鍵)才能拖拽地圖或使用鼠標滾輪縮放。這種交互方式能夠避免用戶在瀏覽頁面時意外滑動或拖動地圖,尤其是在地圖嵌入頁面中時非常有用。 本文將帶你一步一步實現在 Vue …

MATLAB 控制系統設計與仿真 - 34

多變量系統知識回顧 - MIMO system 這一章對深入理解多變量系統以及魯棒分析至關重要 首先,對于如下系統: 當G(s)為單輸入,單輸出系統時: 如果: 則: 所以 因此,對于SISO,系統的增益跟w有關系, 當G(s)為MIMO時,例如2X2時, 假設輸入信號為:

ARCGIS PRO DSK 利用兩期地表DEM數據計算工程土方量

利用兩期地表DEM數據計算工程土方量需要準許以下數據&#xff1a; 當前地圖有3個圖層&#xff0c;兩個柵格圖層和一個矢量圖層 兩個柵格圖層&#xff1a;beforeDem為工程施工前的地表DEM模型 afterDem為工程施工后的地表DEM模型 一個矢量圖層&#xf…

最快打包WPF 應用程序

在 Visual Studio 中右鍵項目選擇“發布”&#xff0c;目標選“文件夾”&#xff0c;模式選“自包含”&#xff0c;生成含 .exe 的文件夾&#xff0c;壓縮后可直接發給別人或解壓運行&#xff0c;無需安裝任何東西。 最簡單直接的新手做法&#xff1a; 用 Visual Studio 的“…