Marco de desarrollo de HarmonyOS Learning Road Ark: aprendizaje del lenguaje ArkTS (Administración del estado 3)

@Link decorador: sincronización bidireccional padre-hijo

La variable decorada con @Link en el componente secundario establece un enlace de datos bidireccional con la fuente de datos correspondiente en el componente principal.

descripción general

Una variable decorada con @Link comparte el mismo valor que su fuente de datos en su componente principal.

Descripción de las reglas de uso del decorador

Decorador de variables @Link

ilustrar

parámetros del decorador

ninguno

Tipo de sincronización

Sincronización bidireccional.

@State, @StorageLink y @Link en el componente principal y @Link en el componente secundario pueden establecer una sincronización de datos bidireccional y viceversa.

Tipos variables que permiten la decoración

Objeto, clase, cadena, número, booleano, tipos de enumeración y matrices de estos tipos.

El tipo debe especificarse y es el mismo que el tipo de la variable de estado de enlace bidireccional.

No se admite ninguno, los tipos de unión de tipos simples y tipos complejos no se admiten, y no se permiten valores indefinidos y nulos.

ilustrar

Los tipos Longitud, ResourceStr y ResourceColor no se admiten, y Longitud, ResourceStr y ResourceColor son tipos de unión de tipos simples y tipos complejos.

El valor inicial de la variable decorada.

Ninguno, deshabilita la inicialización local.

Explicación de las reglas de acceso/transferencia de variables

pase/acceso

ilustrar

Inicializar y actualizar desde el componente principal

requerido. Cree enlaces bidireccionales con los componentes principales @State, @StorageLink y @Link. Permita las variables de decoración @State, @Link, @Prop, @Provide, @Consume, @ObjectLink, @StorageLink, @StorageProp, @LocalStorageLink y @LocalStorageProp en el componente principal para inicializar el componente secundario @Link.

A partir de la versión 9 de la API, el componente secundario @Link inicializa @State desde el componente principal con la sintaxis Comp({ aLink: this.aState }). Comp({aLink: $aState}) también es compatible.

Se utiliza para inicializar componentes secundarios

Permitido, puede usarse para inicializar variables regulares, @State, @Link, @Prop, @Provide.

Ya sea para admitir el acceso fuera del componente

Privado y solo se puede acceder desde el componente propietario.

Figura 1  Ilustración de las reglas de inicialización

Observar los cambios y el comportamiento.

observar cambios

  • Cuando el tipo de datos de la decoración es booleano, cadena o número, el cambio del valor se puede observar sincrónicamente.
  • Cuando el tipo de datos decorado es clase u objeto, puede observar los cambios de asignación y asignación de atributos, es decir, todos los atributos devueltos por Object.keys (observedObject).
  • Cuando el objeto decorado es una matriz, puede observar los cambios al agregar, eliminar y actualizar las celdas de la matriz en la matriz.

comportamiento del marco

Las variables decoradas con @Link comparten un ciclo de vida con el componente personalizado que describen.

