澳门新浦京娱乐场网站-www.146.net-新浦京娱乐场官网
做最好的网站

澳门新浦京娱乐场网站不吻合复杂的前端项目,

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语法。

React.Component 损害了复用性?

2016/09/07 · 基础技能 · binding.scala, data-binding, React, scala.js

本文作者: 伯乐在线 - ThoughtWorks 。未经小编许可,禁止转发!
迎接加入伯乐在线 专栏撰稿人。

本种类的上一篇小说《为啥ReactJS不符合复杂的前端项目》列举了前端开荒中的各类痛点。本篇小说大校详细索求当中“复用性”痛点。大家将用原生 DHTML API 、 ReactJS 和 Binding.scala 完毕同三个需求复用的价签编辑器,然后比较四个标签编辑器哪个完结难度更低,哪个越来越好用。

缘何 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 随时增加和删除查改标签。假使用户增加和删除了标签,应该有某种机制布告页面包车型大巴其余一些。

背景介绍

2018年 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重新写了二个。代码量从近10000行降到了1000多行。

用这几个框架完结的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 框架猜对。

对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省穿梭太多事。

原生 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 成分,平日导致另一处代码受影响而其间景色错乱。

题目一: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 还要慢。

不协作原生DOM操作

除此以外,ReactJS等片段前端框架,会生成虚拟DOM。虚拟DOM不恐怕合作浏览器原生的DOM API ,导致和jQuery、D3等其余库合营时困难重重。例如ReactJS更新DOM对象时常常会毁掉掉jQuery控件。

Reddit众三人评论了那几个标题。他们尚未章程,只好弃用jQuery。小编司的某客户在用了ReactJS后也被迫用ReactJS重写了多量jQeury控件。

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> ); } }

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 用来在组件中传递消息。小编加入的某外国客户项目,平均各类组件大概供给传入七个回调函数。假诺档期的顺序嵌套深,创制网页时,平日供给把回调函数从最顶层的零部件一难得传入最尾部的机件,而当事件触发时,又需求一百年不遇把事件消息往外传。整个前端项目有超越四分之二代码都在这么绕圈子。

标题二: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中的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原型复制粘贴到代码中,整个网址就能够运转了。

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模板本性。

主题素材三: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中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()

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中的代码就能奉行壹次。

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() = { val tags = Vars("initial-tag-1", "initial-tag-2") <div> { tagPicker(tags).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 代替,网页就搞好了。

主题素材四: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咨询集团,追求优异软件品质,致力于科技(science and technology)驱动商业变革。擅长塑造定制化软件出品,援救客户高效将定义转化为价值。同不平日候为客户提供用户体验设计、技巧战略咨询、协会转型等咨询服务。 个人主页 · 小编的篇章 · 84 ·   

澳门新浦京娱乐场网站 4

其他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>
}

结论

本文相比较了差别本领栈中完毕和选取可复用的标签编辑器的难度。

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

Binding.scala 不评释“组件”之类的噱头,而以更轻便的“方法”为最小复用单位,让编制程序体验更加的顺畅,获得了越来越好的代码复用性。

本体系下一篇小说将比较 ReactJS 的杜撰 DOM 机制和 Binding.scala 的纯粹数据绑定机制,揭示 ReactJS 和 Binding.scala 相似用法背后掩藏的不等算法。

结论

固然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渲染框架。

他是对的,三个月后,现在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搭建新时代的前端能力栈。

内嵌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(一千) { 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 赞 1 收藏 评论

连带链接

  • 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 聊天室

强类型的 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

澳门新浦京娱乐场网站 6

ThoughtWorks是一家中外IT咨询公司,追求卓越软件性能,致力于科技驱动商业变革。擅长创设定制化软件出品,帮助客户高效将概念转化为价值。同一时候为客户提供用户体验设计、本事战术咨询、组织转型等咨询服务。 个人主页 · 小编的篇章 · 84 ·   

澳门新浦京娱乐场网站 7

至于小编:ThoughtWorks

澳门新浦京娱乐场网站 8

ThoughtWorks是一家中外IT咨询公司,追求优良软件品质,致力于科技(science and technology)驱动商业变革。擅长营造定制化软件出品,扶助客户快捷将定义转化为价值。同一时间为客户提供用户体验设计、才能战术咨询、组织转型等咨询服务。 个人主页 · 作者的小说 · 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

本文由澳门新浦京娱乐场网站发布于新浦京娱乐场官网,转载请注明出处:澳门新浦京娱乐场网站不吻合复杂的前端项目,