原文连接 : Getting to Grips with React (as an Angular developer)
原文做者 : DAVE CEDDIA
译者 : 李林璞(web前端领域)
译者注:翻译若有疏漏,欢迎指出!感谢!转载请保留此头部。html
你是一个对 React 感兴趣的 Angular 开发者吗?不用担忧,这真的不会让你成为一个背叛者或其余什么,真的。前端
或许你早就已经开始玩 React 了:阅读了 Facebook 的官方教程,建立了一些组件...react
也或许你正处于我几个月前处于的境地:对React彻底没有经验,除了据说过它有多快,它有个虚拟 DOM 的概念,单向绑定,和一些像 Flux , Redux 和 Reflux 之类乱七八糟的东西。git
在接下来一系列的文章里我将尝试帮助你将你辛苦习来的 “Angular” 主义知识应用到 React 当中。github
在 Angular 里,你可能已经习惯去编写各类指令 directive
。若是你是按照流行的规范去编码的话,相信你程序的各个部分都是由一个或多个指令构建而成,并处处都使用了隔离的做用域 scope
(若是这听起来很熟悉但并不像你所作的话,或许你能够阅读一下将scope转化为controllerAs)。web
React 有着相同的概念:编写组件 component
。将你的程序按功能拆分红组件块,并尽量让每一个组件块保持独立和可复用性。事实上,这个想法并非 React 或 Angular 首创的 - 它只是一种很棒的软件开发实践方式。尽量写一些简短并具有可复用性的代码(函数,组件,指令,随便你怎么称呼它们)。app
一个关键的差异在于 React 里 全部东西都是组件 ,从根节点到下面全部。Angular 让你使用 ng-controller
去混合和匹配全部指令,并在以后特定地路由出各自的指令和模板... React 让这个事情变简单了一点。全部东西都是组件,页面,按钮甚至是路由,咱们随后会讲到这些。less
好了,因此说 React 的“组件”是相似于“指令”的。那么它的代码看起来是怎样的呢?函数
下面是一个展现歌曲名字的 Angular 指令:工具
angular.module('demo', []).directive('songName', function() { return { scope: { song: '=' }, restrict: 'E', template: '<span class="song-name">{{ ctrl.song.name }}</span>', controller: function() {}, controllerAs: 'ctrl', bindToController: true }; });
接下来是用 React 写的相同功能的组件:
var SongName = React.createClass({ propTypes: { song: React.PropTypes.object.isRequired }, render: function() { return <span className='song-name'>{this.props.song.name}</span>; } });
你立刻就能够发现一些类似之处:它们都指望获得一个 song
对象,并都彷佛有各类各样的模板。
一些不一样之处在于:React 相对 Angular 有着更少的代码。我敢说...更简洁了不是吗?React 里,指望的参数(song
)有着某种类型验证,而且 HTML 没有引号!
事实上那个看上去没加引号的 HTML 并非真正的 HTML。(等下就会讲到)
React.createClass
和 angular.directive
相似 - 它建立了一个组件类。这个组件 必须 有一个 render
方法,propTypes
是一个可选对象,但最好把它写上。
仍是要对得起 Angular ,它的1.5版本其实介绍了一个 component
方法来缩短指令的长度,因此上面的指令能够简写成下面这样:
angular.module('demo', []).component('songName', { bindings: { song: '=' }, template: '<span class="song-name">{{ $ctrl.song.name }}</span>' });
更简单的写法。它甚至默认没有控制器!我推荐阅读一下Todd Motto的关于组件方法的文章并在你的代码里尝试一下。
但它仍是没有 propTypes
...
propTypes
是一个验证组件所需参数的方法。你能够把个别参数标记为“必需的”或“可选的”(默认它们都是可选的),把它想象成类型检测吧。
下面是真正很酷的部分:若是你指定了propTypes
并说明一个参数是必需的(像上面那样),而后你忘记把它传进来,你就会在控制台获得一个提示信息。
比起 Angular 这真的太棒了!当你忘记给指令传参时你就不再怕莫名其妙地报错了。
什么是 "prop" ?它其实是 “property” 的简写(感谢 React 的开发者,让咱们不再用打出 this.properties
或者 this.propertyTypes
了)。
你能够把 props
看做是传给组件的属性。就像在指令里,你会在 HTML 元素里传递属性同样 - props
会在 JSX 元素里被看成属性传递。
下面是 Angular 里指令的使用方法:
// Notice how you have to mentally translate 'songName' to 'song-name'? <song-name song="ctrl.song"></song-name>
而后下面是 React 里组件的使用方法:
// Notice how you DON'T need to mentally translate SongName to anything? <SongName song={theSong}/>
全部没有子元素的标签在 JSX 里均可以自终止。
但让咱们先花几分钟来说讲 JSX吧...
在我对 React 了解很少的时候,我知道它是把 HTML 和 JS 混合起来的,而后我就想这样作真的很 丑陋 啊。我意思是,这对于最佳实践的思考来讲已经不少年不会这么写了不是吗?从那段使用 jQuery 的黑暗日子开始,咱们就已经知道在 JS 里写 HTML 元素是一件很取巧并且开发体验至关糟糕的事情,因此为何 React 会再次犯一样的错误呢?
因此,这里有两件事情须要搞清楚:
那并非字符串。
你注意到它是怎么作到不给 “HTML” 加引号的吗?那是由于它并非 HTML。不加引号也并非一种语法糖,React 是不会将那个东西转换成 HTML 的。
那并非HTML。
那是 JSX 。我知道它长得很像 HTML ,立刻你可能会想:“JSX嘛 ...只是对 HTML 作了一些细微的改变而后换了个名字而已”,好吧,你也能够那么说。我倒以为它是给咱们提供了一种用函数调用去建立 DOM 元素的语法糖。
建立 DOM 元素的函数调用?是的,看看下面的代码:
// This JSX... <span className='song-name'>{this.props.song.name}</span> // Compiles to this function call: React.createElement('span', {className: 'song-name'}, this.props.song.name); // React.createElement('tagName', props, children);
看起来还挺有道理的,不是吗? HTML 建立嵌套的 DOM 节点,那咱们就用嵌套的函数调用替代了嵌套的 DOM 节点...
// This is valid JSX: <div> <span className='greeting'> <strong>Hello</strong> <strong>World</strong> </span> </div> // ...which compiles to this call: React.createElement('div', null, React.createElement('span', {className: 'greeting'}, React.createElement('strong', null, 'Hello'), React.createElement('strong', null, 'World') ));
实现上来讲,这些 React.createElement
方法并无建立真正的 DOM 节点,它们建立了虚拟的 DOM 节点。
因此说咱们并非把 HTML 字符串写到 Javascript 里的!
但代码逻辑始终仍是和表现层混合起来的!那可不能算对!这么多年的软件开发实践告诉咱们这样作是很很差的。放心,如今只是还没作完呢,你并无把视图和逻辑混合起来。
我认为这是一种相似“货物崇拜”的东西,咱们常常在没真正搞清楚为何的状况下去赞同和执行。有不少很好的理由去说明为何须要把逻辑和视图层给分离开,但当你回头再看会发现一样也有不少很好的理由去合并它们。
或许你已经写过一些带有控制器和分离的模板文件的 Angular 指令了是吧?
告诉我你有多么常常在看不到或者没法修改控制器的状况下去到模板文件里去修改一些东西?又有多么常常在没有接触到模板的状况下去修改控制器?
这些看上去算是你对关注点的分离吗?
咱们喜欢把 JS 和 HTML 分离到不一样的文件里去让它们“关注点分离”,可复用性咱们来了!
但其实它们不多会那样工做。一个指令的控制器和模板一般会牢牢关联在一块儿,因此很天然地,它们就像是硬币的两面。把代码分离到不一样的文件里并不会自动致使关注点分离。
若是你还没注意到的话,其实我是想尝试经过上面的说法告诉你模板和逻辑控制实际上是能够共存在一个文件里的,并且这样作或许看起来更有道理一些。
我敢打赌你仍是充满疑惑。正常,我曾经也是的。
我的来讲,我发现从长期以来信服的理论当中跳出来到一个看似彻底相反的位置确实是一件至关困难的事情。我试过亲自去尝试那么作并证实给本身看这个新方法并非那么糟糕。
但愿你也能够去作一样的事情,只须要一点点时间。去尝试一下 React 的官方教程(不须要什么乱七八糟的工具 - 下载并运行他们的服务就能够开始写代码了),或者也能够试一下个人三分钟输出 Hello World 教程(不须要编译哦!)。
或许就能够像我作的那样,你会发现写 React 组件确实颇有意思。又或者你会发现 React 并非你想要的东西,但至少你尝试并验证过了。
若是你决定使用它了,那就回来这儿吧,我等你!