OpenHarmony application ArkUI state management development example

This article is reproduced from "#2023 Blind Box + Code# OpenHarmony Application ArkUI State Management Development Paradigm", author: zhushangyuan_

This article implements state management in ArkUI based on the orange shopping application .

In the declarative UI programming framework, the UI is the running result of the program state, and the user constructs a UI model, in which the runtime state of the application is a parameter. When the parameters are changed, the UI will also make corresponding changes as the returned result. The re-rendering of the UI brought about by these runtime state changes is collectively referred to as the state management mechanism in ArkUI.

Custom components have variables, which must be decorated with decorators to become state variables. Changes in state variables will cause UI rendering to refresh. If you don't use state variables, the UI can only be rendered at initialization, and will not be refreshed later. The figure below shows the relationship between State and View (UI).

Manage state owned by components

@State decorator: state inside the component

Variables decorated with @State, or state variables, are bound to the rendering of the custom component once the variable has a state property. When the state changes, the UI will have a corresponding rendering change.

Among the decorators related to state variables, @State is the most basic, a decorator that makes variables have state attributes, and it is also the data source for most state variables.

@link decorator: parent-child two-way synchronization

The variable decorated with @Link in the child component establishes two-way data binding with the corresponding data source in the parent component.

A variable decorated with @Link shares the same value as its data source in its parent component.

@Componentexport struct DetailPage {
   
     @State currentLocation: string = ''}

Declare the current location variable currentLocation in the parent component DetailPage

Panel(this.isPanel) {
   
       Location({ isPanel: $isPanel, currentLocation: $currentLocation })}

Pass the currentLocation variable to the child component Location

@Componentexport struct Location {
   
     @Link currentLocation: string}

The child component receives the currentLocation decorated with @Link.

  @Builder cityList(city: any) {
   
       if (this.currentLocation === city.name) {
   
         List() {
   
           ForEach(city.city, twoCity => {
   
             ListItem() {
   
               Column() {
   
                 Text(`${twoCity}`)                .width('100%')                .height(30)                .fontSize(14)                .onClick(() => {
   
                     this.currentLocation = city.name + '/' + twoCity                })            }          }        })      }      .width('100%')      .divider({ strokeWidth: 2, color: $r('app.color.divider'), startMargin: 0, endMargin: 20 })    }  }

Changes to the currentLocation variable in the child component will synchronize the currentLocation in the parent component.

Manage state owned by the application

AppStorage is the application's global UI state storage, which is bound to the application process, created by the UI framework when the application starts, and provides central storage for the application UI state attributes.

Unlike LocalStorage, LocalStorage is page-level and is usually used for data sharing within a page. For AppStorage, it is application-level global state sharing. AppStorage usage scenarios and related decorators: @StorageProp and @StorageLink

@StorageProp

@StorageProp(key) establishes one-way data synchronization with the attribute corresponding to the key in AppStorage. We allow local changes to occur, but for @StorageProp, local changes will never be synchronized back to AppStorage. On the contrary, if AppStorage gives a key When the property changes, the change will be synchronized to @StorageProp, and the local modification will be overwritten.

@Entry@Componentstruct HomePage {
   
     @State curBp: string = 'md' // curBp指当前窗口断点,sm代表小屏,md代表中屏,lg代表大屏}

In the Home.ets page, use @State to declare the current window type: curBp variable and assign the initial value to md, representing the middle screen.

  isBreakpointSM = (mediaQueryResult) => {
   
       if (mediaQueryResult.matches) {
   
         this.curBp = 'sm'      AppStorage.SetOrCreate('curBp', this.curBp)    }  }  isBreakpointMD = (mediaQueryResult) => {
   
       if (mediaQueryResult.matches) {
   
         this.curBp = 'md'      AppStorage.SetOrCreate('curBp', this.curBp)    }  }  isBreakpointLG = (mediaQueryResult) => {
   
       if (mediaQueryResult.matches) {
   
         this.curBp = 'lg'      AppStorage.SetOrCreate('curBp', this.curBp)    }  }

According to the screen size, set curBp to the corresponding value, and save it in AppStorage with SetOrCreate() method.

Use the curBp variable directly in the subcomponent NavigationHomePage

@Entry@Componentexport struct NavigationHomePage {
   
     @StorageProp('curBp') curBp: string = 'sm'}

curBp is judged according to the size of the window and cannot be changed, so use @StorageProp('curBp') to establish one-way data synchronization with AppStorage('curBp').

@StorageLink

@StorageLink(key) establishes two-way data synchronization with the attribute corresponding to the key in AppStorage:

1. When a local modification occurs, the modification will be synchronized back to AppStorage;

2. After the modification in AppStorage occurs, the modification will be synchronized to all properties bound to the corresponding key of AppStorage, including one-way (@StorageProp and one-way binding variables created through Prop), two-way (@StorageLink and through Link Created two-way bind variables) variables and other instances (such as PersistentStorage).

@Entry@Componentstruct HomePage {
   
     @StorageLink('shoppingCartGoodsList') shoppingCartGoodsList: { data: { id: number } }[] = []}

In the Home.ets page, use the @StorageLink decorator to define shoppingCartGoodsList, which is used to obtain the global list of shopping cart items.

this.emitterClass.setShoppingCartGoodsList((eventData)=>{
   
       this.shoppingCartGoodsList.push(eventData.data.id)    AppStorage.SetOrCreate('shoppingCartGoodsList', this.shoppingCartGoodsList)})

Use AppStorage.SetOrCreate('shoppingCartGoodsList', this.shoppingCartGoodsList) to save the shopping cart product list in AppStorage.

Because the items in the shopping cart will be linked to changes, such as adding items to the shopping cart on the product details page, the shopping cart information also needs to be updated on the home page, so the shopping cart product list is decorated with the @StorageLink decorator, which is the same as AppStorage('shoppingCartGoodsList ') to establish two-way synchronization.

Run the test effect

Execute the following command to download the orange shopping application project:

git initgit config core.sparsecheckout trueecho code/Solutions/Shopping/OrangeShopping/ > .git/info/sparse-checkoutgit remote add origin https://gitee.com/openharmony/applications_app_samples.gitgit pull origin master

References

Tangerine shopping sample application

Guess you like

Origin blog.csdn.net/OpenHarmony_dev/article/details/132620680