RAOE / Flat

A lightweight MVVM framework base on TypeScript.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

fre logo

Flat

A lightweight MVVM framework base on TypeScript.

Flat

A lightweight MVVM framework base on TypeScript.

dev...

Render

在执行 render 的时候,会将所有的数组抽成扁平,flat 会认为,children 就只有 Text 节点和 _Elememt 节点,相对来说,抽成扁平,在性能上也会得到提升。

为了能精确定位到更新的元素,在 Component 的原型上附加了类型为 symbol 的 _key,用来唯一标识一个组件

不必关心节点的 key, flat 在初次解析的时候,附加了 component 的 key,key 用了 Symbol 类型,为了保证对比的是同一个 key,于是把 key 附在了组件上。

为直接定位更改的元素,flat 采用了ES6Proxy/ Reflect,因为已经知道了渲染的元素的位置,变更的组件的子组件并不会重新调用 render,大幅度提高了渲染的性能

About Decorator

TypeScript 的 Decorator 不能支持改变类型,这样只有使用类 React 的继承 FlatComponent 来完成对类型的约束,使 Decorator 不能专注的完成一件事情,在用户看来,除了使用 Decorator 还要做额外的工作是在太麻烦了,于是将原来的 FlatComponent 装饰器推掉。

State && Props

值得一提的是,flat 为避免重复 渲染 做了处理, 在 flat 里你不必担心不必要的 渲染

State

flat 里的state是默认就是 immutable 的状态,在 component 中会维护一个对使用者透明的 $state 对象,它由 Proxy 来做支撑,当每次更改 state 的时候都会触发重新创建一个 $state 对象,在必要的时候,直接对比 $state 对象就能知道是否有 state 进行了变更,防止重复渲染,本来是想拿掉 shouldComponentUpdate这个钩子,但是考虑到一些特殊的场景会在 render 执行一些必要的逻辑,所以还是会有对shouldComponentUpdate有支持。

Props

为了让 props 能够避免重复渲染,flat会在判断是否需要 render的时候做一次比较,比较元素上的 Attributes,但是只会进行第一层的比较,遇到复合数据类型,为了不为使用复合数据类型而牺牲渲染效率,flat 只会简单的比较它们的引用,如果不相同,则执行渲染 。

但是你大可以不必担心这类的问题,在 React 中提出了使用 immutable 来创建一个新的对象,来防止重复渲染,方便比较,但是相反,在 falt 中,你只需要直接更改它即可,其他繁琐的事情都由 falt 帮你做了。

class App extends FlatComponent {
  @State()
  person = {
    name: 'zhangsan',
    age: 20
  };

  changeAge() {
    this.person.age++;
  }

  render() {
    console.info('app render');

    return (
      <div id="foo">
        <Greeter person={this.person} />
        <button onclick={() => this.changeAge()}>change age</button>
      </div>
    );
  }
}

每当执行到 changeAge 的时候,falt 会在背后帮你产生一个新对象,以减少重复渲染的问题。

Children

至于 children 它作为一种特殊的 props 也会执行 props 的相关比较逻辑。

flat 里采用一个 children 的规范,如果你传入一个以上的 childrenflat 只会取第一个 children 来注入。

Right

<Foo>{this.bar}</Foo>

Foo

<Foo>
  {this.name}
  {this.age} {/* age 不会被注入到 Foo */}
</Foo>

String Template Compiler

对于 string template 变量的求值,默认认定为 Text 节点,在解析模版完成后,再进行值的插入。 这里有一个例外,当变量为数组时,会在解析模版之前就对其进行求值,然后再把值拼接到模版,flat 会认为,数组返回的也是一个迭代模版。

import Flat, { FlatComponent, Prop, _Element, Ele, Children } from '../../dist';

class Greeter extends FlatComponent {
  @Children()
  names!: string[];

  render(): JSX.Element {
    let greeters = names.map(name => <p>hello {name}</p>);

    return <div>{greeters}</div>;
  }
}

let names = ['A', 'B', 'C'];
let input = (
  <div id="foo">
    <Greeter>{names}</Greeter>
  </div>
);

new Ele(input).bindDOM(document.querySelector('#root'));

关于 _Key

flat 里的 keyreact 或者 vuekey 不同,flatkey 是用 Symbol 来表示的,于是比较的时候仅仅是比较的是引用,如果两个 key 相同,那么则认为它是完全相同的节点。 _key 被挂载到 FlatComponent 下,在创建组件的时候会被继承下来。

flat 中,所有以 _ 或者是 $ 开头的变量,都是不被暴露出的,因此,你不能在 flat 中被访问到。

TODO:

  • 对于自定义组件的求值策略
  • 组件钩子的调用时机以及确定钩子函数
  • @FlatComponent 实现
  • Props 实现,以及 @Prop 的实现
  • virtual DOM 的 Diff 算法

About

A lightweight MVVM framework base on TypeScript.

License:MIT License


Languages

Language:TypeScript 98.8%Language:HTML 1.0%Language:JavaScript 0.2%