关于React的一些你应该知道的东西
亲爱的读者们!
这本书假设你已经知道什么是React以及其能解决你什么样的问题,你或许已经用它写过中小型的应用,如果你想要提高自己的技能,本书能为你解答你未能解决的问题。
你应该知道React是由Facebook和几百位javaScript的社区贡献者维护和开发的,由于采用了虚拟DOM的技术使得它运行起来非常快,目前React是github上创建用户UI最流行的库之一。
React 使用JSX语法,用一种javaScript标记型语法,这种语法需要你以一种组件化的思维思考并且有很多很酷的特性,比如能够使我们写通用的应用(一套代码,能同时运行到服务端和客户端环境)服务端的渲染。
本教程需要你知道如何在node的环境下使用终端命令安装和运行NPM包。
所有的式例采用ES6(es2015),你应该能够看懂和理解。
在第一个章节里。将会介绍一些基本的概念,这对于一个新手弄明白Reat非常有意义,同时对一个熟练React的人高效地使用React也是非常重要。
-命令式编程和声明式编程之间的区别
-什么是React组建及它的实例,以及React 如何使用元素控制UI界面
-React如何改变编译web应用的方式,执行关注点分离新的概念,和这种不受欢迎的设计选择背后的原因
-为什么开发者感到JavaScript不给力以及使用React的生态系统如何避免一些常见的错误
声明式编程
阅读React文档或者关于React的博客,你一定看到声明式这个单词,
实际上,React如此强大的一个原因是它实行了声明式编程范式,因此掌握React,理解声明式编程和与命令式编程的不同很重要,他们的不同之处最简单的方法是认为:命令式编程是描述如何去做事情,声明式编程是描述你想要的是什么
举个简单的例子,假设我们想让一个数组里的字符转小写。
toLowerCase(['FOO', 'BAR']) => ['foo', 'bar']
我们用命令式编程风格实现,像下面这样:
const toLowerCase = input => {
const ouput = []
for (let i = 0; i < input.length; i++) {
ouput.push(input[i].toLowerCase())
}
return ouput;
}
首先,创建一个空的数组,然后,通过遍历每个数组的元素转化成小写,最后,返回结果。
用声明式编程风格实现,像下面这样:
const toLowerCase = input => input.map(value => value.toLowerCase())
map利用当前的数组创建了一个新数组,新数组里的每个元素都是经过了传入map的函数(value => value.toLowerCase()))的处理
这两种编程风格的不同:前面的例子,不优雅并且很难理解,后一种,简单容易阅读,在大型的项目里面,维护起来后者更方便,
另外一个值得一提的是声明式的既不需要声明变量也不需要在执行后保持最新的值,不会改变外部状态。
最后再举个例子看看React中的声明式编程式怎样的,我们会以最web开发中常见的需求:“显示地图用一个标记点” 展开来讲,像下面这样
const map = new google.maps.Map(document.getElementById('map'), { zoom: 4, center: myLatLng, })
const marker = new google.maps.Marker({ position: myLatLng, title: 'Hello World!', })
marker.setMap(map)
明显的命令式,创建map、marker和附加到map上,
React组建是如何显示map在页面上的呢?
<Gmaps zoom={4} center={myLatLng}>
<Marker position={myLatLng} title="Hello World!" />
</Gmaps>
使用声明式编程,开发者只需要描述想要的是什么,不需要罗列出具体的步骤,实际情况是它使用方便,代码更优雅,明显减少bug,更易维护。
React 元素
本书假定读者熟悉组建及其实例,如果你想高效地使用React还有一种对象读者也应该知道:Element,无论你是调用creatClass,继承Component 或者简单地声明无状态的函数,都会创建组建,react在运行时管理组建的所有实例,在某个时间点上可能有相同组建的一个以上的实例在内存中。
如前所述,React尊从声明式编程,不需要告诉它怎样和DOM交互,只需声明你需要在页面上显示什么,其他的React已经帮你做好了,
你可能有这样的体验,许多其他的UI库用的是相反的方式,他们不处理保持界面更新,而是手动处理创建和销毁DOM元素,
为了控制UI流,React使用特殊的类型对象,叫做elements, 它描述显示在屏幕上的东西,这种不可变的对象比起组建和组建的实例来讲更简单并且只是显示界面。
下面是一个elements的例子,
{
type: Title,
props: { color: 'red', children: 'Hello, Title!' }
}
elements 有一个type和其他的属性,type是最重要的属性,它告诉elements,如何处理自身,实际上,如果type是一个string,elements代表一个DOM 节点,如果是一个函数则代表一个组建
有一个children是可选的,代表这个elements的子elements,
elements和组建能过被相互嵌套,
{
type: Title,
props: {
color: 'red',
children: {
type: 'h1',
props: {
children: 'Hello, H1!'
}
}
}
}
当type为函数时,react递归执行,直到返回DOM node,这一处理过程称为reconciliation,被使用在React DOM和 React native中创建用户界面根据各自的平台。
清掉一切
对于第一次使用React的开发者来说并不是件容易的事,它需要开放的思维
其实,React尝试改变我们构建用户界面的方式,用一种打破被认为是最佳实践的方式。
在过去的二十年里,我们已经知道了关注点分离是很重要的,过去是从将逻辑从模版中分离这个角度理解它的,具体的实现是将Javascipt和html代码写到不同的文件,(不要写"行内样式"(inline style)和"行内脚本"(inline script))
为了实践上面所说的分离关注,多种模版解决方案被创建出来,慢慢地,你会发现,许多时候这种分离只是一种错觉,实际情况是Javascipt和html代码紧密耦合在一起,
让我们来看一个模版的例子:
{{#items}}
{{#first}}
<li><strong>{{name}}</strong></li>
{{/first}}
{{#link}}
<li><a href="{{url}}">{{name}}</a></li>
{{/link}}
{{/items}}
这段代码是从Mustache(是一个 logic-less (轻逻辑)模板解析引擎)的官网上摘抄下来的,第一行告诉Mustache循环集合items,在循环的内部,如果first和link存在则渲染html标签,变量封装在双大花括号里,如果你的应用只是显示一些变量,模版库是一种好的选择,但是当面临复杂的数据结构则并适合,
其实模版系统和它的(DSL)领域特定语言提供子集的特性,这些模版只是提供特定的功能而不是达到同样高度的完整性,正如上面的例子所示,模版展示的信息高度依赖从逻辑层获取的数据模型,
另外,通过模版更新用户界面,Javascipt与DOM 元素的交互渲染即使分离的文件已经加载完成,
同样的问题也出现在样式,样式被定义在不同的文件里,被模版引用,CSS选择器遵从标记语言的结构,因此只要改变一个就会改变其他的,样式是一种耦合定义的。
这也是为什么典型的关注点分离最后成为技术的分离,这当然不是一件坏事,但是它没有解决任何实际的问题,而react则把模版放一边(专门用来处理逻辑),这样做的原因是react提倡构建应用使用小的积木(叫做组建)组合起来,这个框架不会告诉你如何关注点分离是因为只有开发者自己知道和决定应用的边界,
基于组建的开发大大地改变了编写web应用的方式,关注点分离的概念渐渐地被现代框架所取代,这种范式被React实现并不是一个新的事物,也不是被它的创建者发明出来的,只是React使它成为主流,更重要的是,使它容易理解和受欢迎,下面是React 组建的渲染例子
render() {
<button style={{ color: 'red' }} onClick={this.handleClick}>
</button>
return (Click me!)
我们会感觉这种写法看起来有些奇怪,不要着急,用惯了就能发现它的便利,
使用js写的逻辑和模版不但有助于关注点分离,而且还对复杂的用户界面强大和表现力,
网友评论