<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: skyrejer</title>
    <description>The latest articles on DEV Community by skyrejer (@skyrejer).</description>
    <link>https://dev.to/skyrejer</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3222620%2Fc72c6cd0-8892-4a93-850f-771c0aa41cfd.png</url>
      <title>DEV Community: skyrejer</title>
      <link>https://dev.to/skyrejer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/skyrejer"/>
    <language>en</language>
    <item>
      <title>Native Hongmeng Router-Navigation Summary</title>
      <dc:creator>skyrejer</dc:creator>
      <pubDate>Thu, 29 May 2025 15:14:43 +0000</pubDate>
      <link>https://dev.to/skyrejer/native-hongmeng-router-navigation-summary-1bl8</link>
      <guid>https://dev.to/skyrejer/native-hongmeng-router-navigation-summary-1bl8</guid>
      <description>&lt;p&gt;Navigation route navigation&lt;br&gt;
Use Navigation to replace all route jumps&lt;/p&gt;

&lt;p&gt;The concept is: the entire application has only one page, and the rest are components [Huawei recommends using Navigation route navigation]&lt;/p&gt;

&lt;p&gt;The first routing method&lt;br&gt;
The outermost layer of the root component must be wrapped by Navigation&lt;br&gt;
The component to be redirected must be wrapped by NavDestination&lt;br&gt;
The redirection object is the NavPathStack object&lt;br&gt;
NavPathStack must be bound to Navigation&lt;br&gt;
The lower-level components use various methods to obtain the upper-level NavPathStack for redirection&lt;br&gt;
The redirection maintenance is implemented by .navDestination&lt;br&gt;
Navigation is bound to NavPathStack, and it is best to use Provide to provide it to child components for use&lt;br&gt;
Route management — bind .navDestination(builder) to Navigation — builder cannot write bracket mode&lt;/p&gt;

&lt;p&gt;import { Friend } from './Friend'&lt;br&gt;
 import { Live } from './Live'&lt;br&gt;
 import { Shake } from './Shake'&lt;br&gt;
 ​&lt;br&gt;
 @Entry&lt;br&gt;
 @Component&lt;br&gt;
 struct NavigationCase {&lt;br&gt;
   @Provide&lt;br&gt;
   stackPath: NavPathStack = new NavPathStack()&lt;br&gt;
 ​&lt;br&gt;
 ​&lt;br&gt;
   &lt;a class="mentioned-user" href="https://dev.to/builder"&gt;@builder&lt;/a&gt;&lt;br&gt;
   getRouterBuilder (name: string) {&lt;br&gt;
    // name is the identifier to jump to&lt;br&gt;
     if(name === 'friend') {&lt;br&gt;
       Friend()&lt;br&gt;
     }&lt;br&gt;
     else if(name === "live") {&lt;br&gt;
      Live()&lt;br&gt;
     }&lt;br&gt;
     else if(name === "shake") {&lt;br&gt;
      Shake()&lt;br&gt;
     }&lt;br&gt;
   }&lt;br&gt;
 ​&lt;br&gt;
   build() {&lt;br&gt;
     // 1. Use Navigation to wrap the entire root component&lt;br&gt;
     Navigation(this.stackPath) {&lt;br&gt;
        List() {&lt;br&gt;
          ListItem(){&lt;br&gt;
            Text("朋友圈")&lt;br&gt;
              .fontSize(20)&lt;br&gt;
              .width("100%")&lt;br&gt;
          }&lt;br&gt;
          .height(50)&lt;br&gt;
          .width("100%")&lt;br&gt;
          .padding({&lt;br&gt;
            left: 20&lt;br&gt;
          })&lt;br&gt;
          .onClick(() =&amp;gt; {&lt;br&gt;
            this.stackPath.pushPath({&lt;br&gt;
              name: 'friend'&lt;br&gt;
            })&lt;br&gt;
          })&lt;br&gt;
 ​&lt;br&gt;
          ListItem(){&lt;br&gt;
            Text("直播")&lt;br&gt;
              .fontSize(20)&lt;br&gt;
              .width("100%")&lt;br&gt;
          }&lt;br&gt;
          .height(50)&lt;br&gt;
          .width("100%")&lt;br&gt;
          .padding({&lt;br&gt;
            left: 20&lt;br&gt;
          })&lt;br&gt;
          .onClick(() =&amp;gt; {&lt;br&gt;
            this.stackPath.pushPath({&lt;br&gt;
              name: 'live'&lt;br&gt;
            })&lt;br&gt;
          })&lt;br&gt;
          ListItem(){&lt;br&gt;
            Text("摇一摇")&lt;br&gt;
              .fontSize(20)&lt;br&gt;
              .width("100%")&lt;br&gt;
          }&lt;br&gt;
          .height(50)&lt;br&gt;
          .width("100%")&lt;br&gt;
          .padding({&lt;br&gt;
            left: 20&lt;br&gt;
          })&lt;br&gt;
          .onClick(() =&amp;gt; {&lt;br&gt;
            this.stackPath.pushPath({&lt;br&gt;
              name: 'shake'&lt;br&gt;
            })&lt;br&gt;
          })&lt;br&gt;
        }&lt;br&gt;
        .divider({&lt;br&gt;
          strokeWidth: 2,&lt;br&gt;
          color: "#ccc"&lt;br&gt;
        })&lt;br&gt;
     }&lt;br&gt;
     .navDestination(this.getRouterBuilder)&lt;br&gt;
     .mode(NavigationMode.Auto)&lt;br&gt;
 ​&lt;br&gt;
   }&lt;br&gt;
 }&lt;br&gt;
 import { IParams } from "./NavigationCase"&lt;br&gt;
 ​&lt;br&gt;
 @Component&lt;br&gt;
 export struct NavigationCase_friend {&lt;br&gt;
   @Consume navStackPath: NavPathStack&lt;br&gt;
   @State age: number = 0&lt;br&gt;
   @State name: string = ''&lt;br&gt;
 ​&lt;br&gt;
   build() {&lt;br&gt;
     NavDestination() {&lt;br&gt;
       Text("朋友圈")&lt;br&gt;
       Button("点我返回上一页")&lt;br&gt;
         .onClick(() =&amp;gt; {&lt;br&gt;
           this.navStackPath.pop()&lt;br&gt;
         })&lt;br&gt;
 ​&lt;br&gt;
       Text(this.name + this.age)&lt;br&gt;
 ​&lt;br&gt;
     }.onWillAppear(() =&amp;gt; {&lt;br&gt;
       const params = this.navStackPath.getParamByName('friend') as IParams[]&lt;br&gt;
       this.age = params[params.length - 1]?.age&lt;br&gt;
       this.name = params[params.length - 1]?.name&lt;br&gt;
       AlertDialog.show({ message: JSON.stringify(params, null, 2) })&lt;br&gt;
     })&lt;br&gt;
   }&lt;br&gt;
 }&lt;br&gt;
The second way: WrapBuilder&lt;br&gt;
wrapBuilder can wrap a global builder, which will not be rendered immediately, and needs to run the builder method directly&lt;/p&gt;

&lt;p&gt;Subcomponents need to export the global builder separately&lt;/p&gt;

&lt;p&gt;WrapBuilder&lt;/p&gt;

&lt;p&gt;wrapBuilder is a global function&lt;/p&gt;

&lt;p&gt;It will return a type of WrapBuilder&amp;lt;[]&amp;gt;, the empty array is the type of the parameter&lt;/p&gt;

&lt;p&gt;map.get(name).builder()&lt;br&gt;
import { FriendPageBuilder } from "./NavigationCase_friend"&lt;br&gt;
 import { LivePageBuilder } from "./NavigationCase_live"&lt;br&gt;
 import { LookPageBuilder } from "./NavigationCase_look"&lt;br&gt;
 ​&lt;br&gt;
 export const RouterMap: Map&amp;gt; = new Map()&lt;br&gt;
 ​&lt;br&gt;
 RouterMap.set("look", wrapBuilder(LookPageBuilder))&lt;br&gt;
 RouterMap.set("live", wrapBuilder(LivePageBuilder))&lt;br&gt;
 RouterMap.set("friend", wrapBuilder(FriendPageBuilder))&lt;br&gt;
 @Component&lt;br&gt;
 export struct NavigationCase_look {&lt;br&gt;
   @Consume navStackPath: NavPathStack&lt;br&gt;
 ​&lt;br&gt;
   build() {&lt;br&gt;
     NavDestination() {&lt;br&gt;
       Text("看一看")&lt;br&gt;
       Button("点我去到live")&lt;br&gt;
         .onClick(() =&amp;gt; {&lt;br&gt;
           this.navStackPath.pushPath({ name: 'live' })&lt;br&gt;
         })&lt;br&gt;
 ​&lt;br&gt;
       Button("返回到根首页")&lt;br&gt;
         .onClick(() =&amp;gt; this.navStackPath.clear())&lt;br&gt;
     }&lt;br&gt;
   }&lt;br&gt;
 }&lt;br&gt;
 ​&lt;br&gt;
 &lt;a class="mentioned-user" href="https://dev.to/builder"&gt;@builder&lt;/a&gt;&lt;br&gt;
 export function LookPageBuilder() {&lt;br&gt;
   NavigationCase_look()&lt;br&gt;
 }&lt;br&gt;
 ​&lt;br&gt;
 import { RouterMap } from './NavigationCase_WrapBuilder'&lt;br&gt;
 ​&lt;br&gt;
 export interface IParams {&lt;br&gt;
   name: string&lt;br&gt;
   age: number&lt;br&gt;
 }&lt;br&gt;
 ​&lt;br&gt;
 @Entry&lt;br&gt;
 @Component&lt;br&gt;
 struct NavigationCase {&lt;br&gt;
   @Provide navStackPath: NavPathStack = new NavPathStack()&lt;br&gt;
 ​&lt;br&gt;
   &lt;a class="mentioned-user" href="https://dev.to/builder"&gt;@builder&lt;/a&gt;&lt;br&gt;
   getBuilder(name: string) {&lt;br&gt;
     RouterMap.get(name)?.builder()&lt;br&gt;
   }&lt;br&gt;
 ​&lt;br&gt;
   build() {&lt;br&gt;
     Navigation(this.navStackPath) {&lt;br&gt;
       List({ space: 20 }) {&lt;br&gt;
         ListItem() {&lt;br&gt;
           Text("朋友圈")&lt;br&gt;
             .width("100%")&lt;br&gt;
             .height(60)&lt;br&gt;
             .backgroundColor(Color.Pink)&lt;br&gt;
         }.onClick(() =&amp;gt; {&lt;br&gt;
           this.navStackPath.pushPath({ name: 'friend', param: { name: 'aaa', age: 18 } as IParams })&lt;br&gt;
         })&lt;br&gt;
 ​&lt;br&gt;
         ListItem() {&lt;br&gt;
           Text("直播")&lt;br&gt;
             .width("100%")&lt;br&gt;
             .height(60)&lt;br&gt;
             .backgroundColor(Color.Brown)&lt;br&gt;
         }&lt;br&gt;
         .onClick(() =&amp;gt; {&lt;br&gt;
           this.navStackPath.pushPath({ name: 'live' })&lt;br&gt;
         })&lt;br&gt;
 ​&lt;br&gt;
         ListItem() {&lt;br&gt;
           Text("看一看")&lt;br&gt;
             .width("100%")&lt;br&gt;
             .height(60)&lt;br&gt;
             .backgroundColor(Color.Orange)&lt;br&gt;
         }&lt;br&gt;
         .onClick(() =&amp;gt; {&lt;br&gt;
           this.navStackPath.pushPathByName('look', null)&lt;br&gt;
         })&lt;br&gt;
       }&lt;br&gt;
     }&lt;br&gt;
     .mode(NavigationMode.Auto)&lt;br&gt;
     .navDestination(this.getBuilder)&lt;br&gt;
   }&lt;br&gt;
 }&lt;br&gt;
The third method: configuration routing&lt;br&gt;
The root component must be wrapped by Navigation&lt;br&gt;
Must be bound to NavStackPath&lt;br&gt;
Subcomponents must be wrapped by NavDestination&lt;br&gt;
There must be a global builder to render subcomponents&lt;br&gt;
No need to configure .navDestination&lt;br&gt;
A routerMap json file [“routerMap”: “$profile:router_map”] needs to be configured in the project’s module.json5&lt;br&gt;
Configure three contents in the routerMap file — name-builder-file path&lt;br&gt;
The route map mode can only be tested in the simulator&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
   "routerMap": [&lt;br&gt;
     {&lt;br&gt;
       "name": "main",&lt;br&gt;
       "buildFunction": "MainPageBuilder",&lt;br&gt;
       "pageSourceFile": "src/main/ets/pages/AgainNavigation/MainPage.ets"&lt;br&gt;
     },&lt;br&gt;
     {&lt;br&gt;
       "name": "detail",&lt;br&gt;
       "buildFunction": "PageDetailBuilder",&lt;br&gt;
       "pageSourceFile": "src/main/ets/pages/AgainNavigation/PageDetail.ets"&lt;br&gt;
     }&lt;br&gt;
   ]&lt;br&gt;
 }&lt;br&gt;
Navigation parameter — Return — Return to the first page&lt;br&gt;
this.stackPath.getParamByName(“当前页的name”)&lt;/p&gt;

&lt;p&gt;.onWillAppear(() =&amp;gt; {&lt;br&gt;
      const params =  this.stackPath.getParamByName("detail") as Params[]&lt;br&gt;
       this.age = params[params.length - 1]?.age&lt;br&gt;
      console.log("onWillAppear")&lt;br&gt;
    })&lt;br&gt;
If no parameters are passed, the array still has a length, but the content is undefined&lt;br&gt;
Return to home page: this.stackPath.popToIndex(-1)&lt;br&gt;
Return to previous page: this.stackPath.pop()&lt;br&gt;
// Return to the previous PageOne page // this.pageStack.popToName(“PageOne”)&lt;br&gt;
// Return to the root home page (clear all pages in the stack) // this.pageStack.clear()&lt;/p&gt;

&lt;p&gt;pushPath (append)/replacePath (replace), unlimited layers&lt;br&gt;
router-32 layers&lt;br&gt;
pushPath({ name: ‘’, param: 123 }), assuming that the object to be passed must be of a specific type, such as interface/class/Record/Map&lt;br&gt;
receive parameter this.stackPath.getParamByName(“xx”) — xx is the name value of the current component&lt;br&gt;
the parameter type obtained is an unknown[], forcing developers to perform as specific type[]&lt;br&gt;
to take the last parameter — if no parameter is passed, the array still exists, but the content is undfined&lt;/p&gt;

&lt;p&gt;Some common properties of the Navigation component&lt;br&gt;
.title() // Title, you can set a custom builder&lt;br&gt;
.titleMode() // Set the page title bar display mode, common properties: NavigationTitleMode.Mini&lt;br&gt;
.hideTitleBar(true) // Hide the title bar&lt;br&gt;
.mode() // Set the display mode of the navigation bar, commonly used Stack, no column display&lt;br&gt;
.navDestination() // Create a NavDestination component. Use the builder function to construct a NavDestination component based on name and param. There can only be one root node under the builder. The builder allows a layer of custom components outside the NavDestination component, but custom components are not allowed to set properties and events, otherwise they will only display blank.&lt;/p&gt;

&lt;p&gt;Recommendations for NavDestination Components&lt;br&gt;
It is not recommended to set layout-related properties such as position and size, as this may cause abnormal page display.&lt;/p&gt;

</description>
      <category>harmony</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>router route jump</title>
      <dc:creator>skyrejer</dc:creator>
      <pubDate>Thu, 29 May 2025 15:12:51 +0000</pubDate>
      <link>https://dev.to/skyrejer/router-route-jump-41k2</link>
      <guid>https://dev.to/skyrejer/router-route-jump-41k2</guid>
      <description>&lt;p&gt;Routing Mode&lt;br&gt;
Routing provides two different jump modes, and different modes determine whether the page will create multiple instances.&lt;br&gt;
Standard: Multi-instance mode, which is also the default jump mode. The target page is added to the top of the page stack, regardless of whether there is a page with the same URL.&lt;br&gt;
Single: Single instance mode. If the URL of the target page already exists in the page stack, the page with the same URL closest to the top of the stack will be moved to the top of the stack, and the page will become a new page. If the URL of the target page does not exist in the page stack, it will jump according to the default multi-instance mode.&lt;br&gt;
In short:&lt;br&gt;
Standard: Regardless of whether it has been added before, it will always be added to the page stack [Common] [Default]&lt;br&gt;
Single: If a page has been added before, the previously added page will be used [Use depending on the situation]&lt;/p&gt;

&lt;p&gt;router.pushUrl(options, mode?)  // router.pushUrl(options, router.RouterMode.Standard)&lt;br&gt;
router.replaceUrl(option, mode?)&lt;br&gt;
Page jump and back&lt;br&gt;
Normal jump (can return)&lt;/p&gt;

&lt;p&gt;router.pushUrl({&lt;br&gt;
 url: 'Page address'  // page/Index&lt;br&gt;
})&lt;br&gt;
Replace jump (cannot return)&lt;/p&gt;

&lt;p&gt;router.replaceUrl({&lt;br&gt;
    url: "Page address"&lt;br&gt;
})&lt;br&gt;
return&lt;/p&gt;

