澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

损伤了复用性,不合乎复杂的前端项目

2019-12-12 作者:澳门新萄京赌场网址   |   浏览(79)

React.Component 损害了复用性?

2016/09/07 · 根底技艺 · binding.scala, data-binding, React, scala.js

正文小编: 伯乐在线 - ThoughtWorks 。未经小编许可,禁绝转发!
接待参加伯乐在线 专辑作者。

本连串的上生龙活虎篇小说《为何ReactJS不符合复杂的前端项目》列举了前端开拓中的各种痛点。本篇小说上校详细索求当中“复用性”痛点。大家将用原生 DHTML API 、 ReactJS 和 Binding.scala 达成同叁个亟需复用的竹签编辑器,然后相比较八个标签编辑器哪个落成难度更低,哪个越来越好用。

HTML也能够静态编写翻译?

2016/11/30 · HTML5 · 1 评论 · binding.scala, React, 前端

正文小编: 伯乐在线 - ThoughtWorks 。未经作者许可,禁绝转发!
迎接参预伯乐在线 专栏小编。

More than React系列小说:

《More than React(后生可畏)为啥ReactJS不合乎复杂的前端项目?》

《More than React(二)React.Component损伤了复用性?》

《More than React(三)虚拟DOM已死?》

《More than React(四)HTML也能够静态编写翻译?》


《More than React》体系的上风华正茂篇作品《虚拟DOM已死?》正如了Binding.scala和任何框架的渲染机制。本篇随笔中校介绍Binding.scala中的XHTML语法。

为啥 ReactJS 不符合复杂的前端项目?

2016/08/17 · JavaScript · 15 评论 · React, ReactJS, 前端

正文我: 伯乐在线 - ThoughtWorks 。未经笔者许可,禁止转发!
招待参与伯乐在线 专辑笔者。

《More than React》系列的稿子会一同分成五篇。本文是首先篇,介绍用ReactJS开辟时遇上的各种难点。前面四篇文章的每大器晚成篇将会分别详细争论之中二个主题素材,以至Binding.scala如何消除这一个标题。

《More than React》类别的篇章会一齐分为五篇。本文是首先篇,介绍用ReactJS开辟时蒙受的各种难点。前面四篇小说的每大器晚成篇将会分别详细座谈之中四个难题,以致Binding.scala如何解决这么些标题。

虚拟 DOM 已死?

2016/10/24 · 幼功本领 · 1 评论 · DOM

正文笔者: 伯乐在线 - ThoughtWorks 。未经笔者许可,防止转发!
款待参预伯乐在线 专辑撰稿者。

本体系文章:

  • 《为啥 ReactJS 不相符复杂的前端项目?》
  • 《React.Component 毁伤了复用性?》

本种类的上生机勃勃篇小说《React.Component 损伤了复用性?》研究了何等在前端开荒中编辑可复用的分界面成分。本篇文章将从性质和算法的角度相比较Binding.scala 和别的框架的渲染机制。

Binding.scala 完成了生机勃勃套精确数据绑定机制,通过在模板中运用 bindfor/yield 来渲染页面。你只怕用过部分其余 Web 框架,好多接纳脏检查或然设想 DOM 机制。和它们相比较,Binding.scala 的精确数据绑定机制使用更简便易行、代码更健康、品质越来越高。

标签编辑器的遵循需求

在InfoQ的不胜枚举作品都有标签。比方本文的价签是“binding.scala”、“data-binding”、“scala.js”。

举个例子你要开垦三个博客系统,你也目的在于博客小编能够拉长标签。所以您可能会提供标签编辑器供博客小编辑访问取。

如图所示,标签编辑器在视觉上分为两行。

图片 1

率先行体现已经增进的全部标签,每一种标签旁边有个“x”按键能够去除标签。第二行是贰个文本框和三个“Add”开关能够把文本框的源委足够为新标签。每一趟点击“Add”按键时,标签编辑器应该检查标签是或不是已经增多过,避防再次增添标签。而在中标增添标签后,还应清空文本框,以便客户输入新的价签。

除却顾客界面以外,标签编辑器还应有提供 API 。标签编辑器所在的页面能够用 API 填入初叶标签,也能够调用 API 随即增加和删除查改标签。假如客商增加和删除了标签,应该有某种机制公告页面包车型客车此外界分。

别的前端框架的标题

背景介绍

二〇一八年 4 月,小编首先次在有些客户的门类中接触到ReactJS 。

自身意识ReactJS要比小编原先用过的AngularJS轻易超级多,它提供了响应式的数额绑定成效,把数量映射到网页上,使本人得以轻易完结相互影响轻易的网址。

可是,随着作者更是浓烈的施用ReactJS,我发觉用ReactJS编写交互作用复杂的网页特不便。 作者期望有生龙活虎种方法,能够像ReactJS同样轻易解决轻巧难点。除此以外,还要能轻易消灭复杂难题。

于是本身把ReactJS用Scala重新写了三个。代码量从近七万行降至了黄金年代千多行。

用那一个框架完毕的TodoMVC应用,只用了154行代码。而用ReactJS完结平等作用的TodoMVC,需要488行代码。

下图是用Binding.scala实现的TodoMVC应用。

图片 2

本条框架就是Binding.scala。

背景介绍

2018年 4 月,笔者首先次在有个别客商的门类中接触到ReactJS 。

自家意识ReactJS要比本人原先用过的AngularJS轻便比较多,它提供了响应式的多少绑定功用,把数据映射到网页上,使自个儿得以轻巧达成相互影响轻易的网址。

可是,随着小编更加深远的利用ReactJS,作者意识用ReactJS编写交互作用复杂的网页特不便。
自己愿意有风流浪漫种艺术,能够像ReactJS同样轻便消除轻松难题。别的,还要能简单消逝复杂难点。

于是乎自个儿把ReactJS用Scala重新写了三个。代码量从近八万行减低到了黄金年代千多行。

用这几个框架达成的TodoMVC应用,只用了154行代码。而用ReactJS完成均等作用的TodoMVC,需要488行代码。

下图是用Binding.scala达成的TodoMVC应用。

其风度翩翩框架正是Binding.scala。

ReactJS虚拟DOM的缺点

诸如, ReactJS 使用设想 DOM 机制,让前者开采者为每种组件提供二个 render 函数。render 函数把 propsstate 转变来 ReactJS 的虚构DOM,然后 ReactJS 框架依据render 再次回到的设想 DOM 成立相仿布局的真正 DOM。

每当 state 校勘时,ReactJS 框架重新调用 render 函数,获取新的虚拟DOM 。然后,框架会相比较上次生成的伪造 DOM 和新的设想 DOM 有怎么着分裂,进而把差别应用到真正 DOM 上。

如此做有两大毛病:

  1. 每次 state 更改,render 函数都要生成完全的伪造 DOM,哪怕 state 退换十分小,render函数也会完好总结一遍。假使 render 函数很复杂,那些历程就能够白白浪费超多总结能源。
  2. ReactJS 框架相比设想 DOM 差距的长河,既慢又轻松出错。举个例子,你想要在有个别 <ul> 列表的顶端插入风流倜傥项 <li> ,那么 ReactJS 框架会误认为你改改了 <ul> 的每生机勃勃项 <li>,然后在尾巴部分插入了叁个 <li>

那是因为 ReactJS 收到的新旧八个虚构 DOM 之间相互独立,ReactJS 并不知道数据源发生了怎么操作,只可以依据新旧五个虚构 DOM 来猜测需求执行的操作。自动的困惑算法既不允许又慢,必定要前端开拓者手动提供 key 属性、shouldComponentUpdate 方法、componentDidUpdate 方法大概 componentWillUpdate 等措施展能力能扶持 ReactJS 框架猜对。

原生 DHTML 版

率先,笔者试着不用其它前端框架,直接调用原生的 DHTML API 来达成标签编辑器,代码如下:

JavaScript

<!DOCTYPE html> <html> <head> <script> var tags = []; function hasTag(tag) { for (var i = 0; i < tags.length; i ) { if (tags[i].tag == tag) { return true; } } return false; } function removeTag(tag) { for (var i = 0; i < tags.length; i ) { if (tags[i].tag == tag) { document.getElementById("tags-parent").removeChild(tags[i].element); tags.splice(i, 1); return; } } } function addTag(tag) { var element = document.createElement("q"); element.textContent = tag; var removeButton = document.createElement("button"); removeButton.textContent = "x"; removeButton.onclick = function (event) { removeTag(tag); } element.appendChild(removeButton); document.getElementById("tags-parent").appendChild(element); tags.push({ tag: tag, element: element }); } function addHandler() { var tagInput = document.getElementById("tag-input"); var tag = tagInput.value; if (tag && !hasTag(tag)) { addTag(tag); tagInput.value = ""; } } </script> </head> <body> <div id="tags-parent"></div> <div> <input id="tag-input" type="text"/> <button onclick="addHandler()">Add</button> </div> <script> addTag("initial-tag-1"); addTag("initial-tag-2"); </script> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;script&gt;
    var tags = [];
 
    function hasTag(tag) {
      for (var i = 0; i &lt; tags.length; i ) {
        if (tags[i].tag == tag) {
          return true;
        }
      }
      return false;
    }
 
    function removeTag(tag) {
      for (var i = 0; i &lt; tags.length; i ) {
        if (tags[i].tag == tag) {
          document.getElementById("tags-parent").removeChild(tags[i].element);
          tags.splice(i, 1);
          return;
        }
      }
    }
 
    function addTag(tag) {
      var element = document.createElement("q");
      element.textContent = tag;
      var removeButton = document.createElement("button");
      removeButton.textContent = "x";
      removeButton.onclick = function (event) {
        removeTag(tag);
      }
      element.appendChild(removeButton);
      document.getElementById("tags-parent").appendChild(element);
      tags.push({
        tag: tag,
        element: element
      });
    }
 
    function addHandler() {
      var tagInput = document.getElementById("tag-input");
      var tag = tagInput.value;
      if (tag &amp;&amp; !hasTag(tag)) {
        addTag(tag);
        tagInput.value = "";
      }
    }
  &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div id="tags-parent"&gt;&lt;/div&gt;
  &lt;div&gt;
    &lt;input id="tag-input" type="text"/&gt;
    &lt;button onclick="addHandler()"&gt;Add&lt;/button&gt;
  &lt;/div&gt;
  &lt;script&gt;
    addTag("initial-tag-1");
    addTag("initial-tag-2");
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
 

为了落实标签编辑器的坚决守护,我用了 45 行 JavaScript 代码来编排 UI 逻辑,外加若干的 HTML <div> 外加两行 JavaScript 代码填入早先化数据。

HTML 文件中硬编码了几个 <div>。这些<div> 本人并非动态创制的,但足以看成容器,放置任何动态创立的因素。

代码中的函数来会把网页内容动态更新到这么些 <div> 中。所以,假使要在同一个页面展现七个标签编辑器,id 就能冲突。因而,以上代码未有复用性。

就算用 jQuery 替代 DHTML API,代码复用依旧很难。为了复用 UI ,jQuery 开辟者日常必需附加扩大代码,在 onload 时扫描整个网页,搜索全部一定 class 属性的要素,然后对这么些成分举办改变。对于复杂的网页,那么些 onload 时运行的函数超级轻松就能够矛盾,举个例子一个函数校勘了三个 HTML 成分,日常形成另豆蔻梢头处代码受影响而内部景色错乱。

对HTML的不尽帮衬

从前小编们选拔任何前端框架,比方Cycle.js 、Widok、ScalaTags时,由于框架不辅助HTML语法,前端程序猿被迫浪费多量岁月,手动把HTML改写成代码,然后稳步调节和测量检验。

便是是支撑HTML语法的框架,举个例子ReactJS,扶持情况也很支离破碎。

比方说,在ReactJS中,你不能够如此写:

JavaScript

