前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[译]使用 Riot,ES6 和 Webpack 构建应用

[译]使用 Riot,ES6 和 Webpack 构建应用

作者头像
逆葵
发布2019-04-25 14:30:28
9200
发布2019-04-25 14:30:28
举报
文章被收录于专栏:FECodingFECoding

在读完 Muut 上 Frameworkless JavaScript 这篇博文后,我遇上了 Riot,请一定先阅读该博文!Muut 的程序员拿出实际行动编写了 Riot,一个 类似React 的用来构建响应式UI组件的微型库。

阅读Riot的文档时,令我感触最深的是 Riot 竟如此容易理解——相比 React 来说,在 Riot 里需要学习的术语和概念极少(说实话,和 Polymer 和 Angular 等比起来,Riot 也是十分简单易懂的)。

为了有助于学习 Riot,我把自己用 React 编写的 flux-backbone-todo 搬运到了用 Riot 编写的 Riot Todo app 上。这篇博文就是我记录这次重构经历的笔记的合集。

如果觉得文章太长,这里是精简版:

  1. Riot 确实践行了它最小化的座右铭。Todo 应用的 Riot 版本(未压缩)只有很小的 32 KB。作为对比,React 版本则达到了 964 KB 之多(即使减去在 Riot 版本中未使用到的 Backbone 和 jQuery,React 版本仍然有 600 KB)。不管你怎么看,这都是一个巨大的差异。
  2. Riot 有那种很少见的“刚刚好”的感觉,使用起来非常愉悦。
  3. Riot 是一个相对较新的方案,因此我没有找到其在大一些的项目中的性能方面的统计数据。在大型项目中 Riot 表现究竟怎样尚未有定论,我希望它能够做的很好。

如果你对 Riot 还不熟悉,可以先去浏览一下 Riot官网——开发文档是第一课。我将列出一些我所学到的但是阅读文档时不一定很明显易懂的内容,而不会去讨论 Riot 是如何工作的。

在 Riot 中使用 ES6

示例的应用采用 ES6 编写,我使用 6to5 转译器将其转换为 ES5 代码,使用 Webpack 将编译后的代码以及需要的库一起打包。这种方式使得联结 JavaScript 模块成为必要——当你理解最新的 ES6 中 importexport 表述的优势时(看这个示例),你就会知道使用 ES6 编写代码是非常棒的。

Webpack通过配置可以使用 6to5 loader 将 ES6 源码自动转换成 CommonJS 格式的 ES5 模块,再将其打包至一个单独的 bundle.js 文件。

为什么我不使用 Riot 的 .tag 文件

Riot 标签文件是指包含 HTML 标记以及 JavaScript UI 逻辑的 HTML 模板。如果你已经浏览过了上面提到的 Todo应用,你可能会疑惑标签文件在哪里——答案是我已经不再使用它们,并且更喜欢用 JavaScript 来替代之。去除 .tag 文件简化了我的编码、加工和工作流程。对我来说,标签文件的复杂性和局限性大于它任何可以感知到的优点。

这并不是对 Riot 的一种批判。对标签文件来说,灵活的地方在于它完全可选而非强制使用,在此记录我不使用它的原因。

当你审视编译后的 JavaScript 代码时,你会看到 Riot 标签文件其实是一层轻微的语法糖.

  • 它添加了额外的概念层——新的或者比较新的语法和语义需要学习。
  • 它添加了额外的编译步骤。
  • 标签文件编译器指定了你可以使用的语言和模板(CoffeeScript、ES6和Jade),这有悖于“使用你最喜欢的工具”的理念。
  • 标签构造主体的逻辑脱离上下文:
    • 这使得标签文件无法被编辑器/IDE 的代码检测以及其他的工具处理
    • 涉及 this 时,脱离上下文意味着代码不是合法的 JavaScript 并且在编辑器/IDE 中会报错
  • 目前没有对模块化(CommonJS,AMD)标签文件编译为普通 JavaScript 的支持。
  • 标签文件需要构建工具(比如 Webpack 和 Browserify)直接使用标签转换器来进行转换。
  • 类似 ES6 的构造方法很棒但它们不是合法的 JavaScript 并且很可能总是成为持续混乱(语法和语义上)的来源。你可以使用 ES6 的箭头函数以几乎相同的简洁程度来获得相同的语义(拥有词法作用域的 this),举例如下:
代码语言:javascript
复制
this.add = (e) => {
        	var input = e.target[0]
        	this.items.push(input.value)
        	input.value = ''
        }; 

这里有一个使用 ES6 模板字符串和箭头函数的 ES6 形式的 JavaScript 标签文件的例子

ES6 模板字符串提高了标签 HTML 模板的可读性。相似的,如果你使用的是 CoffeeScript,那么你可以使用 CoffeeScript 块字符串。JSX 是另一种可选项——React 的 JSX 转换器可以经过修改然后生成字符串文本,这样你就可以获得现有的 JSX 工具的支持。

Riot和React的基本区别

