前天趁着双十一不到半价购入了高程4,到手就翻了200多页,写的确实比上一版好多了,删减了很多没有必要的内容,又要掀起一波JavaScript
的新高潮了。
话说从夏天开始折腾起React.js
之后,一直没闲着,有事没事就看两眼和搜搜React
的相关信息。互联网上的宝藏还真是多,React.js小书就是这样一个短小精悍却很实用的教程,带着读者自己写出来了React
和React-redux
,借此加深对于React
的理解。
作者是胡子大哈,点开知乎一看,签名是本人已经永久退出知乎;React.js小书的链接的域名部分是http://huziketang.mangojuice.top/,点进去是一个胡子课堂,但是链接都已经失效,没有实质内容;点开主域名http://www.mangojuice.top/一看,是一个没有内容的“HuoLuoBo的博客”。从React小书的内容来看,请了几位大厂的工程师来为这本小书提意见,可见这作者也是一名曾经的前端大佬。
不知道大佬这本书写于什么时候,但从安装React
那一节中可以看到,当时的React
界面与现在我用的React
(16版)有所不同,所以估计成书也有些年月了。不过考虑到前端日新月异的发展速度,可能实际时间也没多久。花了两天功夫仔细看完和敲完代码,把自己的一些感想和心得记录下来。
JSX
原理
兼听则明确实有道理。本来还只是朦胧的对JSX
有点感觉,这里作者直接指出一个DOM
元素的信息就是三个:标签名,属性,子元素,所以一个DOM
元素就可以拆解成为一个JavaScript
对象,类似于:
{
tag: 'div',
attrs: { className: 'box', id: 'content'},
children: [
{
tag: 'div',
arrts: { className: 'title' },
children: ['Hello']
},
{
tag: 'button',
attrs: null,
children: ['Click']
}
]
}
其中每一个元素又可以通过React.createElement()
来构建,这就是JSX
的本质。这样还有一大好处,就是把DOM
元素的信息与HTML
这个形式进行解绑,可以把信息渲染到各种媒介上,这也是为什么对于日常编写WEB
应用,除了有一个核心的React.js
库,还需要另外一个react-dom
库的原因。
一些小心得
记录一下里边提到的几个小要点
灵活控制props.children
的内容
在React
里,可以直接在组件标签内传入其他组件或者原生HTML
代码,在组件内部就可以通过props.children
来获取传入的内容,这个传入的内容实际上是一个数组,所以可以用数组索引来控制渲染哪一些,还可以把这些children
渲染在不同的地方,非常灵活。
dangerouslySetInnerHTML
属性
正常情况下,所有表达式在计算的时候如果最后是打印出来,都会被自动转义,React
不会允许直接插入HTML
内容,但是使用这个属性就可以,例子如下:
...
render () {
return (
<div
className='editor-wrapper' dangerouslySetInnerHTML={{__html: this.state.content}} />
)
}
...
要给这个属性一个对象,对象的__html
属性就是要渲染进去的内容,相当于innerHTML
,这个属性千万不要滥用,或者干脆说平时就压根别用。
利用第三方库prop-types
来进行类型验证
究竟props
传了什么玩意进来,有的时候就不好控制,因此React
提供了一个库,专门用于验证props
的类型。
用法是固定的在类里边配置一个静态属性,名称也是固定的,如下:
class Comment extends Component {
static propTypes = {
comment: PropTypes.object,
content: PropTypes.string.isRequired
}
......
}
propTypes
是一个对象,对象的属性名就是props
中传入的属性名,值是对应的类型,后边可以加上.isRequired
来强制必须传入该属性。
默认defaultProps
前边说了可以验证属性和设置,但即使做了验证也挡不住就是不给传,这个时候可以给props
设置默认值,也是通过一个特殊的静态变量:
class Comment extends Component {
static defaultProps = {
likedText: '取消',
unlikedText: '点赞'
}
......
}
这样如果props
中没有对应的属性的话,就会采用默认值,再也不用怕瞎传属性啦。
context
属性
这东西就像WEB
容器里的容器全局变量一样,绑一个东西就可以从另外一个地方取回来。不过React
的context
不像WEB
容器那么直接,而是要使用特殊的写法,还必须得搭配类型验证。先来看看如何设置context
:
class Comment extends Component {
//这是特定的变量名称,必须写这个,否则无法使用context特性
static childContextTypes = {
themeColor: PropTypes.string
}
//这是特定的方法名称,必须这么写。这个函数看着是get,实际上是将内容放入到context,并且再返回context
getChildContext () {
return { themeColor: this.state.themeColor }
}
......
}
和WEB
容器一样,在某个地方给设置上了属性和值,在其他的地方就能取出来,在其他的组件中取出来的方法也需要搭配类型验证,然后使用this.context.attrname
即可:
class Title extends Component {
static contextTypes = {
themeColor: PropTypes.string
}
render () {
return (
<h1 style={{ color: this.context.themeColor }}>React.js 小书标题</h1>
)
}
}
......
}
Redux
库实际上就是附着在context
上,不然你以为有什么魔法能够实现全局状态吗。
后记
亲自写完一个Redux
的实现之后,发现就是利用装饰器和函数式编程的特性,不断的将组件分离成无状态组件和依赖react
基础库之外,需要进行逻辑处理数据的组件,然后再通过高阶组件特性结合起来。对Redux
需要编写一个reducer
的特点也更加清晰了。虽然看上去React
要写的代码好像比原来使用Vue.js
要复杂一点,但相比之下数据的处理和流动非常清晰。
今天听说有了hook
之后,高阶组件也用的少了,不知道是什么套路,hook
我也要去学习一下才行。
最后再提一句,全面转向Markdown
来写博客真的太爽了。