<recycle-list>

Summary

<recycle-list> is a new vertical or horizontal list container with the ability to recycle and reuse, which can greatly optimize memory usage and rendering performance.

  • Please refer to Design.md for design ideas. For details, please refer to Implementation.md
  • This feature is partially dependent on the build tool, please ensure that the version of weex-loader is up to date (v0.7.2+)
  • Use the latest version of the playground app (SDK version 0.18.0+) to scan the code for native effects, or use dotwe.org to view the web preview directly.

Child Component

<recycle-list> can only use <cell-slot> as its immediate child node, and other nodes are invalid.

<cell-slot>

<cell-slot> Represents a template for each item in the list, which is only used to describe the structure of the template, and does not correspond to the actual node. The number of <cell-slot> only indicates the number of types of templates, and the number of real list items is determined by data.

  • warning attribute omission
    • If you don't write a switch, use the first template with or without case or default.
    • In the case of a switch, case and default must be written, otherwise the template will be ignored

Attributes

  • for In <recycle-list>, add the for attribute to describe how to loop through the list‘s data. The syntax is similar to Vue’s v-for directive, but it loops through its own internal nodes, not the current node. Written:
    • alias in expression
    • (alias, index) in expression
  • switch Adding a switch attribute to the <recycle-list> can be used to specify the field name for the region's molecular template type in the data. The semantics are consistent with the switch in the programming language, along with the case and default attributes in <cell-slot>
  • If the switch attribute is omitted, only the first <cell-slot> will be treated as a template and the extra template will be ignored.
<recycle-list for="(item, i) in longList" switch="type">
  <cell-slot case="A">
    <text>- A {{i}} -</text>
  </cell-slot>
  <cell-slot case="B">
    <text>- B {{i}} -</text>
  </cell-slot>
</recycle-list>
  • scrollDirection
    Value vertical or horizontal

Recyclable component

Subcomponents used in <recycle-list> will also be treated as templates, and the recyclable attribute will be added to the <template> tag when developing the component before it can be used in <recycle-list>.

<template recyclable>
  <div>
    <text>...</text>
  </div>
</template>
<script>
  // ...
</script>

Adding the recyclable property does not affect the functionality of the component itself, it can still be used in other normal components.

Precautions

Binding of attributes and text

When binding properties or text, only expressions are supported, function calls are not supported, and filters are not supported. You can refer to the expressions supported byImplementation.md#支持的表达式

For example, the following notation is not available:

<div :prop="capitalize(card.title)">
  <text>{{ card.title | capitalize }}</text>
</div>

For this scenario, it is recommended to use the computed property.

Because the value of the template is implemented by the client, and the definition of the function is at the front end (filter can be considered as the syntactic sugar of the function in the template), if you take the communication once every time, the rendering performance will be greatly reduced.

<slot> unavailable

The <cell-slot> function and <slot> are partially overlapping, and are more radical, conceptually conflicting, and there are many boundary conditions that cannot be fully supported. Do not use <slot> in <cell-slot> and its subcomponents.

v-once does not optimize rendering performance

Different from the understanding in the front-end framework, the logic to implement multiplexing in the client will mark the state of the template node. Adding v-once can ensure that the node is only rendered once, but it does not necessarily optimize the rendering performance, but may drag Comparison efficiency when slow client multiplexing nodes.

Style feature restrictions

Plan support. The binding style class name (v-bind:class) is not supported in the current version. For reasons and progress, please refer to #14.

Two-way binding

Plan support. The v-model has not been tuned yet. Please do not use it for the time being.

Subcomponent restrictions

  • No Virtual DOM! The components used in <recycle-list> do not have Virtual DOM! Features related to Virtual DOM are also not supported. Try to process only the data during the development process, and do not operate the generated nodes.

    The following properties are no longer meaningful, please do not use:

    • vm.$el
    • vm.$refs.xxx
    • vm.$vnode
    • vm.#slots
    • vm.#scopedSlots

    The values in vm.$refs may be arrays, instances of subcomponents, DOM elements, which are commonly used in front ends. If not supported, the functionality of the dom module and animation module in Weex also has an effect.

    The technical solution is currently being discussed, some of the interfaces may be redesigned, or an interface designed for <recycle-list> will be available on vm.

  • Component properties The properties of the current subcomponent do not support functions. (Discussing the implementation plan)

    <sub-component :prop="item.xxx" />
    

    Because the subcomponent's attribute values need to be passed between the front end and the client, only serializable values are supported. The type of item.xxx can be an object, an array, a string, a number, a boolean, etc., and functions are not supported.

  • Life cycle behavioral differences

    Since the rendering of the list has a recycling mechanism, whether the node is rendered or not is also related to the user's scrolling behavior, and the lifecycle behavior of the component may be inconsistent.

    Recyclable long lists do not render all nodes immediately, only when they are about to scroll into the visible area (and scrollable safe area), the semantics of the component lifecycle does not change, but the trigger is delayed.

    Suppose there are 100 pieces of data, one piece of data corresponds to one component. When the first screen is rendered, only the nodes of 8 data can be displayed. Only the first 8 components are created, and only the lifecycle of the first 8 components is triggered.

    • The component's beforeCreate and created will only fire when the component is about to be created and created.
    • Similarly, the component's beforeMount and mounted only the page is actually rendered to the component, and will only fire when it is about to be mounted and already mounted.
  • Component custom event Plan support. Features such as vm.$on, vm.$once, vm.$emit, vm.$off are not fully tuned, the interface is available, but the behavior may be slightly different (parameters are missing), do not use it for the time being.

Demo

<recycle-list for="(item, i) in longList" switch="type">
  <cell-slot case="A">
    <text>- A {{i}} -</text>
  </cell-slot>
  <cell-slot case="B">
    <text>- B {{i}} -</text>
  </cell-slot>
</recycle-list>

If you have the following data:

const longList = [
  { type: 'A' },
  { type: 'B' },
  { type: 'B' },
  { type: 'A' },
  { type: 'B' }
]

The following equivalent nodes are generated:

<text>- A 0 -</text>
<text>- B 1 -</text>
<text>- B 2 -</text>
<text>- A 3 -</text>
<text>- B 4 -</text>

If you merge the templates into one, you can also omit the switch and case to further simplify the example:

<recycle-list for="(item, i) in longList">
  <cell-slot>
    <text>- {{item.type}} {{i}} -</text>
  </cell-slot>
</recycle-list>

More demos:

Template syntax

Using subcomponents