class BrokenReactComponent extends React.Component { render() { return ( <ol> <li class="unsupported-class">不支持 class 属性</li> <li style="background-color: red">不支持 style 属性</li> <li> <input type="checkbox" id="unsupported-for"/> <label for="unsupported-for">不支持 for 属性</label> </li> </ol> ); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class BrokenReactComponent extends React.Component {
  render() {
    return (
      <ol>
        <li class="unsupported-class">不支持 class 属性</li>
        <li style="background-color: red">不支持 style 属性</li>
        <li>
          <input type="checkbox" id="unsupported-for"/>
          <label for="unsupported-for">不支持 for 属性</label>
        </li>
      </ol>
    );
  }
}

前面三个程序员必得手动把 classfor 属性替换来 classNamehtmlFor,还要把内联的 style 样式从CSS语法改成JSON语法,代码手艺运营:

JavaScript

class WorkaroundReactComponent extends React.Component { render(卡塔尔 { return ( <ol> <li className="workaround-class">被迫把 class 改成 className</li> <li style={{ backgroundColor: "red" }}>被迫把体制表改成 JSON</li> <li> <input type="checkbox" id="workaround-for"/> <label htmlFor="workaround-for">被迫把 for 改成 htmlFor</label> </li> </ol> 卡塔尔国; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class WorkaroundReactComponent extends React.Component {
  render() {
    return (
      <ol>
        <li className="workaround-class">被迫把 class 改成 className</li>
        <li style={{ backgroundColor: "red" }}>被迫把样式表改成 JSON</li>
        <li>
          <input type="checkbox" id="workaround-for"/>
          <label htmlFor="workaround-for">被迫把 for 改成 htmlFor</label>
        </li>
      </ol>
    );
  }
}

这种开荒情势下,前端程序员纵然能够把HTML原型复制粘贴到代码中,但还亟需大量更动技艺实际运营。比Cycle.js、Widok只怕ScalaTags省各处太多事。

标题意气风发:ReactJS组件难以在千头万绪交互作用页面中复用

ReactJS中的最小复用单位是组件。ReactJS的构件比AngularJS的Controller和View 要轻量些。 每种组件只要求前端开荒者提供三个 render 函数,把 propsstate 映射成网页成分。

如此的轻量级组件在渲染轻松静态页面时很好用, 可是后生可畏旦页面有相互作用,就必需在组件间传递回调函数来处管事人件。

自家将要《More than React(二)组件对复用性有剧毒?》中用原生DHTML API、ReactJS和Binding.scala实现同三个内需复用的页面,介绍Binding.scala怎样简单完毕、简单复用复杂的相互逻辑。

标题后生可畏:ReactJS组件难以在纷纭交互作用页面中复用

ReactJS中的最小复用单位是组件。ReactJS的零件比AngularJS的Controller和View 要轻量些。
每种组件只供给前端开采者提供叁个 render 函数,把 propsstate 映射成网页成分。

那样的轻量级组件在渲染轻巧静态页面时很好用,
而是只要页面有相互,就务须在组件间传递回调函数来处管事人件。

自家就要《More than React(二)组件对复用性有剧毒?》中用原生DHTML API、ReactJS和Binding.scala达成同三个索要复用的页面,介绍Binding.scala怎么样轻易落成、轻便复用复杂的互相逻辑。

AngularJS的脏检查

除了那么些之外近似 ReactJS 的杜撰 DOM 机制,其余流行的框架,举例 AngularJS 还恐怕会接受脏检查算法来渲染页面。

左近 AngularJS 的脏检查算法和 ReactJS 有相仿的劣点,无法得到消息情状改善的用意,必需完整重新总计 View 模板。除却,AngularJS 更新 DOM 的限量往往会比实际所需大得多,所以会比 ReactJS 还要慢。

ReactJS 达成的标签编辑器组件

ReactJS 提供了足以复用的机件,即 React.Component 。假如用 ReactJS 达成标签编辑器,大概能够如此写:

JavaScript

class TagPicker extends React.Component { static defaultProps = { changeHandler: tags => {} } static propTypes = { tags: React.PropTypes.arrayOf(React.PropTypes.string).isRequired, changeHandler: React.PropTypes.func } state = { tags: this.props.tags } addHandler = event => { const tag = this.refs.input.value; if (tag && this.state.tags.indexOf(tag) == -1) { this.refs.input.value = ""; const newTags = this.state.tags.concat(tag); this.setState({ tags: newTags }); this.props.changeHandler(newTags); } } render() { return ( <section> <div>{ this.state.tags.map(tag => <q key={ tag }> { tag } <button onClick={ event => { const newTags = this.state.tags.filter(t => t != tag); this.setState({ tags: newTags }); this.props.changeHandler(newTags); }}>x</button> </q> ) }</div> <div> <input type="text" ref="input"/> <button onClick={ this.addHandler }>Add</button> </div> </section> ); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class TagPicker extends React.Component {
 
  static defaultProps = {
    changeHandler: tags =&gt; {}
  }
 
  static propTypes = {
    tags: React.PropTypes.arrayOf(React.PropTypes.string).isRequired,
    changeHandler: React.PropTypes.func
  }
 
  state = {
    tags: this.props.tags
  }
 
  addHandler = event =&gt; {
    const tag = this.refs.input.value;
    if (tag &amp;&amp; this.state.tags.indexOf(tag) == -1) {
      this.refs.input.value = "";
      const newTags = this.state.tags.concat(tag);
      this.setState({
        tags: newTags
      });
      this.props.changeHandler(newTags);
    }
  }
 
  render() {
    return (
      &lt;section&gt;
        &lt;div&gt;{
          this.state.tags.map(tag =&gt;
            &lt;q key={ tag }&gt;
              { tag }
              &lt;button onClick={ event =&gt; {
                const newTags = this.state.tags.filter(t =&gt; t != tag);
                this.setState({ tags: newTags });
                this.props.changeHandler(newTags);
              }}&gt;x&lt;/button&gt;
            &lt;/q&gt;
          )
        }&lt;/div&gt;
        &lt;div&gt;
          &lt;input type="text" ref="input"/&gt;
          &lt;button onClick={ this.addHandler }&gt;Add&lt;/button&gt;
        &lt;/div&gt;
      &lt;/section&gt;
    );
  }
 
}
 

以上 51 行 ECMAScript 2016代码实现了叁个标签编辑器组件,即TagPicker。就算代码量比 DHTML 版长了一丝丝,但复用性大大晋级了。

要是你绝不 ECMAScript 二零一六 的话,那么代码还组织带头人一些,何况须求管理局地JavaScript 的坑,举个例子在回调函数中用持续 this

ReactJS 开采者能够随即用 ReactDOM.render 函数把 TagPicker 渲染到任何空白成分内。其余,ReactJS 框架能够在 stateprops 更改时触发 render ,进而防止了手动校订现有的 DOM。

若是不思量冗余的 key 属性,单个组件内的人机联作 ReactJS 还算壮志未酬。可是,复杂的网页构造往往要求多少个零件层层嵌套,这种父亲和儿子组件之间的互相,ReactJS 就很棘手了。

举例,假诺必要在 TagPicker 之外展现全部的价签,每当顾客增加和删除标签,那几个标签也要自动更新。要完结那个功用,须要给 TagPicker 传入 changeHandler 回调函数,代码如下:

JavaScript

class Page extends React.Component { state = { tags: [ "initial-tag-1", "initial-tag-2" ] }; changeHandler = tags => { this.setState({ tags }卡塔尔国; }; render(卡塔尔 { return ( <div> <TagPicker tags={ this.state.tags } changeHandler={ this.changeHandler }/> <h3>全体标签:</h3> <ol>{ this.state.tags.map(tag => <li>{ tag }</li> 卡塔尔 }</ol> </div> 卡塔尔(英语:State of Qatar); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Page extends React.Component {
 
  state = {
    tags: [ "initial-tag-1", "initial-tag-2" ]
  };
 
  changeHandler = tags =&gt; {
    this.setState({ tags });
  };
 
  render() {
    return (
      &lt;div&gt;
        &lt;TagPicker tags={ this.state.tags } changeHandler={ this.changeHandler }/&gt;
        &lt;h3&gt;全部标签:&lt;/h3&gt;
        &lt;ol&gt;{ this.state.tags.map(tag =&gt; &lt;li&gt;{ tag }&lt;/li&gt; ) }&lt;/ol&gt;
      &lt;/div&gt;
    );
  }
 
}
 

为了能接触页面其余一些更新,作者被迫扩大了二个 21 行代码的 Page 组件。

Page 组件必得完毕 changeHandler 回调函数。每当回调函数触发,调用 Page 自己的 setState 来触发 Page 重绘。

从那些事例,我们能够看看, ReactJS 能够简不难单的消除轻松的标题,但碰上档期的顺序复杂、交互作用频仍的网页,实现起来就很麻烦。使用 ReactJS 的前端项目充满了各样 xxxHandler 用来在组件中传递音信。作者加入的某海外顾客项目,平均各个组件大约须要传入四个回调函数。即便档案的次序嵌套深,创制网页时,通常必要把回调函数从最顶层的机件风度翩翩百年难遇传入最底部的零器件,而当事件触发时,又须求风度翩翩稀缺把事件音信往外传。整个前端项目有超过二分之一代码都在如此绕圈子。

不协作原生DOM操作

别的,ReactJS等局地前端框架,会生成设想DOM。设想DOM不大概合作浏览器原生的DOM API ,以致和jQuery、D3等任何库协作时举步维艰。比方ReactJS更新DOM对象时日常会破坏掉jQuery控件。

Reddit诸五个人商议了这么些题目。他们从没主意,只好弃用jQuery。笔者司的某客商在用了ReactJS后也被迫用ReactJS重写了汪洋jQeury控件。

标题二:ReactJS的虚构DOM 算法又慢又不允许

ReactJS的页面渲染算法是编造DOM差量算法。

开采者须要提供 render 函数,根据 propsstate 生成虚拟 DOM。 然后 ReactJS 框架依据 render 再次来到的虚构 DOM 创制肖似结构的敦朴 DOM.

每当 state 改正时,ReacJS 框架重新调用 render 函数,获取新的虚构 DOM 。 然后,框架会相比上次生成的伪造 DOM 和新的伪造 DOM 有如何区别,然后把差距应用到真正DOM上。

这么做有两大毛病:

  1. 每次 state 更改,render 函数都要生成完全的设想 DOM. 哪怕 state 改换异常的小,render函数也会完全计算三回。如若 render 函数很复杂,这一个进程就白白浪费了数不尽测算能源。
  2. ReactJS框架相比设想DOM差别的长河,既慢又易于失误。举例,倘让你想要在有些 <ul>列表的最上端插入后生可畏项 <li> ,那么ReactJS框架会误感觉你改改了 <ul> 的每风姿浪漫项 <li>,然后在尾巴部分插入了二个 <li>

那是因为 ReactJS收到的新旧七个设想DOM之间相互独立,ReactJS并不知道数据源爆发了什么样操作,只好依靠新旧八个设想DOM来猜测亟需执行的操作。 自动的测度算法既不允许又慢,一定要前端开辟者手动提供 key 属性、shouldComponentUpdate 方法、componentDidUpdate 方法依然 componentWillUpdate 等措施展能力能帮衬 ReactJS 框架猜对。

本人就要《More than React(三)设想DOM已死?》中相比ReactJS、AngularJS和Binding.scala渲染机制,介绍轻松质量高的Binding.scala正确数据绑定机制。

主题材料二:ReactJS的设想DOM 算法又慢又不许

ReactJS的页面渲染算法是虚构DOM差量算法。

开辟者需求提供 render 函数,根据 propsstate 生成设想 DOM。
下一场 ReactJS 框架根据 render 再次回到的虚构 DOM 成立相像布局的实际 DOM.

每当 state 改正时,ReacJS 框架重新调用 render 函数,获取新的杜撰 DOM 。
接下来,框架会相比较上次生成的伪造 DOM 和新的虚构 DOM 有何样不同,然后把差距应用到实际DOM上。

如此做有两大劣势:

  1. 每次 state 更改,render 函数都要生成完全的设想 DOM. 哪怕 state 退换相当的小,render函数也会完好总括一回。若是 render 函数很复杂,那么些进度就白白浪费了广大测算能源。
  2. ReactJS框架相比虚构DOM差别的经过,既慢又易于失误。比方,借使你想要在有些 <ul> 列表的顶端插入风流罗曼蒂克项 <li> ,那么ReactJS框架会误以为你改改了 <ul> 的每蓬蓬勃勃项 <li>,然后在尾巴部分插入了三个 <li>

那是因为 ReactJS收到的新旧八个设想DOM之间相互独立,ReactJS并不知道数据源产生了怎么着操作,只可以依照新旧多个设想DOM来猜测急需实行的操作。
电动的推测算法既不准又慢,必供给前端开辟者手动提供 key 属性、shouldComponentUpdate 方法、componentDidUpdate 方法依旧 componentWillUpdate 等措施展技艺能协理 ReactJS 框架猜对。

自己就要《More than React(三)虚构DOM已死?》中相比ReactJS、AngularJS和Binding.scala渲染机制,介绍轻便质量高的Binding.scala正确数据绑定机制。

Binding.scala的确切数据绑定

Binding.scala 使用准确数据绑定算法来渲染 DOM 。

在 Binding.scala 中,你能够用 @dom 注解申明数据绑定表达式。@dom 会自动把 = 之后的代码包装成 Binding 类型。

比如:

@dom val i: Binding[Int] = 1 @dom def f: Binding[Int] = 100 @dom val s: Binding[String] = "content"

1
2
3
@dom val i: Binding[Int] = 1
@dom def f: Binding[Int] = 100
@dom val s: Binding[String] = "content"

@dom 既可用于 val 也得以用于 def ,能够发挥包罗 IntString 在内的别的数据类型。

除却,@dom 方法还足以一向编写 XHTML,比方:

@dom val comment: Binding[Comment] = <!-- This is a HTML Comment --> @dom val br: Binding[HTMLBRElement] = <br/> @dom val seq: Binding[BindingSeq[HTMLBRElement]] = <br/><br/>

1
2
3
@dom val comment: Binding[Comment] = <!-- This is a HTML Comment -->
@dom val br: Binding[HTMLBRElement] = <br/>
@dom val seq: Binding[BindingSeq[HTMLBRElement]] = <br/><br/>

这些 XHTML 生成的 Comment 和 HTMLBRElement 是 HTML Node 的派生类。实际不是XMLNode。

每个 @dom 方法都得以依赖别的数据绑定表明式:

val i: Var[Int] = Var(0) @dom val j: Binding[Int] = 2 @dom val k: Binding[Int] = i.bind * j.bind @dom val div: Binding[HTMLDivElement] = <div>{ k.bind.toString }</div>

1
2
3
4
val i: Var[Int] = Var(0)
@dom val j: Binding[Int] = 2
@dom val k: Binding[Int] = i.bind * j.bind
@dom val div: Binding[HTMLDivElement] = <div>{ k.bind.toString }</div>

通过这种格局,你能够编写制定 XHTML 模板把数据源映射为 XHTML 页面。这种准确的照耀关系,描述了数据里面包车型客车关联,并不是 ReactJS 的 render 函数那样描述运算进程。所以当数码产生转移时,独有受影响的片段代码才会另行总括,而不必要再次总括整个 @dom 方法。

比如:

val count = Var(0) @dom def status: Binding[String] = { val startTime = new Date "本页面早先化的年华是" startTime.toString "。开关被按过"

  • count.bind.toString "次。按键最后三回按下的时光是" (new Date卡塔尔国.toString } @dom def render = { <div> { status.bind } <button onclick={ event: 伊芙nt => count := count.get 1 }>更新意况</button> </div> }
1
2
3
4
5
6
7
8
9
10
11
12
13
val count = Var(0)
 
@dom def status: Binding[String] = {
  val startTime = new Date
  "本页面初始化的时间是" startTime.toString "。按钮被按过" count.bind.toString "次。按钮最后一次按下的时间是" (new Date).toString
}
 
@dom def render = {
  <div>
    { status.bind }
    <button onclick={ event: Event => count := count.get 1 }>更新状态</button>
  </div>
}

上述代码能够在ScalaFiddle事实上运营一下试跳。

注意,status 并不是多个平时的函数,而是描述变量之间涉及的极度规表达式,每一趟渲染时只实行在那之中某些代码。举例,当 count 改动时,独有坐落于 count.bind 未来的代码才会再一次计算。由于 val startTime = new Date 位于 count.bind 此前,并不会再一次计算,所以会直接维系为开垦网页第一遍施行时的初始值。

些微人在学习 ReactJS 或许 AngularJS 时,要求上学 keyshouldComponentUpdate$apply$digest 等繁琐概念。这个概念在 Binding.scala 中常常有一纸空文。因为 Binding.scala 的 @dom 方法描述的是变量之间的涉及。所以,Binding.scala 框架知道确切数据绑定关系,能够自动物检疫查测量试验出供给立异的微小部分。

Binding.scala 的中坚用法

在批注 Binding.scala 如何得以完成标签编辑器早先,作者先介绍一些 Binding.scala 的底子知识:

Binding.scala 中的最小复用单位是数据绑定表明式,即 @dom 方法。每个 @dom 方法是黄金年代段 HTML 模板。比方:

JavaScript

// 两个 HTML 换行符 @dom def twoBr = <br/><br/>

1
2
3
// 两个 HTML 换行符
@dom def twoBr = &lt;br/&gt;&lt;br/&gt;
 

JavaScript

// 一个 HTML 标题 @dom def myHeading(content: String) = <h1>{content}</h1>

1
2
3
// 一个 HTML 标题
@dom def myHeading(content: String) = &lt;h1&gt;{content}&lt;/h1&gt;
 

各样模板还足以接受bind语法富含其余子模板,举个例子:

JavaScript

@dom def render = { <div> { myHeading("Binding.scala的特点").bind } <p> 代码短 { twoBr.bind } 概念少 { twoBr.bind } 功能多 </p> </div> }

1
2
3
4
5
6
7
8
9
10
11
12
13
@dom def render = {
  &lt;div&gt;
    { myHeading("Binding.scala的特点").bind }
    &lt;p&gt;
      代码短
      { twoBr.bind }
      概念少
      { twoBr.bind }
      功能多
    &lt;/p&gt;
  &lt;/div&gt;
}
 

您能够参见附录:Binding.scala火速上手指南,学习上手Binding.scala开拓的具体步骤。

别的,本连串第四篇小说《HTML也足以编写翻译》还将列出Binding.scala所支撑的全体HTML模板本性。

Binding.scala中的XHTML

于今有了Binding.scala ,能够在@dom办法中,直接编写XHTML。比如:

JavaScript

@dom def introductionDiv = { <div style="font-size:0.8em"> <h3>Binding.scala的优点</h3> <ul> <li>简单</li> <li>概念少<br/>功能多</li> </ul> </div> }

1
2
3
4
5
6
7
8
9
@dom def introductionDiv = {
  <div style="font-size:0.8em">
    <h3>Binding.scala的优点</h3>
    <ul>
      <li>简单</li>
      <li>概念少<br/>功能多</li>
    </ul>
  </div>
}

如上代码会被编译,直接创建真实的DOM对象,而从不伪造DOM。

Binding.scala对浏览器原生DOM的扶持很好,你能够在这里些DOM对象上调用DOM API,与 D3、jQuery等别的库交互作用也截然没不寻常。

ReactJS对XHTML语法的一鳞半爪。相比较之下,Binding.scala协助完全的XHTML语法,前端技术员能够一直把设计好的HTML原型复制粘贴到代码中,整个网址就足以运作了。

难题三:ReactJS的HTML模板成效既不康健、也不健康

ReactJS支持用JSX编写HTML模板。

一手遮天上,前端技术员只要把静态HTML原型复制到JSX源文件中, 扩展部分变量替换代码, 就能够退换成动态页面。 理论上这种做法要比Cycle.js、Widok、ScalaTags等框架更符合复用设计员提供的HTML原型。

糟糕的是,ReactJS对HTML的支撑四分五裂。开荒者必需手动把classfor品质替换来classNamehtmlFor,还要把内联的style体制从CSS语法改成JSON语法,代码能力运作。 这种开采格局下,前端技术员固然能够把HTML原型复制粘贴到代码中,但还亟需大量更改能力实际运营。 比Cycle.js、Widok、恐怕、ScalaTags省持续太多事。

除去,ReactJS还提供了propTypes体制校验虚构DOM的合法性。 但是,这一编写制定也破绽超多。 就算钦命了propTypes,ReactJS也无法在编写翻译前提前开采错误。唯有测验覆盖率相当的高的种类时技艺在每一种组件使用其余构件时开展校验。 就算测验覆盖率超高,propTypes反之亦然不能够检查实验出拼错的属性名,假如您把onClick写成了onclick, ReactJS就不会报错,往往招致开采者额外开销多量时刻每一个核实多少个很简短的bug。

自家将要《More than React(四)HTML也得以编写翻译?》中相比较ReactJS和Binding.scala的HTML模板,介绍Binding.scala怎么着在整机扶持XHTML语法的同时静态检查语法错误和语义错误。

难点三:ReactJS的HTML模板成效既不康健、也不硬朗

ReactJS支持用JSX编写HTML模板。

一手遮天上,前端程序员只要把静态HTML原型复制到JSX源文件中,
追加部分变量替换代码,
就能够改换成动态页面。
商量上这种做法要比Cycle.js、Widok、ScalaTags等框架更相符复用设计员提供的HTML原型。

不幸的是,ReactJS对HTML的援救东鳞西爪。开拓者必需手动把classfor属性替换到classNamehtmlFor,还要把内联的style体制从CSS语法改成JSON语法,代码才具运营。
这种开拓方式下,前端技术员就算能够把HTML原型复制粘贴到代码中,但还需求多量改正本事实际运营。
比Cycle.js、Widok、只怕、ScalaTags省相连太多事。

除开,ReactJS还提供了propTypes机制校验设想DOM的合法性。
可是,这第一建工公司制也破绽超级多。
固然钦命了propTypes,ReactJS也不能够在编写翻译前提前开掘错误。唯有测验覆盖率超级高的等级次序时技巧在每种组件使用任何零零部件时张开校验。
不怕测量检验覆盖率超级高,propTypes依旧无法检验出拼错的属性名,借使您把onClick写成了onclick
ReactJS就不会报错,往往招致开垦者额外开支大批量时日各个考察一个比较轻易的bug。

本身将要《More than React(四)HTML也足以编写翻译?》中相比较ReactJS和Binding.scala的HTML模板,介绍Binding.scala怎么着在黄金年代体化帮忙XHTML语法的同一时间静态检查语法错误和语义错误。

结论

正文相比较了设想 DOM 、脏检查和标准数据绑定三种渲染机制。

AngularJS ReactJS Binding.scala
渲染机制 脏检查 虚拟DOM 精确数据绑定
数据变更时的运算步骤
  1. 重复检查数据是否更改
  2. 大范围更新页面,哪怕这部分页面根本没有修改
  1. 重新生成整个虚拟DOM
  2. 比较新旧虚拟DOM的差异
  3. 根据差异更新页面
  1. 直接根据数据映射关系,更新最小范围页面
检测页面更新范围的准确性 不准 默认情况下不准,需要人工提供keyshouldComponentUpdate才能准一点
需要前端工程师理解多少API和概念才能正确更新页面 很多 很多 只有@dombind两个概念
总体性能 非常差

那三种机制中,Binding.scala 的纯粹数据绑定机制概念越来越少,作用越来越强,品质更高。作者将要下黄金时代篇作品中牵线 Binding.scala 怎么样在渲染 HTML 时静态检查语法错误和语义错误,进而幸免 bug 。

1 赞 收藏 1 评论

Binding.scala完成的标签编辑器模板

末尾,下文将显示什么用Binding.scala达成标签编辑器。

标签编辑器要比刚刚介绍的HTML模板复杂,因为它不唯有是静态模板,还包括交互作用。

JavaScript

@dom def tagPicker(tags: Vars[String]) = { val input: Input = <input type="text"/> val addHandler = { event: Event => if (input.value != "" && !tags.get.contains(input.value)) { tags.get = input.value input.value = "" } } <section> <div>{ for (tag <- tags) yield <q> { tag } <button onclick={ event: Event => tags.get -= tag }>x</button> </q> }</div> <div>{ input } <button onclick={ addHandler }>Add</button></div> </section> }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@dom def tagPicker(tags: Vars[String]) = {
  val input: Input = &lt;input type="text"/&gt;
  val addHandler = { event: Event =&gt;
    if (input.value != "" &amp;&amp; !tags.get.contains(input.value)) {
      tags.get = input.value
      input.value = ""
    }
  }
  &lt;section&gt;
    &lt;div&gt;{
      for (tag &lt;- tags) yield &lt;q&gt;
        { tag }
        &lt;button onclick={ event: Event =&gt; tags.get -= tag }&gt;x&lt;/button&gt;
      &lt;/q&gt;
    }&lt;/div&gt;
    &lt;div&gt;{ input } &lt;button onclick={ addHandler }&gt;Add&lt;/button&gt;&lt;/div&gt;
  &lt;/section&gt;
}
 

本条标签编辑器的 HTML 模板后生可畏共用了 18 行代码就贯彻好了。

标签编辑器中必要彰显当前持有标签,所以那边用tags: Vars[String]保留全体的标签数据,再用for/yield循环把tags中的每一个标签渲染成UI成分。

Vars 是支撑数据绑定的列表容器,每当容器中的数据发生退换,UI就能够活动退换。所以,在x按键中的onclick事件中删去tags中的数据时,页面上的竹签就能够自动随之灭绝。雷同,在Add按钮的onclick中向tags中加多数据时,页面上也会活动发出相应的竹签。

Binding.scala不但完成标签编辑器比 ReactJS 轻松,并且用起来也比 ReactJS 轻易:

JavaScript

@dom def render(卡塔尔(英语:State of Qatar) = { val tags = Vars("initial-tag-1", "initial-tag-2"卡塔尔(قطر‎<div> { tagPicker(tags卡塔尔(英语:State of Qatar).bind } <h3>全体标签:</h3> <ol>{ for (tag <- tags卡塔尔 yield <li>{ tag }</li> }</ol> </div> }

1
2
3
4
5
6
7
8
9
@dom def render() = {
  val tags = Vars("initial-tag-1", "initial-tag-2")
  &lt;div&gt;
    { tagPicker(tags).bind }
    &lt;h3&gt;全部标签:&lt;/h3&gt;
    &lt;ol&gt;{ for (tag &lt;- tags) yield &lt;li&gt;{ tag }&lt;/li&gt; }&lt;/ol&gt;
  &lt;/div&gt;
}
 

设若用 9 行代码另写五个 HTML 模板,在模板中调用刚才完结好的 tagPicker 就行了。

完整的 DEMO 请访问 。

在 Binding.scala 没有必要像 ReactJS 那样编写 changeHandler 之类的回调函数。每当客户在 tagPicker 输入新的标签时,tags 就能转移,网页也就能够自行随之转移。

相对来讲 ReactJS 和 Binding.scala 的代码,能够窥见以下分别:

  • Binding.scala 的开拓者能够用接近 tagPicker 这样的 @dom 方法表示 HTML 模板,而无需组件概念。
  • Binding.scala 的开垦者能够在点子之间传递 tags 那样的参数,而无需 props 概念。
  • Binding.scala 的开辟者能够在章程钦定义局地变量表示情形,而不供给 state 概念。

由此看来 Binding.scala 要比 ReactJS 简洁明了不菲。

借让你用过 ASP 、 PHP 、 JSP 之类的服务端网页模板语言, 你会发掘和 Binding.scala 的 HTML 模板很像。

动用 Binding.scala 一点也无需函数式编制程序知识,只要把规划工具中生成的 HTML 原型复制到代码中,然后把会变的局地用花括号代替、把重复的豆蔻梢头部分用 for / yield 替代,网页就抓好了。

Binding.scala中XHTML的类型

@dom方法中XHTML对象的体系是Node的派生类。

比如,<div></div> 的档次正是HTMLDivElement,而 <button></button> 的品类就是 HTMLButtonElement。

此外, @dom 注脚会修正总体艺术的重回值,包装成几个Binding。

JavaScript

@dom def typedButton: Binding[HTMLButtonElement] = { <button>按钮</button> }

1
2
3
@dom def typedButton: Binding[HTMLButtonElement] = {
  <button>按钮</button>
}

注意typedButton是个原生的HTMLButtonElement,所以能够一向对它调用 DOM API。举例:

JavaScript

@dom val autoPrintln: Binding[Unit] = { println(typedButton.bind.innerHTML卡塔尔(قطر‎ // 在调整新北打字与印刷按键内部的 HTML } autoPrintln.watch(卡塔尔(英语:State of Qatar)

1
2
3
4
@dom val autoPrintln: Binding[Unit] = {
  println(typedButton.bind.innerHTML) // 在控制台中打印按钮内部的 HTML
}
autoPrintln.watch()

这段代码中,typedButton.bind.innerHTML 调用了 DOM API HTMLButtonElement.innerHTML。通过autoPrintln.watch(),每当按键爆发更新,autoPrintln中的代码就能够实施二回。

难点四:ReactJS与服务器通讯时索要复杂的异步编制程序

ReactJS从服务器加载数据时的构造可以充当MVVM(Model–View–ViewModel卡塔尔(قطر‎形式。 前端程序员必要编写制定三个数据库访谈层作为Model,把ReactJS的state当做ViewModel,而render用作View。 Model担任访问数据库并把数量设置到state(即View Model)上,可以用Promise和fetch API实现。 然后,render,即View,担负把View Model渲染到页面上。

在此全数流程中,前端程序猿须求编写制定多量闭包组成的异步流程, 设置、访谈状态的代码五零四散, 一非常的大心就能够bug丛生,尽管小心翼翼的拍卖各个异步事件,也会促成程序变得复杂,既难调试,又难保险。

自身就要《More than React(五)为何别用异步编制程序?》中相比较ReactJS和Binding.scala的数目同步模型,介绍Binding.scala怎样自动同步服务器数据,制止手动异步编制程序。

标题四:ReactJS与服务器通讯时索要复杂的异步编制程序

ReactJS从服务器加载数据时的构造能够看成MVVM(Model–View–ViewModel卡塔尔(قطر‎方式。
前面二个程序员要求编写制定三个数据库访谈层作为Model,把ReactJS的state当做ViewModel,而render当做View。
Model肩负访谈数据库并把数量设置到state(即View Model)上,可以用Promise和fetch API实现。
然后,render,即View,担当把View Model渲染到页面上。

在此总体流程中,前端技术员需求编写制定大量闭包组成的异步流程,
安装、访谈状态的代码五零四散,
轻率就能够bug丛生,固然如临深渊的管理各样异步事件,也会招致程序变得复杂,既难调试,又难保证。

本人就要《More than React(五)为啥别用异步编制程序?》中相比ReactJS和Binding.scala的数额同步模型,介绍Binding.scala怎么样自动同步服务器数据,制止手动异步编制程序。

关于作者:ThoughtWorks

图片 3

ThoughtWorks是一家中外IT咨询集团,追求特出软件品质,致力于科学技术驱动商业变革。长于创设定制化软件出品,扶持客户高效将概念转变为价值。同不经常间为顾客提供顾客体验设计、本领战术咨询、组织转型等咨询服务。 个人主页 · 笔者的小说 · 84 ·   

图片 4

结论

正文相比了分化才能栈中实现和行使可复用的标签编辑器的难度。

原生 HTML ReactJS Binding.scala
实现标签编辑器需要代码行数 45行 51行 17行
实现标签编辑器的难点 在代码中动态更新HTML页面太繁琐 实现组件的语法很笨重
使用标签编辑器并显示标签列表需要代码行数 难以复用 21行 8行
阻碍复用的难点 静态HTML元素难以模块化 交互组件之间层层传递回调函数过于复杂

Binding.scala 不表达“组件”之类的噱头,而以更轻松的“方法”为最小复用单位,让编制程序体验特别通畅,拿到了更加好的代码复用性。

本种类下黄金时代篇文章将对比 ReactJS 的杜撰 DOM 机制和 Binding.scala 的规范数据绑定机制,爆料 ReactJS 和 Binding.scala 相通用法背后隐蔽的两样算法。

其他HTML节点

Binding.scala支持HTML注释:

JavaScript

@dom def comment = { <!-- 你看不见小编 --> }

1
2
3
@dom def comment = {
  <!-- 你看不见我 -->
}

Binding.scala也支持CDATA块:

JavaScript

@dom def inlineStyle = { <section> <style><![CDATA[ .highlight { background-color:gold } ]]></style> <p class="highlight">Binding.scala真好用!</p> </section> }

1
2
3
4
5
6
7
8
9
10
@dom def inlineStyle = {
  <section>
    <style><![CDATA[
      .highlight {
        background-color:gold
      }
    ]]></style>
    <p class="highlight">Binding.scala真好用!</p>
  </section>
}

结论

固然Binding.scala初看上去很像ReactJS, 但隐讳在Binding.scala背后的编制更简便易行、更通用,与ReactJS和Widok天渊之别。

于是,通过简化概念,Binding.scala灵活性更加强,能用通用的不二等秘书技肃清ReactJS消灭不了的千头万绪难题。

比方,除了上述三个地点以外,ReactJS的情状管理也是艰苦难点,如若引进Redux或许react-router那样的第三方库来管理景况,会促成架构变复杂,分层变多,代码绕来绕去。而Binding.scala能够用和页面渲染相像的数码绑定机制描述复杂的气象,无需其它第三方库,就会提供服务器通信、状态管理和网站分发的成效。

以下表格中列出了上述Binding.scala和ReactJS的效果差别:

Binding.scala

ReactJS

复用性

细微复用单位

方法

组件

复用难度

任由交互内容依旧静态内容都轻易复用

轻巧复用静态内容组件,但麻烦复用交互作用组件

页面渲染算法

算法

确切的数目绑定

虚拟 DOM

性能

正确性

机关保障科学

须求开垦者手动设置 key 属性,不然复杂的页面会混杂。

HTML 模板

语法

Scala XML 字面量

JSX

是还是不是扶持 HTML 或 XHTML 语法

总体帮忙 XHTML

残破援助。平时的 XHTML 不能够编写翻译。开垦者必得手动把 classfor 属性替换成 classNamehtmlFor,还要把内联的 style 样式从 CSS 语法改成 JSON 语法。

何以校验模板语法

电动编写翻译时校验

运行时通过 propTypes 校验但相当小概检查测量检验大概的拼写错误。

服务器通讯

机制

自行远程数据绑定

损伤了复用性,不合乎复杂的前端项目。MVVM 异步编程

金玉锦绣难度

简单

复杂

其他

怎么分摊网站可能锚点链接

扶助把网站当成普通的绑定变量来用,无需第三方库。

不补助,供给第三方库 react-router

职能康健性

完全的前端开拓建设方案

自己只满含视图部分机能。供给非常理解 react-router 、 Redux 等级三方库本领兑现全体的前端项目。

上学曲线

API 简单,对没用过 Scala 的人的话也很好懂

上心灵。但成效太弱引致前期学习第三方库时曲线陡峭。

Binding.scala

ReactJS

多个多月前,我在Scala.js的论坛公布Binding.scala时,这时Scala.js社区最风靡的响应式前端编制程序框架是Widok。TimNieradzik是Widok的撰稿者。他在看见本身颁发的框架后,表扬那些框架是Scala.js社区最有前程的 HTML 5渲染框架。

他是对的,5个月后,现在Binding.scala已经化为Scala.js社区最盛行的响应式前端编制程序框架。

Awesome Scala网站相对来说了Scala的响应式前端编制程序框架,Binding.scala的龙腾虎跃程度和流行度都比Udash、Widok等任何框架要高。

图片 5

本身在几日前的多少个类型中,也慢慢扬弃JavaScript和ReactJS,改用Scala.js和Binding.scala搭建新时期的前端本事栈。

结论

就算Binding.scala初看上去很像ReactJS,
但隐蔽在Binding.scala背后的建制更简便易行、更通用,与ReactJS和Widok楚河汉界。

所以,通过简化概念,Binding.scala灵活性更加强,能用通用的办法化解ReactJS湮灭不了的错综相连难点。

比如,除了上述四个方面以外,ReactJS的意况管理也是来处不易难点,如若引进Redux可能react-router那样的第三方库来拍卖景况,会形成布局变复杂,分层变多,代码绕来绕去。而Binding.scala能够用和页面渲染同样的数目绑定机制描述复杂的景况,无需其它第三方库,就会提供服务器通讯、状态处理和网站分发的成效。

以下表格中列出了上述Binding.scala和ReactJS的效果与利益差别:

3-sheet.png

多个多月前,小编在Scala.js的论坛发布Binding.scala时,当时Scala.js社区最风靡的响应式前端编制程序框架是Widok。TimNieradzik是Widok的审核人。他在阅览自家颁发的框架后,赞美那些框架是Scala.js社区最有前途的 HTML 5渲染框架。

他是对的,三个月后,现在Binding.scala已经化为Scala.js社区最盛行的响应式前端编制程序框架。

Awesome Scala网站相对来说了Scala的响应式前端编制程序框架,Binding.scala的活泼程度和流行度都比Udash、Widok等此外框架要高。

自家在方今的多少个连串中,也稳步吐弃JavaScript和ReactJS,改用Scala.js和Binding.scala搭建新时期的前端技能栈。

相关链接

  • Binding.scala 项目主页
  • Binding.scala • TodoMVC 项目主页
  • Binding.scala • TodoMVC DEMO
  • Binding.scala • TodoMVC 以外的别样 DEMO
  • JavaScript 到 Scala.js 移植指南
  • Scala.js 项目主页
  • Scala API 参照他事他说加以考察文书档案
  • Scala.js API 参照他事他说加以考查文书档案
  • Scala.js DOM API 参考文书档案
  • Binding.scala火速上手指南
  • Binding.scala API参照他事他说加以调查文书档案
  • Binding.scala 的 Gitter 聊天室

    1 赞 1 收藏 评论

内嵌Scala代码

除去能够把XHTML内嵌在Scala代码中的 @dom 方法中,Binding.scala 还支持用 { ... } 语法把 Scala 代码内嵌到XHTML中。举例:

JavaScript

@dom def randomParagraph = { <p>生成二个随意数: { math.random.toString }</p> }

1
2
3
@dom def randomParagraph = {
  <p>生成一个随机数: { math.random.toString }</p>
}

XHTML中内嵌的Scala代码能够用 .bind 绑定变量可能调用其余 @dom 方法,比如:

JavaScript

val now = Var(new Date卡塔尔 window.setInterval(1000卡塔尔国 { now := new Date } @dom def render = { <div> 今后时刻:{ now.bind.toString } { introductionDiv.bind } { inlineStyle.bind } { typedButton.bind } { comment.bind } { randomParagraph.bind } </div> }

1
2
3
4
5
6
7
8
9
10
11
12
13
val now = Var(new Date)
window.setInterval(1000) { now := new Date }
 
@dom def render = {
  <div>
    现在时间:{ now.bind.toString }
    { introductionDiv.bind }
    { inlineStyle.bind }
    { typedButton.bind }
    { comment.bind }
    { randomParagraph.bind }
  </div>
}

上述代码渲染出的网页中,时间会动态退换。

连锁链接

  • Binding.scala 项目主页
  • Binding.scala • TodoMVC 项目主页
  • Binding.scala • TodoMVC DEMO
  • Binding.scala • TodoMVC 以外的别的DEMO
  • JavaScript 到 Scala.js 移植指南
  • Scala.js 项目主页
  • Scala API 参谋文档
  • Scala.js API 参谋文书档案
  • Scala.js DOM API 参谋文档
  • Binding.scala飞快上手指南
  • Binding.scala API参照他事他说加以考察文书档案
  • Binding.scala 的 Gitter 聊天室

    1 赞 5 收藏 15 评论

连带链接

  • Binding.scala 项目主页
  • Binding.scala • TodoMVC 项目主页
  • Binding.scala • TodoMVC DEMO
  • Binding.scala • TodoMVC 以外的其他DEMO
  • JavaScript 到 Scala.js 移植指南
  • Scala.js 项目主页
  • Scala API 参谋文书档案
  • Scala.js API 参谋文书档案
  • Scala.js DOM API 参照他事他说加以考察文书档案
  • Binding.scala快捷上手指南
  • Binding.scala API参照他事他说加以考察文书档案
  • Binding.scala 的 Gitter 聊天室

至于作者:ThoughtWorks

图片 6

ThoughtWorks是一家中外IT咨询集团,追求卓绝软件品质,致力于科学技术驱动商业变革。专长构建定制化软件出品,辅助顾客快捷将定义转变为价值。同期为用户提供客户体验设计、技巧战略咨询、协会转型等咨询服务。 个人主页 · 作者的稿子 · 84 ·   

图片 7

强类型的 XHTML

Binding.scala中的XHTML 都帮忙静态类型检查。比如:

JavaScript

@dom def typo = { val myDiv = <div typoProperty="xx">content</div> myDiv.typoMethod() myDiv }

1
2
3
4
5
@dom def typo = {
  val myDiv = <div typoProperty="xx">content</div>
  myDiv.typoMethod()
  myDiv
}

由于上述代码有拼写错误,编写翻译器就可以报错:

JavaScript

typo.scala:23: value typoProperty is not a member of org.scalajs.dom.html.Div val myDiv = <div typoProperty="xx">content</div> ^ typo.scala:24: value typoMethod is not a member of org.scalajs.dom.html.Div myDiv.typoMethod() ^

1
2
3
4
5
6
typo.scala:23: value typoProperty is not a member of org.scalajs.dom.html.Div
        val myDiv = <div typoProperty="xx">content</div>
                     ^
typo.scala:24: value typoMethod is not a member of org.scalajs.dom.html.Div
        myDiv.typoMethod()
              ^

有关小编:ThoughtWorks

图片 8

ThoughtWorks是一家中外IT咨询集团,追求优异软件品质,致力于科学技术驱动商业变革。专长创设定制化软件出品,扶持顾客火速将概念转变为价值。同不时候为顾客提供顾客体验设计、技艺计谋咨询、协会转型等咨询服务。 个人主页 · 笔者的篇章 · 84 ·   

图片 9

内联CSS属性

style 属性设置内联样式时,style 的值是个字符串。举个例子:

JavaScript

@dom def invalidInlineStyle = { <div style="color: blue; typoStyleName: typoStyleValue"></div> }

1
2
3
@dom def invalidInlineStyle = {
  <div style="color: blue; typoStyleName: typoStyleValue"></div>
}

如上代码中设置的 typoStyleName 样式名写错了,但编写翻译器并从未报错。

要想让编写翻译器能检查内联样式,能够用 style: 前缀而不用 style 属性。比如:

JavaScript

@dom def invalidInlineStyle = { <div style:color="blue" style:typoStyleName="typoStyleValue"></div> }

1
2
3
@dom def invalidInlineStyle = {
  <div style:color="blue" style:typoStyleName="typoStyleValue"></div>
}

那么编写翻译器就能够报错:

JavaScript

typo.scala:28: value typoStyleName is not a member of org.scalajs.dom.raw.CSSStyleDeclaration <div style:color="blue" style:typoStyleName="typoStyleValue"></div> ^

1
2
3
typo.scala:28: value typoStyleName is not a member of org.scalajs.dom.raw.CSSStyleDeclaration
        <div style:color="blue" style:typoStyleName="typoStyleValue"></div>
         ^

那样一来,能够在编写制定代码时就知晓属性有未有写对。不像原生JavaScript / HTML / CSS那样,碰着bug也查不出去。

自定义属性

即便您要求绕开对质量的项目检查,以便为HTML成分增添定制数据,你能够属性加上 data: 前缀,比如:

JavaScript

@dom def myCustomDiv = { <div data:customAttributeName="attributeValue"></div> }

1
2
3
@dom def myCustomDiv = {
  <div data:customAttributeName="attributeValue"></div>
}

那样一来Scala编译器就不会报错了。

结论

正文的后生可畏体化DEMO请访谈 ScalaFiddle。

从那几个示例能够观察,Binding.scala 一方面支持完全的XHTML ,能够从高保真HTML 原型无缝移植到动态网页中,开荒进程极为流畅。其他方面,Binding.scala 能够在编写翻译时静态检查XHTML中冒出语法错误和语义错误,进而防止bug 。

以下表格相比较了ReactJS和Binding.scala对HTML语法的扶植程度:

ReactJS Binding.scala
是否支持HTML语法? 残缺支持
是否支持标准的style属性? 不支持,必须改用 JSON 语法
是否支持标准的class属性? 不支持,必须改用className
是否支持标准的for属性? 不支持,必须改用htmlFor
是否支持HTML注释? 不支持
是否兼容原生DOM操作? 不兼容
是否兼容jQuery? 不兼容
能否在编译时检查出错误? 不能

自个儿就要下后生可畏篇文章中牵线 Binding.scala 如何兑现服务器发送央求并在页面彰显结果的流程。

有关链接

  • Binding.scala 项目主页
  • Binding.scala • TodoMVC 项目主页
  • Binding.scala • TodoMVC DEMO
  • Binding.scala • TodoMVC 以外的其余DEMO
  • JavaScript 到 Scala.js 移植指南
  • Scala.js 项目主页
  • Scala API 参照他事他说加以考查文书档案
  • Scala.js API 参谋文书档案
  • Scala.js DOM API 参照他事他说加以考查文书档案
  • Binding.scala快捷上手指南
  • Binding.scala API参谋文档
  • 损伤了复用性,不合乎复杂的前端项目。Binding.scala 的 Gitter 聊天室

    1 赞 1 收藏 1 评论

有关小编:ThoughtWorks

图片 10

ThoughtWorks是一家中外IT咨询公司,追求卓越软件质量,致力于科学和技术驱动商业变革。专长营造定制化软件出品,扶持客商高效将定义转变为价值。同不常间为客户提供客商体验设计、技能战略咨询、组织转型等咨询服务。 个人主页 · 我的作品 · 84 ·   

图片 11

本文由澳门新萄京官方网站发布于澳门新萄京赌场网址,转载请注明出处:损伤了复用性,不合乎复杂的前端项目

关键词: