[译] 逐渐去掌握 React(作为一名 Angular 开发者)
你是一个对 React 感兴趣的 Angular 开发者吗?不用担心,这真的不会让你成为一个背叛者或其他什么,真的。 或许你早就已经开始玩 React 了:阅读了 Facebook 的官方教程,创建了一些组件... 也或许你正处于我几个月前处于的境地:对React完全没有经验,除了听说过它有多快,它有个虚拟 DOM 的概念,单向绑定,和一些像 Flux,Redux 和 Reflux 之类乱七八糟的东西。 在接下来一系列的文章里我将尝试帮助你将你辛苦习来的 “Angular” 主义知识应用到 React 当中。
在 Angular 里,你可能已经习惯去编写各种指令 React 有着相同的概念:编写组件 一个关键的差别在于 React 里 所有东西都是组件 ,从根节点到下面所有。Angular 让你使用 好了,所以说 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>; } }); 你马上就可以发现一些相似之处:它们都期望得到一个 一些不同之处在于:React 相对 Angular 有着更少的代码。我敢说...更简洁了不是吗?React 里,期望的参数( 事实上那个看上去没加引号的 HTML 并不是真正的 HTML。(等下就会讲到)
还是要对得起 Angular ,它的1.5版本其实介绍了一个 angular.module('demo',[]).component('songName',{ bindings: { song: '=' },template: '<span class="song-name">{{ $ctrl.song.name }}</span>' }); 更简单的写法。它甚至默认没有控制器!我推荐阅读一下Todd Motto的关于组件方法的文章并在你的代码里尝试一下。 但它还是没有 propTypes
下面是真正很酷的部分:如果你指定了 比起 Angular 这真的太棒了!当你忘记给指令传参时你就再也不怕莫名其妙地报错了。 props什么是 "prop" ?它实际上是 “property” 的简写(感谢 React 的开发者,让我们再也不用打出 你可以把 使用组件下面是 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吧... JS里的HTML?!在我对 React 了解不多的时候,我知道它是把 HTML 和 JS 混合起来的,然后我就想这样做真的很 丑陋 啊。我意思是,这对于最佳实践的思考来说已经很多年不会这么写了不是吗?从那段使用 jQuery 的黑暗日子开始,我们就已经知道在 JS 里写 HTML 元素是一件很取巧而且开发体验相当糟糕的事情,所以为什么 React 会再次犯同样的错误呢? 所以,这里有两件事情需要搞清楚:
JSX 编译成 Javascript创建 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','Hello'),'World') )); 实现上来说,这些 但...关注点的分离!所以说我们并不是把 HTML 字符串写到 Javascript 里的! 但代码逻辑始终还是和表现层混合起来的!那可不能算对!这么多年的软件开发实践告诉我们这样做是很不好的。放心,现在只是还没做完呢,你并没有把视图和逻辑混合起来。 我认为这是一种类似“货物崇拜”的东西,我们经常在没真正搞清楚为什么的情况下去赞同和执行。有很多很好的理由去说明为什么需要把逻辑和视图层给分离开,但当你回头再看会发现同样也有很多很好的理由去合并它们。 或许你已经写过一些带有控制器和分离的模板文件的 Angular 指令了是吧? 告诉我你有多么经常在看不到或者无法修改控制器的情况下去到模板文件里去修改一些东西?又有多么经常在没有接触到模板的情况下去修改控制器? 这些看上去算是你对关注点的分离吗? 我们喜欢把 JS 和 HTML 分离到不同的文件里去让它们“关注点分离”,可复用性我们来了! 但其实它们很少会那样工作。一个指令的控制器和模板通常会紧紧关联在一起,所以很自然地,它们就像是硬币的两面。把代码分离到不同的文件里并不会自动导致关注点分离。 如果你还没注意到的话,其实我是想尝试通过上面的说法告诉你模板和逻辑控制其实是可以共存在一个文件里的,而且这样做或许看起来更有道理一些。 试试看我敢打赌你还是充满疑惑。正常,我曾经也是的。 个人来说,我发现从长期以来信服的理论当中跳出来到一个看似完全相反的位置确实是一件相当困难的事情。我试过亲自去尝试那么做并证明给自己看这个新方法并不是那么糟糕。 希望你也可以去做同样的事情,只需要一点点时间。去尝试一下 React 的官方教程(不需要什么乱七八糟的工具 - 下载并运行他们的服务就可以开始写代码了),或者也可以试一下我的三分钟输出 Hello World 教程(不需要编译哦!)。 或许就可以像我做的那样,你会发现写 React 组件确实很有意思。又或者你会发现 React 并不是你想要的东西,但至少你尝试并验证过了。 如果你决定使用它了,那就回来这儿吧,我等你! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |