Skip to content

1.0.0 版本升级改动

musicode edited this page Apr 25, 2019 · 22 revisions

大致说下 1.0.0 版本的升级思路

  1. 采用 typescript 重写所有代码
  2. 底层编译重新设计,性能大幅提升
  3. 更加完备的错误提示
  4. 更加稳定的 API
  5. 对外提供以下四种版本,功能从多到少排序:

yox.js:拥有完整功能的源码版本,建议使用此版本进行开发

yox.min.js:拥有完整功能,但不包含错误提示的压缩版本

yox.runtime.js:不包含编译器的压缩版本,文件体积大为减少,且性能更佳,建议使用此版本进行上线

可通过 Yox.compile('你的模板源码', true) 获取编译后的字符串

yox.pure.js:不包含任何 DOM 的压缩版本,是纯数据操作版本

先列举几个简单的改动:

  1. 删除 Yox.is.primitive 方法
  2. Yox.Event 构造函数签名改为 (type, originalEvent)
  3. Yox.string.camelCase 改为 Yox.string.camelize
  4. 表达式模板 语法增强了校验,具体可查看运行时的报错或警告信息

下面说几个比较大的改动:

hasSlot 过滤器

hasSlot(name) 过滤器已不建议使用,更新如下:

before

<div>
  {{#if hasSlot('icon')}}
    <slot name="icon" />
  {{else}}
    默认 icon
  {{/if}}
</div>

after

<div>
  <slot name="icon">
    // 默认 icon
  </slot>
</div>

如果没有人能说出非要 hasSlot 不可的理由,正式版会删掉 hasSlot

数据监听

立即执行监听函数,由从前的 sync 改为了 immediate,虽然这个单词不好记,但没办法,它就是更规范一些。

before

{
  watchers: {
    title: {
      sync: true,
      watcher: function () {

      }
    }
  }
}

after

{
  watchers: {
    title: {
      immediate: true,
      watcher: function () {

      }
    }
  }
}

如果你用的是 yox.watch('keypath', function, true),则无需任何改动。

自定义指令

新版重新设计了自定义指令,结构如下:

Yox.directive({
  name: {
    bind: function (node, directive, vnode) {

      // 当指令写在组件上,isComponent 为 true
      // 比如 <Dog o-x="x" />
      if (vnode.isComponent) {
        // node 是一个 Yox 实例
      }
      else {
        // node 是一个 DOM 元素
      }

      // 如果指令需要销毁,比如绑定了事件
      // 你要在 vnode.data[directive.key] 属性上绑定销毁需要用到的数据

      vnode.data[directive.key] = function () {
        // 销毁逻辑
      }

    },
    unbind: function (node, directive, vnode) {
      // 销毁它
      vnode.data[directive.key]()
    }
  }
})

directive 经过精心设计,你大概会用到以下属性

directive.key

在一个元素(或组件)上,指令的唯一性由两部分保证,一个是指令的命名空间,比如是内置的 event 指令还是自定义指令,一个是指令的实际名称,比如 click,当两者相加时,我们可以认为它是唯一的,比如你不会在一个元素上写两个 on-click,这是没有意义的。

  • directive.ns: 命名空间,比如 event
  • directive.name: 指令名称,比如 click
  • directive.key:vnode 级别的 unique key,比如 event.click

directive.value

指令值的字面量,如果是基本类型,框架会自动转型。举例如下:

  • o-x="1": value 为 1
  • o-x="true": value 为 0
  • o-x="'1'": value 为 "1"
  • o-x="name": value 为空 "name",但此时你想做的可能是读取 data 中的 name,这要用到下面的 getter

directive.getter

指令的取值函数,如果指令表达式不是字面量,那么框架会把表达式编译成 getter 函数,取值非常简单,执行它即可。

directive.handler

如果指令表达式是调用函数的形式,比如常见的 on-click="submit()",框架会把表达式编译成 handler 函数,你需要做的就是在合适的时机调用它。

Lazy 指令

本质上,lazy 不是指令,而是指令的辅助。

lazy 有两种值,一种是 true,一般用于 model 指令,表示输入框在失焦时触发变化。一种是大于 0 的数字,表示延时多久,这个一般取决于指令的实现方。

Yox.directive({
  name: {
    bind: function (node, directive, vnode) {
      // vnode.lazy 是一个对象,拥有当前节点上的所有 lazy 配置
    }
  }
})

比如,我们可以为每个事件分别设置延时。

<input
  type="text"

  model="value"
  on-click="click()"
  on-mousedown="mousedown()"
  on-mouseup="mouseup()"

  lazy-model="100"
  lazy-click="200"
  lazy-mousedown="300"
  lazy-mouseup

  lazy="999"
/>

button 节点的 lazy 格式如下:

{
  model: 100,
  click: 200,
  mousedown: 300,
  mouseup: true,
  '': 999
}
Clone this wiki locally