最重要的区别在于 UI 标记模板是如何声明的:

  • 在 React 中 UI 标记模板是在你的 JavaScript 源码中生成的(使用 JSX 语言的扩展)。
  • Riot 则反转了 React 的模型,将标记和逻辑都放在 HTML(标签)文件中。

这种反转的结果是 React 模板 DSL(领域特定语言)就是 JavaScript,而 Riot 依赖自定义的模板 DSL(采用自定义标签实现)。下面是两个简化的从一个 todo 事项的数组中生成一个列表的例子,第一个采用 React JavaScript编写,第二个是等价的 Riot 标签标记形式:

代码语言:javascript
复制
<ul>
  todos.map(todo =>
    <li><TodoItemComponent todo={todo} /></li>)
</ul>
代码语言:javascript
复制
<ul>
  <li each="{todo in todos}">
    <todo-item todo="{todo}">
  </li>
</ul>

第一个例子中使用了 JavaScript 的 map 函数来生成一个 <li> 元素的列表;第二个例子则使用了 Riot 自定义的 each 模板属性。

Steve Luscher 在这个视频的结尾解释了为何他认为 JavaScript 比自定义模板 DSL 更优秀——你不仅需要学习一门自定义的 DSL,而且还要拘泥于这套 DSL 提供的特性的束缚。对于像上面这样较小的普通用例来说,两种方式其实没太多选择余地,但是在编写更大的高度动态化的 UI 组件时,React 的 JavaScript 方式的威力和灵活性就明显更优越了。

小贴士

避免自关闭的XHTML风格的标签

不要用/>来关闭标签,因为它不总是立刻就能关闭标签。当以 HTML5 元素对待时,<foo /> 表示<foo>(然而在 XHTML 中<foo />表示<foo></foo>),换言之,HTML5 会忽略/字符。有关这个话题可以在 Stackoverflow 上查看更多讨论。还可以查看下面两处内容:

绑定标签事件处理器到 this 上

绑定标签事件处理器到 this 上,以确保这些处理器总是和标签文本一起清除(可选的方式是使用约定俗成的var self = this)。比如:

代码语言:javascript
复制
this.clear = function(e) {
  dispatcher.trigger(dispatcher.CLEAR_TODOS);
}.bind(this);

使用 ES6 中的词法作用域绑定的箭头函数也可以获得相同的效果:

代码语言:javascript
复制
this.clear = (e) => {
  dispatcher.trigger(dispatcher.CLEAR_TODOS);
};

关于循环项

使用each={item in items}结构将当前的循环项目传递给自定义的子标签。在下面的例子中,自定义的todo-item标签内的代码可以使用opts.todo来获取当前的 todo 项:

代码语言:javascript
复制
<ul>
 <li each="{todo in opts.store.todos}">
   <todo-item store="{parent.opts.store}" todo="{todo}">
 </li>
</ul>

命名空间事件名称

使用命名空间加冒号的约定来组织应用的事件名称,比如admin:editadmin:deleteadmin:new等。

可以在 CSS 文件中使用自定义标签

自定义标签最终会被渲染生成到 DOM 中,因此它们可以使用在 CSS 选择器和 DOM 审查中使用,这里是一个例子

调试

当用 Webpack 打包时你需要使用开发工具 source-map 配置选项来为你打包后的应用生成 source map 文件。这使得你可以在 ES6 的源码文件中进行调试。

当需要浏览和调试源码时,打开浏览器的 Sources 窗口然后定位到webpack:///.文件夹:

  • 在 Firefox 中:打开 Debugger(Ctrl+Shift+S)。
  • 在 Google Chrome 中:打开 Console(Ctrl+Shift+J)然后点击 Sources 标签来查看源码面板。

我不是很喜欢调试程序和设置断点——大多数情况下我仅仅会有策略地在代码中放置暂时性的console.log()

未来蓝图

Riot(类似 React)是一个 UI 库而不是一个框架。这非常棒(相对于大包大揽的框架来说,我更喜欢小而精的库的集合),但是对于具有一定复杂度的应用来说就需要条理清晰的高级的结构(一个体系结构)来提高可伸缩性、可发展性和可维护性。Flux 为类似React的应用增加了体系结构的选择。我喜欢 Flux,因为它很容易理解并且它能给人一种很直观的感觉(并非出于任何理论上的信仰)。Riot Todo app 使用了名为 RiotControl 的 Flux 风格的 dispatcher(经过轻微修改)来实现 Flux 体系结构。

{% blockquote srackham http://blog.srackham.com/posts/riot-es6-webpack-apps/ Building Apps with Riot, ES6 and Webpack %} 原文出处: {% endblockquote %}

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 在 Riot 中使用 ES6
  • 为什么我不使用 Riot 的 .tag 文件
  • Riot和React的基本区别
  • 小贴士
    • 避免自关闭的XHTML风格的标签
      • 绑定标签事件处理器到 this 上
        • 关于循环项
          • 命名空间事件名称
            • 可以在 CSS 文件中使用自定义标签
              • 调试
              • 未来蓝图
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档