Para comprender el mecanismo de inicialización y actualización de la variable @Link, es necesario comprender la relación entre el componente principal y el componente secundario que posee la variable @Link, el proceso de representación inicial y la actualización bidireccional (tome el componente principal como @ Estado como ejemplo).

  1. Representación inicial: se creará una nueva instancia del componente secundario después de ejecutar la función build() del componente principal. El proceso de inicialización es el siguiente:
    1. La variable @State en el componente principal debe especificarse para inicializar la variable @Link del componente secundario. El valor de la variable @Link del componente secundario se mantiene sincronizado con la variable de origen de datos de su componente principal (sincronización de datos bidireccional).
    2. La clase contenedora de la variable de estado @State del componente principal se pasa al componente secundario a través del constructor.Después de que la clase contenedora @Link del componente secundario obtiene la variable de estado @State del componente principal, registra la clase contenedora @Link actual este puntero a la clase contenedora @Link del componente padre Variables de estado.
  2. La actualización de la fuente de datos de @Link: es decir, la actualización de la variable de estado en el componente principal provoca la actualización de @Link del componente secundario relacionado. Pasos de procesamiento:
    1. A través de los pasos de la representación inicial, podemos ver que la clase contenedora @Link del componente secundario registra el puntero this actual en el componente principal. Después de cambiar la variable @State del componente principal, recorrerá y actualizará todos los componentes del sistema (elementid) y las variables de estado (como las clases contenedoras @Link) que dependen de él.
    2. Después de notificar la actualización de la clase contenedora @Link, se notificará la actualización a todos los componentes del sistema (elementId) que dependen de la variable de estado @Link en el subcomponente. De esta forma, se realiza la sincronización de datos de estado del componente padre con el componente hijo.
  3. Actualización de @Link: cuando se actualiza @Link en el componente secundario, los pasos de procesamiento son los siguientes (tome el componente principal como @State como ejemplo):
    1. Después de actualizar @Link, llame al método set de la clase contenedora @State del componente principal para sincronizar el valor actualizado con el componente principal.
    2. El componente secundario @Link y el componente principal @State atraviesan respectivamente los componentes dependientes del sistema y actualizan la interfaz de usuario correspondiente. De esta forma, el componente secundario @Link se vuelve a sincronizar con el componente principal @State.

Escenas a utilizar

@Link para tipos simples y tipos similares a objetos

En el siguiente ejemplo, haga clic en "Vista principal: Establecer botón amarillo" y "Vista principal: Establecer botón verde" en el componente principal ShufflingContainer para sincronizar los cambios del componente principal con los componentes secundarios y los cambios de las variables de decoración @Link en el componente secundario. Los componentes GreenButton y YellowButton también se sincronizarán con su componente principal.

class GreenButtonState {
  width: number = 0;
  constructor(width: number) {
    this.width = width;
  }
}
@Component
struct GreenButton {
  @Link greenButtonState: GreenButtonState;
  build() {
    Button('Green Button')
      .width(this.greenButtonState.width)
      .height(150.0)
      .backgroundColor('#00ff00')
      .onClick(() => {
        if (this.greenButtonState.width < 700) {
          // 更新class的属性,变化可以被观察到同步回父组件
          this.greenButtonState.width += 125;
        } else {
          // 更新class,变化可以被观察到同步回父组件
          this.greenButtonState = new GreenButtonState(100);
        }
      })
  }
}
@Component
struct YellowButton {
  @Link yellowButtonState: number;
  build() {
    Button('Yellow Button')
      .width(this.yellowButtonState)
      .height(150.0)
      .backgroundColor('#ffff00')
      .onClick(() => {
        // 子组件的简单类型可以同步回父组件
        this.yellowButtonState += 50.0;
      })
  }
}
@Entry
@Component
struct ShufflingContainer {
  @State greenButtonState: GreenButtonState = new GreenButtonState(300);
  @State yellowButtonProp: number = 100;
  build() {
    Column() {
      // 简单类型从父组件@State向子组件@Link数据同步
      Button('Parent View: Set yellowButton')
        .onClick(() => {
          this.yellowButtonProp = (this.yellowButtonProp < 700) ? this.yellowButtonProp + 100 : 100;
        })
      // class类型从父组件@State向子组件@Link数据同步
      Button('Parent View: Set GreenButton')
        .onClick(() => {
          this.greenButtonState.width = (this.greenButtonState.width < 700) ? this.greenButtonState.width + 100 : 100;
        })
      // class类型初始化@Link
      GreenButton({ greenButtonState: $greenButtonState })
      // 简单类型初始化@Link
      YellowButton({ yellowButtonState: $yellowButtonProp })
    }
  }
}

 @Enlace de tipo de matriz

@Component
struct Child {
  @Link items: number[];

  build() {
    Column() {
      Button(`Button1: push`).onClick(() => {
        this.items.push(this.items.length + 1);
      })
      Button(`Button2: replace whole item`).onClick(() => {
        this.items = [100, 200, 300];
      })
    }
  }
}

@Entry
@Component
struct Parent {
  @State arr: number[] = [1, 2, 3];

  build() {
    Column() {
      Child({ items: $arr })
      ForEach(this.arr,
        item => {
          Text(`${item}`)
        },
        item => item.toString()
      )
    }
  }
}

Como se mencionó anteriormente, el marco ArkUI puede observar la adición, eliminación y reemplazo de elementos de matriz. En este ejemplo, los tipos de @State y @Link son el mismo número[], no está permitido definir @Link como un tipo de número (@Link item: number), y crearlo con cada elemento de datos en el @State matriz en el subensamblaje del componente padre.

@Provide decorador y @Consume decorador: sincronización bidireccional con componentes descendientes

@Provide y @Consume se aplican a la sincronización bidireccional de datos con componentes descendientes y se aplican a escenarios en los que los datos de estado pasan entre varios niveles. A diferencia del paso mencionado anteriormente entre los componentes padre e hijo a través del mecanismo de parámetros con nombre, @Provide y @Consume se deshacen de los grilletes del mecanismo de paso de parámetros y realizan el paso entre niveles.

La variable decorada con @Provide está en el nodo ancestro, que puede entenderse como una variable de estado que se "proporciona" a los descendientes. La variable decorada con @Consume es para "consumir (vincular)" la variable proporcionada por el nodo ancestro en el componente descendiente.

descripción general

Las variables de estado decoradas con @Provide/@Consume tienen las siguientes características:

  • La variable de estado decorada por @Provide está automáticamente disponible para todos sus componentes descendientes, es decir, la variable se "proporciona" a sus componentes descendientes. Se puede ver que la conveniencia de @Provide es que los desarrolladores no necesitan pasar variables entre componentes varias veces.
  • Los descendientes utilizan @Consume para obtener las variables proporcionadas por @Provide y establecen una sincronización de datos bidireccional entre @Provide y @Consume. A diferencia de @State/@Link, el primero puede pasarse entre componentes padre-hijo de varios niveles.
  • @Provide y @Consume pueden vincularse con el mismo nombre de variable o el mismo alias de variable, y los tipos de variable deben ser los mismos.
// 通过相同的变量名绑定
@Provide a: number = 0;
@Consume a: number;

// 通过相同的变量别名绑定
@Provide('a') b: number = 0;
@Consume('a') c: number;

Descripción del decorador

Las reglas de @State también se aplican a @Provide, la diferencia es que @Provide también actúa como una fuente de sincronización para varios descendientes.

@Proporcionar decorador variable

ilustrar

parámetros del decorador

alias: const string, opcional.

Si se especifica un alias, la variable está vinculada por el alias; si no se especifica ningún alias, la variable está vinculada por el nombre de la variable.

Tipo de sincronización

Sincronización bidireccional.

Sincronización de datos de las variables @Provide a todas las variables @Consume y viceversa. La operación de sincronización bidireccional es la misma que la combinación de @State y @Link.

Tipos variables que permiten la decoración

Objeto, clase, cadena, número, booleano, tipos de enumeración y matrices de estos tipos.

No se admite ninguno, los tipos de unión de tipos simples y tipos complejos no se admiten, y no se permiten valores indefinidos y nulos.

Se debe especificar el tipo. La variable @Consume debe ser del mismo tipo que la variable @Provide.

ilustrar

Los tipos Longitud, ResourceStr y ResourceColor no se admiten, y Longitud, ResourceStr y ResourceColor son tipos de unión de tipos simples y tipos complejos.

El valor inicial de la variable decorada.

debe especificarse.

@Consume decorador de variables

ilustrar

parámetros del decorador

alias: const string, opcional.

Si se proporciona un alias, la variable @Provide debe tener el mismo alias para que coincida correctamente; de ​​lo contrario, el nombre de la variable debe ser el mismo para que coincida correctamente.

Tipo de sincronización

Bidireccional: desde variables @Provide (ver @Provide para más detalles) a todas las variables @Consume, y viceversa. La sincronización bidireccional funciona igual que la combinación de @State y @Link.

Tipos variables que permiten la decoración

Objeto, clase, cadena, número, booleano, tipos de enumeración y matrices de estos tipos.

any no es compatible, y no se permiten undefined y null.

Se debe especificar el tipo. La variable @Consume debe ser del mismo tipo que la variable @Provide.

ilustrar

  • Las variables decoradas con @Consume deben tener los atributos y alias correspondientes de las variables decoradas con @Provide en sus nodos principales o antepasados.

El valor inicial de la variable decorada.

Ninguno, deshabilita la inicialización local.

Explicación de las reglas de acceso/transferencia de variables

@Proporcionar pase/acceso

ilustrar

Inicializar y actualizar desde el componente principal

可选,允许父组件中常规变量、@State、@Link、@Prop、@Provide、@Consume、@ObjectLink、@StorageLink、@StorageProp、@LocalStorageLink和@LocalStorageProp装饰的变量装饰变量初始化子组件@Provide。

用于初始化子组件

允许,可用于初始化@State、@Link、@Prop、@Provide。

和父组件同步

否。

和后代组件同步

和@Consume双向同步。

是否支持组件外访问

私有,仅可以在所属组件内访问。

图1 @Provide初始化规则图示

@Consume传递/访问

说明

从父组件初始化和更新

禁止。通过相同的变量名和alias(别名)从@Provide初始化。

用于初始化子组件

允许,可用于初始化@State、@Link、@Prop、@Provide。

和祖先组件同步

和@Provide双向同步。

是否支持组件外访问

私有,仅可以在所属组件内访问

图2 @Consume初始化规则图示

观察变化和行为表现

观察变化

  • 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。
  • 当装饰的数据类型为class或者Object的时候,可以观察到赋值和属性赋值的变化(属性为Object.keys(observedObject)返回的所有属性)。
  • 当装饰的对象是array的时候,可以观察到数组的添加、删除、更新数组单元。

框架行为

  1. 初始渲染:
    1. @Provide装饰的变量会以map的形式,传递给当前@Provide所属组件的所有子组件;
    2. 子组件中如果使用@Consume变量,则会在map中查找是否有该变量名/alias(别名)对应的@Provide的变量,如果查找不到,框架会抛出JS ERROR;
    3. 在初始化@Consume变量时,和@State/@Link的流程类似,@Consume变量会保存在map中查找到的@Provide变量,并把自己注册给@Provide。
  2. 当@Provide装饰的数据变化时:
    1. 通过初始渲染的步骤可知,子组件@Consume已把自己注册给父组件。父组件@Provide变量变更后,会遍历更新所有依赖它的系统组件(elementid)和状态变量(@Consume);
    2. 通知@Consume更新后,子组件所有依赖@Consume的系统组件(elementId)都会被通知更新。以此实现@Provide对@Consume状态数据同步。
  3. 当@Consume装饰的数据变化时:
    1. 通过初始渲染的步骤可知,子组件@Consume持有@Provide的实例。在@Consume更新后调用@Provide的更新方法,将更新的数值同步回@Provide,以此实现@Consume向@Provide的同步更新。

使用场景

在下面的示例是与后代组件双向同步状态@Provide和@Consume场景。当分别点击CompA和CompD组件内Button时,reviewVotes 的更改会双向同步在CompA和CompD中。

@Component
struct CompD {
  // @Consume装饰的变量通过相同的属性名绑定其祖先组件CompA内的@Provide装饰的变量
  @Consume reviewVotes: number;

  build() {
    Column() {
      Text(`reviewVotes(${this.reviewVotes})`)
      Button(`reviewVotes(${this.reviewVotes}), give +1`)
        .onClick(() => this.reviewVotes += 1)
    }
    .width('50%')
  }
}

@Component
struct CompC {
  build() {
    Row({ space: 5 }) {
      CompD()
      CompD()
    }
  }
}

@Component
struct CompB {
  build() {
    CompC()
  }
}

@Entry
@Component
struct CompA {
  // @Provide装饰的变量reviewVotes由入口组件CompA提供其后代组件
  @Provide reviewVotes: number = 0;

  build() {
    Column() {
      Button(`reviewVotes(${this.reviewVotes}), give +1`)
        .onClick(() => this.reviewVotes += 1)
      CompB()
    }
  }
}

Supongo que te gusta

Origin blog.csdn.net/weixin_47094733/article/details/132034371
Recomendado
Clasificación