&lt;p&gt;router.back()&lt;br&gt;
Both router.pushUrl() and router.replaceUrl can jump to the page, the difference is: whether to replace the current page&lt;/p&gt;

&lt;p&gt;router.pushUrl(): The target page will not replace the current page, but will be pushed into the page stack. This can preserve the state of the current page, and you can return to the current page by pressing the back key or calling the router.back() method&lt;br&gt;
router.replaceUrl(): The target page will replace the current page and destroy the current page. This can release the resources of the current page, and you cannot return to the current page&lt;/p&gt;

&lt;p&gt;Page Stack&lt;br&gt;
The page stack is a data structure used to store program runtime pages, following the first-in-last-out principle&lt;/p&gt;

&lt;p&gt;Router mode jump routing, the maximum capacity of the page stack is 32 pages&lt;/p&gt;

&lt;p&gt;router.clear()  // Clear the page stack&lt;br&gt;
router.getLength()  // Returns the current length of the page stack&lt;br&gt;
router.getState()  // Get page status&lt;br&gt;
 let page = router.getState()&lt;br&gt;
 console.log("current Index = " + page.index)&lt;br&gt;
 console.log("current name = " + page.name)&lt;br&gt;
 console.log("current path = " + page.path)&lt;br&gt;
parameter&lt;br&gt;
pushUrl&lt;/p&gt;

&lt;p&gt;router.pushUrl({&lt;br&gt;
    url: "url string",&lt;br&gt;
    params: {&lt;br&gt;
        // Passing parameters as objects&lt;br&gt;
    }&lt;br&gt;
})&lt;/p&gt;

&lt;p&gt;router.getParams() as object  // Receiving route parameters&lt;br&gt;
replaceUrl&lt;/p&gt;

&lt;p&gt;router.replaceUrl({&lt;br&gt;
    url: "URL",&lt;br&gt;
    params: {&lt;br&gt;
        // Passing parameters as objects&lt;br&gt;
    }&lt;br&gt;
})&lt;br&gt;
back&lt;/p&gt;

&lt;p&gt;router.back({&lt;br&gt;
 url: 'URL',&lt;br&gt;
 params: {&lt;br&gt;
  // Passing parameters as objects&lt;br&gt;
 }&lt;br&gt;&lt;br&gt;
// Parameters can be passed when back is returned, but generally no parameters are required for back&lt;br&gt;
})&lt;br&gt;
Cross-package jump in router mode&lt;br&gt;
Navigation route jump — cross-package: hap -&amp;gt; hsp / hsp -&amp;gt; hsp&lt;/p&gt;

&lt;p&gt;Navigation naturally supports cross-package jump&lt;/p&gt;

&lt;p&gt;By path&lt;/p&gt;

&lt;p&gt;Rule: @bundle:package name/module name/ets/pages/xx page // The prefix can be encapsulated into a constant: @bundle:package name&lt;/p&gt;

&lt;p&gt;router.pushUrl({&lt;br&gt;
    url: '@bundle:com.itheima.sz.new.content/home/ets/pages/Index'&lt;br&gt;
})&lt;br&gt;
By name (compared to the path method, it is more troublesome)&lt;/p&gt;

&lt;p&gt;Modify the page to jump to @Entry ==&amp;gt; @Entry({routerName: ‘xxx’ })&lt;br&gt;
Add dependencies, add the hsp module to jump to in oh-package.json&lt;br&gt;
Import(“module name/path file”) in the page you want to jump to&lt;br&gt;
router.pushNamedRoute&lt;/p&gt;

&lt;p&gt;import { router } from '&lt;a class="mentioned-user" href="https://dev.to/kit"&gt;@kit&lt;/a&gt;.ArkUI';&lt;/p&gt;

&lt;p&gt;import("home/src/main/ets/pages/Index")&lt;/p&gt;

&lt;p&gt;@Entry&lt;br&gt;
@Component&lt;br&gt;
struct IndexPage {&lt;br&gt;
  build() {&lt;br&gt;
    RelativeContainer() {&lt;br&gt;
      Button("Cross-package jump 1-path method")&lt;br&gt;
        .alignRules({&lt;br&gt;
          center: { anchor: '&lt;strong&gt;container&lt;/strong&gt;', align: VerticalAlign.Center },&lt;br&gt;
          middle: { anchor: '&lt;strong&gt;container&lt;/strong&gt;', align: HorizontalAlign.Center }&lt;br&gt;
        })&lt;br&gt;
        .onClick(() =&amp;gt; {&lt;br&gt;
          router.pushUrl({&lt;br&gt;
            url: &lt;code&gt;@bundle:com.itheima.sz.new.content/home/ets/pages/Index&lt;/code&gt;&lt;br&gt;
          })&lt;br&gt;
          // Rule - @bundle:package name/module name/ets/pages/xxx page&lt;br&gt;
        })&lt;br&gt;
        .id("btn1")&lt;br&gt;
      Button("Cross-package jump 2-name method")&lt;br&gt;
        .alignRules({&lt;br&gt;
          top: { anchor: 'btn1', align: VerticalAlign.Bottom },&lt;br&gt;
          middle: { anchor: '&lt;strong&gt;container&lt;/strong&gt;', align: HorizontalAlign.Center }&lt;br&gt;
        })&lt;br&gt;
        .margin({&lt;br&gt;
          top: 20&lt;br&gt;
        })&lt;br&gt;
        .onClick(() =&amp;gt; {&lt;br&gt;
          // router.pushUrl({&lt;br&gt;
          //   url: &lt;code&gt;@bundle:com.itheima.sz.new.content/home/ets/pages/Index&lt;/code&gt;&lt;br&gt;
          // })&lt;br&gt;
          // Rule - @bundle:package name/module name/ets/pages/xxx page&lt;br&gt;
          router.pushNamedRoute({&lt;br&gt;
            name: 'homePage'&lt;br&gt;
          })&lt;br&gt;
        })&lt;br&gt;
    }&lt;br&gt;
    .height('100%')&lt;br&gt;
    .width('100%')&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>harmony</category>
      <category>programming</category>
    </item>
    <item>
      <title>A brief introduction to V1 and V2 decorators in HarmonyOS development</title>
      <dc:creator>skyrejer</dc:creator>
      <pubDate>Thu, 29 May 2025 15:09:29 +0000</pubDate>
      <link>https://dev.to/skyrejer/a-brief-introduction-to-v1-and-v2-decorators-in-harmonyos-development-1ibb</link>
      <guid>https://dev.to/skyrejer/a-brief-introduction-to-v1-and-v2-decorators-in-harmonyos-development-1ibb</guid>
      <description>&lt;p&gt;To use the V1 decorator, you need to decorate the component with the @Component decorator, while V2 needs to use @ComponentV2&lt;br&gt;
V1 Decorator&lt;br&gt;
@State: Components manage their own states. Adding @State allows ordinary variables to become state variables. When variables are updated, the UI is automatically refreshed.&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/prop"&gt;@prop&lt;/a&gt;: Commonly used for parent-child transmission, one-way data flow, parent components are passed to child components, and the transmission is irreversible.&lt;br&gt;
The difference between &lt;a class="mentioned-user" href="https://dev.to/prop"&gt;@prop&lt;/a&gt; and @State, parent-child transmission can also use @State, but &lt;a class="mentioned-user" href="https://dev.to/prop"&gt;@prop&lt;/a&gt; one-way data flow is more semantic and can avoid component state disorder&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/link"&gt;@link&lt;/a&gt;: Parent-child two-way communication&lt;br&gt;
@ObjectLink/@Observed/@Track: Partially refresh the UI, better performance, can be used to prevent image flickering&lt;br&gt;
@Provide/@Consume: Although the official said it is a two-way communication, in fact, it can only pass values ​​from @Provide to @Consume, and cannot be passed in the reverse direction&lt;/p&gt;

&lt;p&gt;V2 Decorator&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/local"&gt;@local&lt;/a&gt; is equivalent to @State&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/param"&gt;@param&lt;/a&gt;: from parent to child, from parent component to child component, child component cannot modify the value of parent component, if modified, error will be reported, if you want to modify, you need to use @ Once + @ Param&lt;/p&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;p&gt;Once once is used, the parent component only passes the value to the child component for the first time, and the subsequent child component data is maintained by itself&lt;br&gt;
@ Param [non-@ Once] way to pass the value, if the child component modifies the value of the parent component through callback, then this modification will not be synchronized to the child component&lt;br&gt;
@ Require: whether it must be passed&lt;br&gt;
@ ObservedV2 + @ Tace: local refresh can be achieved, @ Tace adds properties that need to set state variables&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/provider"&gt;@provider&lt;/a&gt;() / @Consumer(): This version truly realizes two-way communication, and its functions are more powerful than V1&lt;/p&gt;

&lt;p&gt;@ Provider() isScale: boolean = false&lt;br&gt;
@ Consumer() isScale: booean = false&lt;br&gt;
Other decorators&lt;br&gt;
@ Event: callback function used to implement parent-child component communication&lt;/p&gt;

&lt;p&gt;// Parent Component&lt;br&gt;
getState = (state: string) =&amp;gt; { console.log("状态：", state) }&lt;/p&gt;

&lt;p&gt;// From father to son&lt;br&gt;
TSMTest({&lt;br&gt;
    getState: this.getState&lt;br&gt;
})&lt;/p&gt;

&lt;p&gt;// Subcomponents&lt;br&gt;
@ Event getState: (state: string) =&amp;gt; void = (state: string) =&amp;gt; {}Watch&lt;br&gt;
Watch&lt;/p&gt;

&lt;p&gt;V1 version: @ Watch&lt;br&gt;
@ Watch is used to monitor state variables. If the developer needs to pay attention to whether the value of a state variable has changed, @Watch can be used to set a callback function for the state variable.&lt;br&gt;
Decorator parameter: required. Constant string, the string needs to be quoted. It is a reference to the method of (string) =&amp;gt; void custom member function.&lt;/p&gt;

&lt;p&gt;If other state variables are changed in the @ Watch method, it will also cause state changes and @ Watch execution;&lt;/p&gt;

&lt;p&gt;During the first initialization, the @ Watch decorated method will not be called, that is, the initialization is not considered to be a change in the state variable. The @ Watch callback method will only be called when the state changes subsequently.&lt;/p&gt;

&lt;p&gt;To avoid the generation of loops, it is recommended not to modify the current decorated state variable in the @ Watch callback method;&lt;/p&gt;

&lt;p&gt;The property value update function will delay the re-rendering of the component, so the callback function should only perform fast operations;&lt;/p&gt;

&lt;p&gt;V2 version: @ Monitor&lt;/p&gt;

&lt;p&gt;@ Monitor("isScale")&lt;br&gt;
getShowScale() {&lt;br&gt;
    if(this.isScale) {&lt;br&gt;
        console.log("Size recovery")&lt;br&gt;
    }&lt;br&gt;
}&lt;br&gt;
The @ Monitor decorator has the ability to monitor deeply, and can monitor changes in specified items in nested classes, multi-dimensional arrays, and object arrays. Monitoring changes in member attributes in nested classes and object arrays requires that the class be decorated with @ ObservedV2 and the attribute be decorated with &lt;a class="mentioned-user" href="https://dev.to/trace"&gt;@trace&lt;/a&gt;.&lt;br&gt;
Only updates to state variables can trigger the callback function of @ Monjtor&lt;br&gt;
A single @ Monitor decorator can monitor changes in multiple attributes at the same time. When these attributes change together in an event, the callback method of @ Monitor will only be triggered once.&lt;br&gt;
In the inheritance class scenario, @ Monitor can be defined in the parent and child components for the same attribute to monitor. When the attribute changes, the @ Monitor callback defined in the parent and child components will be called.&lt;br&gt;
@ Monitor supports monitoring items in arrays, including multi-dimensional arrays and object arrays. @ Monitor cannot monitor changes caused by API calls of built-in types (Array, Map, Date, Set). When @ Monitor monitors the entire array, it can only observe the assignment of the entire array. You can determine whether the array has changes such as insertion and deletion by monitoring the length change of the array. Currently, only the “.” method is supported to express monitoring of deep attributes and array items.&lt;br&gt;
If the properties monitored by @ Monitor are changed multiple times in one event, the last modification will prevail.&lt;/p&gt;

&lt;p&gt;Column() {&lt;br&gt;
      Button("change count to 1000")&lt;br&gt;
        .onClick(() =&amp;gt; {&lt;br&gt;
          for (let i = 1; i &amp;lt;= 1000; i++) {&lt;br&gt;
            this.frequence.count = i;&lt;br&gt;
          }&lt;br&gt;
        })&lt;br&gt;
      Button("change count to 0 then to 1000")&lt;br&gt;
        .onClick(() =&amp;gt; {&lt;br&gt;
          for (let i = 999; i &amp;gt;= 0; i--) {&lt;br&gt;
            this.frequence.count = i;&lt;br&gt;
          }&lt;br&gt;
          // The onCountChange method is not triggered in the end&lt;br&gt;
          this.frequence.count = 1000; &lt;br&gt;
        })&lt;br&gt;
    }&lt;br&gt;
After clicking the button “change count to 1000”, the onCountChange method is triggered once and the log “count change from 0 to 1000” is output. After clicking the button “change count to 0 then to 1000”, the value of the attribute count does not change before and after the event and is 1000, so the onCountChange method is not triggered.&lt;/p&gt;

&lt;p&gt;limit&lt;br&gt;
When there are multiple monitoring methods for a property in a class, only the last defined monitoring method will take effect.&lt;br&gt;
The target property monitored by @ Monitor is determined at initialization and cannot be changed dynamically. It is not recommended for developers to use variables as parameters for @ Monitor initialization.&lt;br&gt;
Developers are advised to avoid changing the monitored property again in @ Monitor, which will cause an infinite loop.&lt;/p&gt;

&lt;p&gt;Summarize&lt;br&gt;
@ Watch can only monitor a single state variable and follow the state variable observation capability (one level).&lt;/p&gt;

&lt;p&gt;@ Monitor can monitor multiple state variables at the same time and follow the state variable observation capability (deep level) [requires &lt;br&gt;
Takudzwa Bouy Tace Jangah&lt;br&gt;
.&lt;/p&gt;

&lt;p&gt;AppStorage&lt;br&gt;
The V1 version of AppStorage can be directly decorated with @ StorageProp + @ StorageLink. The V2 decorator is slightly more complicated, but the benefits are more obvious. The V1 decorator shares one AppStorage, while the V2 decorator can implement multiple AppStorages.&lt;/p&gt;

&lt;p&gt;@ ObservedV2&lt;br&gt;
class AppStorageKey {&lt;br&gt;
    @ Tace&lt;br&gt;
    isScale: boolean = false&lt;br&gt;
    textController: TextController = new TextController()&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;@ Local appStorage: AppStorageKey = AppStorageV2.connect(AppStorageKey, () =&amp;gt; new AppStorageKey())!&lt;/p&gt;

&lt;p&gt;// use&lt;br&gt;
this.appStorage.isScale = true&lt;br&gt;
Custom component mix scenarios&lt;br&gt;
V2 decorators cannot be used in V1’s custom components, otherwise compilation errors will occur.&lt;/p&gt;

&lt;p&gt;When there is no variable transfer between components, V2’s custom components can be used in V1’s custom components, including custom components decorated with @ ComponentV2 imported from a third party.&lt;/p&gt;

&lt;p&gt;When there is variable transfer between components, V1’s variables are passed to V2’s custom components, with the following restrictions:&lt;/p&gt;

&lt;p&gt;Variables in V1 that are not decorated with decorators (hereinafter referred to as ordinary variables): V2 can only receive them using @ Param.&lt;/p&gt;

&lt;p&gt;Variables in V1 that are decorated with decorators (hereinafter referred to as state variables): V2 can only receive them using @ Param decorators, and are limited to simple data types such as boolean, number, enum, string, undefined, and null.&lt;/p&gt;

&lt;p&gt;V1 decorators cannot be used in V2’s custom components, otherwise compilation errors will occur.&lt;/p&gt;

&lt;p&gt;When there is no variable transfer between components, V2’s custom components can use V1’s custom components, including custom components decorated with @ Component imported from a third party.&lt;/p&gt;

&lt;p&gt;When there is variable transfer between components, the variables of V2 are passed to the custom components of V1, with the following restrictions:&lt;/p&gt;

&lt;p&gt;Variables in V2 that are not decorated by decorators (hereinafter referred to as ordinary variables): If V1 uses decorators to decorate the received data, it can only be passed through @State, &lt;a class="mentioned-user" href="https://dev.to/prop"&gt;@prop&lt;/a&gt;, and @Provide.&lt;br&gt;
Variables in V2 that are decorated by decorators (hereinafter referred to as state variables): If V1 uses decorators to decorate the received data, built-in type data is not supported: Array, Set, Map, Date.&lt;/p&gt;

&lt;p&gt;How to migrate from V1 to V2 decorators&lt;br&gt;
&lt;a href="https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/arkts-v1-v2-migration-V14" rel="noopener noreferrer"&gt;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/arkts-v1-v2-migration-V14&lt;/a&gt;&lt;/p&gt;

</description>
      <category>harmony</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
