GithubHelp home page GithubHelp logo

weex-native-directive's Introduction

可回收长列表(<recycle-list>

<recycle-list> 是一个新的列表容器,具有节点回收和复用的能力,可以大幅优化内存占用和渲染性能。

功能还未完成,请谨慎使用!

设计思路请参考 Design.md,具体的实现细节请参考 Implementation.md

基本用法

原有 <list><cell> 组件的功能不受影响,针对新功能提供了新的 <recycle-list><cell-slot> 组件。如果想利用列表回收和复用的特性,使用新组件即可。

该功能部分依赖与编译工具,请确保 weex-loader 的版本升级到最新。

<recycle-list>

<recycle-list> 是一个新的列表容器,只能使用 <cell-slot> 作为其直接子节点,使用其他节点无效。

for 属性

<recycle-list> 添加 for 属性即可描述如何循环展开列表的数据,语法和 Vue 的 v-for 指令类似,但是它循环的是自己内部的子节点,并不是当前节点。

for 属性支持如下两种写法:

  • alias in expression
  • (alias, index) in expression

switch 属性

<recycle-list> 添加 switch 属性可以用来指定数据中用于区分子模板类型的字段名,语义和编程语言里的 switch 一致,配合 <cell-slot> 中的 casedefault 属性一起使用。

如果省略了 switch 属性,则只会将第一个 <cell-slot> 视为模板,多余的模板将会被忽略。

<cell-slot>

<cell-slot> 代表的是列表每一项的模板,它只用来描述模板的结构,并不对应实际的节点。<cell-slot> 的个数只表示模板的种类数,真实列表项的个数是由数据决定的。

case 属性

声明了当前模板的类型,只有和数据中的类型与当前类型匹配时才会渲染,语义和编程语言里的 case 一致。

所有模板中最多只会匹配到一项,按照模板的顺序从上到下匹配,一旦匹配成功就不在继续匹配下一个。

default 属性

表示当前模板为默认模板类型,不需要指定值。如果数据项没有匹配到任何 case 类型,则渲染带有 default 模板。如果存在多个 default,则只会使用第一个默认模板。

key 属性

可选属性,用于指定列表数据中可以作为唯一标识的键值,可以优化渲染性能。

属性的省略

  • 如果没写 switch,无论有没有写 casedefault,都只使用第一个模板。
  • 在写了 switch 的情况下,casedefault 必须写一个,否则该模板将会被忽略。

可复用的组件

<recycle-list> 中使用的子组件也将被视为模板,在开发组件时给 <template> 标签添加 recyclable 属性,才可以用在 <recycle-list> 中。

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

添加了 recyclable 属性并不会影响组件本身的功能,它仍然可以用其他在正常的组件里。

实例

在上层语法中的使用方式如下:

<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>

如果有如下数据:

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

则会生成如下等价节点:

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

如果将模板合并成一个,也可以省略 switchcase,将例子进一步简化:

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

使用子组件

<recycle-list> 中使用了组件 <banner>

<recycle-list for="(item, i) in labels">
  <cell-slot>
    <banner></banner>
  </cell-slot>
</recycle-list>

<banner> 组件的定义如下:

<template recyclable>
  <text class="title">BANNER</text>
</template>

更多细节可以参考:完整代码

注意事项

属性和文本的绑定

绑定属性或者文本时,仅支持表达式,不支持函数调用,也不支持使用 filter,可以参考 Implementation.md#支持的表达式

例如,下列写法不可用:

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

针对这种场景,推荐使用 computed 属性来实现。

因为模板的取值是由客户端实现的,而函数的定义在前端(filter 可以认为是在模板里调用函数的语法糖),如果每次取值都走一次通信的话,会大幅降低渲染性能。

<slot> 不可用

<cell-slot> 的功能和 <slot> 有部分重叠,而且更为激进,在概念上有冲突,存在很多边界情况无法完全支持。不要在 <cell-slot> 及其子组件里使用 <slot>

v-once 不会优化渲染性能

和前端框架中的理解不同,客户端里要实现复用的逻辑,会标记模板节点的状态,添加了 v-once 能保证节点只渲染一次,但是并不一定能优化渲染性能,反而可能会拖慢客户端复用节点时的比对效率。

样式功能的限制

计划支持

目前版本里还不支持绑定样式类名(v-bind:class),原因和进展可以参考 #14

双向绑定

计划支持

v-model 还未调通,暂时不要使用。

子组件的限制

没有 Virtual DOM!

使用在 <recycle-list> 中的组件没有 Virtual DOM!与 Virtual DOM 相关的功能也不支持。在开发过程中尽量只处理数据,不要操作生成后的节点。

下列这些属性都不再有意义,请不要使用:

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

vm.$refs 里的值可能是数组、子组件的实例、DOM 元素,在前端里比较常用,如果不支持对 Weex 里的 dom 模块animation 模块的功能也有影响。目前正在讨论技术方案,部分接口可能会重新设计,或者是在 vm 上透出专为 <recycle-list> 设计的接口。

组件的属性

目前子组件的属性不支持函数。(正在讨论实现方案)

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

因为子组件的属性值需要在前端和客户端之间传递,所以仅支持可序列化的值。item.xxx 的类型可以是对象、数组、字符串、数字、布尔值等,不支持函数。

生命周期的行为差异

由于列表的渲染存在回收机制,节点渲染与否也与用户的滚动行为有关,组件的生命周期行为会有一些不一致。

可回收长列表不会立即渲染所有节点,只有即将滚动到可视区域(以及可滚动的安全区域)内时才开始渲染,组件生命周期的语义没变,但是会延迟触发。

假设有 100 条数据,一条数据了对应一个组件。渲染首屏时只能展示 8 条数据的节点,那就只有前 8 个组件被创建了,也只有前 8 个组件的生命周期被触发。

  • 组件的 beforeCreatecreated 也只有在组件即将创建创建完成时才会触发。
  • 同理,组件的 beforeMountmounted 也只有页面真正渲染到了该组件,在即将挂载已经挂载时才会触发。
  • 修改处于屏幕外的组件的数据,不一定会触发 beforeUpdateupdated 生命周期。(行为未定义,需要进一步排查)

组件的自定义事件

计划支持

vm.$on, vm.$once, vm.$emit, vm.$off 等功能还未完全调通,接口可用,但是行为可能有些差异(参数丢失),暂时不要使用。

更多例子

Web 版本的 <recycle-list> 还正在开发,online playground 上暂时无法预览效果。支持 <recycle-list> 的 playground app 还未发布,基于最新源码构建的 playground 才可以扫码查看效果。

模板语法

使用子组件

复杂用法

下列功能暂未验证,欢迎贡献例子。

  • 深层子组件 (TODO)
  • 重复多个子组件 (TODO)
  • 子组件同时用在 recycle-list 和普通 list 中 (TODO)
  • 更新模板结构 (TODO)
  • 多处绑定 listData (TODO)
  • 动态 switch/case (TODO)
  • 动态修改数据的 type (TODO)
  • header/loading/refresh (TODO)
  • 使用各种类型的子组件 (TODO)
  • 子组件的自定义事件 (TODO)
  • 父子组件通信过程 (TODO)
  • 在内部嵌套 list/scroller (TODO)
  • 使用 <component> (TODO)
  • 使用 <template> (TODO)
  • 使用 <slot> (TODO)
  • 在子组件中使用 <recycle-list> (TODO)

weex-native-directive's People

Contributors

acton393 avatar cxfeng1 avatar hanks10100 avatar imyzf avatar yyx990803 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

weex-native-directive's Issues

Ios 上数据源为 null 崩溃

image

Ios 上数据源为 null 崩溃,安卓没问题。

1:facilityClass 初始值为null,会崩溃,
2: facilityClass 初始值为空数组 [ ],后续赋值为null,不会崩溃

To support scrollToElement

when will the recycle-list support the Dom API scroolToElement, or providing another API to support scroll to specific height is also OK.

所有例子WeexPlayground都不能运行

运行时报 TypeError: Cannot read property 'label' of undefined
at Ot.render (0658e5ec6c1d83e8c19adde7e0b2a0fa.bundle.vue.js:714)
at Ot.e._render (vue.min.js:6)
at Ot.r (vue.min.js:6)
at Uo.get (vue.min.js:6)
at new Uo (vue.min.js:6)
at Se (vue.min.js:6)
at Ot.$mount (vue.min.js:6)
at Ot.$mount (vue.min.js:6)
at Ot.e._init (vue.min.js:6)
at new Ot (vue.min.js:6)

Use more readable attributes on `<recycle-list>`

Syntax

Change the compiler to support the new syntax.

  • Use for instead of the list-data, alias and index.
  • Use switch instead of the template-key.
  • Use case instead of the template-type.

Examples

Before:

<recycle-list :list-data="longList" template-key="cellType" alias="item" index="i">
  <cell-slot template-type="A"> ... </cell-slot>
  <cell-slot template-type="B"> ... </cell-slot>
</recycle-list>

After:

<recycle-list for="(item, i) in longList" switch="cellType">
  <cell-slot case="A"> ... </cell-slot>
  <cell-slot case="B"> ... </cell-slot>
</recycle-list>

The data of longList still should be binding with the <recycle-list>.

Support to use filters

Using callbacks to support filters in the template.

<text>{{ item.title | i18n }}</text>

Should be compiled to:

{
  type: 'text',
  attrs: {
    value: {
      '@binding': 'item.title'
      '@filters': [i18n]
   }
}

The i18n is a function, and it'll be converted into a callback id when sending to native. Native render engines should get the value of item.title and pass it to the callbacks which are defined in @filters.

Simplified syntax?

Currently it seems switch and case attributes (previously template-key and template-type) are always required, even when there is only one <cell-slot>.

I think when there is only one <cell-slot>, it should be used by default, so switch and case can be omitted:

<recycle-list for="item in longList">
  <cell-slot>
    <text>{{ item.foo }}</text>
  </cell-slot>
</recycle-list>

Manage style sheets in native render engines

<div :class="box.classList"></div>

Will be compiled to:

{
  type: 'div',
  attrs: {
    class: {
      '@binding': 'box.classList'
    }
  }
}

Currently, class names and the stylesheet are managed in front-end frameworks and weex-js-runtime. However, in this case, the result of box.classList couldn't be got in front-end frameworks.

The stylesheet should be managed in native render engines.

Parse object literal in binding attributes or styles

Source:

<div :style="{ fontSize: 15, color: item.color }"></div>

Should be compiled to:

{
  style: {
    fontSize: 15,
    color: { '@binding':  'item.color' }
  }
}

Current is:

{
  style: {
    '@binding':  '{ fontSize: 15, color: item.color }'
  }
}

提示:Unknown custom element: <recycle-list>,怎么解决呢?

Unknown custom element: < recycle-list > - did you register the component correctly? For recursive components, make sure to provide the "name" option.


我用weex-toolkit 建了一个新页面,然后在里面使用了 recycle-list这个组件,编译时顺利通过,运行时会提示以上的错误。

运行: weex --version 查到的版本信息如下:
v1.1.0-beta.6

  • weexpack : v0.4.7-beta.21
  • weex-builder : v0.2.13-beta.4
  • weex-previewer : v1.3.13-beta.12
  • toolkit-repair : v0.0.5

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.