Svelte v2 已通过时了!

带你蜻蜓点水,细看新版变化。

注意:原文发表于2018-04-18,随着框架不断演进,部份内容可能已不适用。javascript

大约是一年以前,咱们首次在 Svelte 的 issue 跟踪器上讨论过 v2 版本,如今是时候进行一些重大变动了。css

咱们的座右铭是“按部就班,破旧立新”。html

……好吧,我错了,看来我要改过自新了。java

这篇博文阐述了新版本的变化,都变了哪些地方、为何要变以及应对的策略。git

长话短说,先看梗概

咱们会不厌其详地描述每个变动细项,若是你仍是遇到了困难,请在咱们气氛友好的 Discord 聊天室 中寻求帮助。github

  • 从 npm 安装 Svelte v2
  • svelte-upgrade 升级你的模板
  • 删除对 component.observe 方法的调用,或者从 svelte-extras 中添加 observe 方法
  • 将对 component.get('foo') 的调用重写为 component.get().foo
  • 从你的自定义事件处理程序中返回 destroy,而不是 teardown
  • 确保没有将值是数字类型的字符串做为 props 传递给组件

最新的模板语法

最明显的变化是:咱们对模板语法作了一些改进。npm

咱们常常听到的反馈是,“哎呀,又是Mustache”或者“哎呀,这不Handlebars嘛”。canvas

在 Web 开发的较早时期,许多开发者使用基于字符串的模板系统,但他们彷佛对模板深痛恶绝。浏览器

因为 Svelte 也采用了这种 {{表达式}} 的语法,所以许多人觉得咱们也在某种程度上有那些相同的局限性,好比奇怪的做用域规则,或者没法随意使用 JavaScript 表达式。bash

提示:若是你须要显示一个 '{' 字符,那么它能够简单地用 '{' 来表示。

除此之外,JSX 证实了使用双大括号其实大可没必要。

因此咱们使得模板更加的 …… 怎么说呢,

Svelte 采用单个大括号括起表达式。

应该说结果彷佛看起来更轻松了,打字时也更愉快了:

<h1>Hello {name}!</h1>

固然也还有一些其余的更新的。

好消息是你不须要手动去一个一个地改,只须要在代码库上运行 svelte-upgrade 就行:

npx svelte-upgrade v2 src

这假定 src 目录下的任何 .html 文件都是一个小组件。

源目录和目标目录都可以任君自由指定,例如,你可使用 npx svelte-upgrade v2 routes 更新 Sapper 应用。

要查看完整的变动列表,请移尊步到 svelte-upgrade 的 README 文档

计算属性

人们常常对 Svelte 感到困惑的一件事情是计算属性的工做方式。

回顾一下,若是你有这么一个组件……

export  default  {
  computed:  {
    d: (a, b, c)  => a = b + c
  }
};

……Svelte 首先检查函数的参数,以便计算出 d 所依赖的参数是什么,而后它会自动编写好代码,在这些值发生改变时,经过将新值注入到函数中,从而更新 d

很酷吧!

由于它容许你从组件的输入中获取复杂的值,而没必要担忧什么时候须要从新计算它们,但这用法也怪里怪气的。

JavaScript 语法不支持这么写。

在 v2,咱们用解构来代替:

export  default  { 
  computed:  {  
    d: ({ a, b, c })  => a = b + c 
  }  
};

Svelte 编译器仍然能够知道 d 依赖哪一个值,但再也不注入值,而是将整个组件状态对象丢给每一个计算的属性中。

友情提示:你一样不须要手动进行此更改,只须要对组件运行 svelte-upgrade,如上所示。

IE11,很差意思,好自为之

Svelte v1 生成的是 ES5 的代码,这样你就不会被迫使用转译器。

但如今都 2018 年了,几乎全部浏览器都支持现代 JavaScript。若是能抛弃 ES5 的束缚,咱们就能够生成更精简的代码。

不过你若是还须要友好地支持 IE11,你仍是能够用 Babel 或者 Bublé 之类的转译器的。

新的生命周期 Hook

除了 oncreateondestroy 外,Svelte v2 还添加了两个生命周期函数来响应状态更改:

export default {  
  onstate({ changed, current, previous }) {  
    // 在 oncreate 以前以及状态变动时触发  
  },  
  onupdate({ changed, current, previous }) {  
    // 在 oncreate 以后触发, 而且状态变动后更新了 DOM 时触发  
  }  
};

你还能够经过编写代码的方式监听这些事件:

component.on('state',  ({ changed, current, previous })  => {  
  // ...  
});

component.observe

使用新的生命周期函数,咱们再也不须要 component.observe(...) 方法:

// 以前  
export default {  
  oncreate() {  
    this.observe('foo', foo => { 
      console.log(`foo is now ${foo}`);  
    });  
  }  
};  

// 以后
export default {
  onstate({ changed, current }) {
    if (changed.foo) {
      console.log(`foo is now ${current.foo}`);  
    }  
  }  
};

这能够减小 Svelte 生成的代码量,并为你提供了更大的灵活性。

例如,如今能够十分容易在几个属性中的任何一个发生变动时响应这些动做,比方说在不释放观察者的状况下进行重绘 canvas。

不过若是你实在喜欢使用 component.observe(...),你能够经过 svelte-extras 来支持这玩意。

import { observe } from 'svelte-extras';

export default {
  methods: { observe } 
};

component.get

这个方法再也不接收可选的 key 参数 —— 相反,它总数返回整个 state 对象:

// 以前  
const foo =  this.get('foo');
const bar =  this.get('bar');  

// 以后
const  { foo, bar }  =  this.get();

初时,这种改变可能看起来很烦人,但这是正确的方向:

除了其余特殊状况外,未来咱们会更充分地探索这个方面,它可能会在类型系统中发挥更好的做用。

event_handler.destroy

若是你的应用程序具备自定义的事件处理器,那么它必须返回一个带有 destroy 方法,而不是 teardown 方法。这样事件处理器就和组件的 API 对齐了。

再也不严格要求类型

之前,传递给组件的数字类型的值会被视为纯数字:

<Counter  start='1'  />

这可能会致使一些意外行为。如今已经被更改了。

若是你须要传递数字的字面量,能够直接用表达式:

<Counter  start={1}  />

编译器方面的变动

在大多数状况下,你是永远不须要直接和编译器打交道的,所以编译器方面你其实不须要什么对策的。

无论怎么说,值得注意的是:编译器的 API 也是有变动的。

如今编译器将返回 jscssaststats,而不是有一大堆属性的对象:

const { js, css, ast, stats }  = svelte.compile(source, options);

jscss 都是 {code, map} 对象,其中 code 是代码字符串,map 表明 sourcemap。

ast 是组件的抽象语法树,而且 stats 对象包含有关组件的元数据以及编译信息。

之前是有一个 svelte.validate 方法来检查你的组件是否有效的。

不过它已经被删掉了,若是你只需检查组件,而不实际对其进行编译的话,那么仅仅传递一个 generate: false 选项便可。

个人应用还有问题要寻求帮助

但愿以上的内容已经覆盖了全部可能的问题,而且更新对你来讲,应该比较轻松从容的。

若是你发现错误或者本文未尽事项,请进入 Discord 聊天室 里头转转看,或者在 issue 跟踪器 反馈给咱们。

< The End >

  • 窗明几净,静候时日变迁 -
相关文章
相关标签/搜索