React 学习总结

官网地址https://facebook.github.io/react/docs/hello-world.html

JSX
  1. 可以在JSX中插入任何表达式,表达式需要用{}包裹,插入string,可以用""
  2. JSX分割成多行时,用()包裹起来,避免自动分号插入的陷阱
  3. JSX的属性采用驼峰式命名方式,如HTML中的class,JSX命名为className
  4. JSX避免XSS (cross-site-scripting) 攻击
  5. Babel通过调用React.createElement()来编译JSX,React必须在JSX代码的作用域内,参考:深入JSX
  6. React.createElement()创建的对象成为"React elements"
Rendering elements
  1. 元素是React应用的最小组成单位
  2. React的元素都是对象,创建廉价
  3. 通过ReactDOM.render()将React元素渲染成DOM元素,如ReactDOM.render(element, document.getElementById('root'));
  4. React elements是不可变( immutable)的,它代表某个时刻的UI改变UI的唯一方法就是创建一个新的element,然后把它传递给ReactDOM.render()
  5. React DOM会将新创建的element以及它的children和前一个element相比,只改变DOM中需要改变的部分来更新DOM
Components and Props
  1. Components将UI分割成独立的、可复用的、可单独思考的块
  2. 可以使用函数或者类定义类,分别称为Function Component(函数组件)和Class Component(类组件)
    Function Component:函数的入参只能是一个props对象,并且返回值是一个React元素
    Class Component:class继承React.Component,有一个render属性,render返回一个自定义组件、DOM组件或者null和false(null和false表明不需要渲染任何东西)
  3. 组件名的首个字母必须大写,如<Welcome />,用于区分自定义元素(首个字母大写)和DOM元素(首个字母小写)
  4. Component返回元素必须是一个根元素
  5. 纯函数:不改变输入值的函数,所有的组件必须是像纯函数一样,不改变props,props是只读的
  6. props默认值是"true"
  7. 可以使用……作为扩展操作来传递全部props对象,<Greeting {...props} />
  8. 在开口标签和闭合标签之间的内容是一种特殊的props:props.children
  9. props.children可以是混合的JSX、{}包裹的表达式或者函数
  10. false, null, undefined, and true都是有效孩子,不会被渲染,需要渲染时,使用{String(myVariable)}转化为string

6-10参考:深入JSX

State and Lifecycle
  1. 只有通过class方法定义的组件才有state属性
  2. 在class的constructor中,通过super(props)继承props,通过this.state = {……}来初始化state,只能通过setState来修改state
  3. state的修改是异步的,setState的callback函数可以传入两个参数:prevState, props(前一个状态、参数)this.setState((prevState, props) => {……})
  4. 会对setState返回的对象与state做一个merge操作
  5. 生命周期钩子
    componentDidMount():组件插入DOM(render()完成)时立刻执行
    componentWillUnmount():在组件即将从 DOM 中移除的时候立刻被调用
  6. 数据是从父组件到子组件单向流动的,可以将state作为props传递给子组件
Handling Events
  1. 命名事件方式不同:react->驼峰式(如onClick),DOM->小写(如onclick
  2. react传递函数(如:onClick={activateLasers})给事件处理器而不是string(如:onclick="activateLasers()"
  3. DOM调用return false来阻止默认行为,在react中,必须显示调用preventDefault()
  4. 注意JSX事件回调函数中的this,可以在constructor函数中绑定this.handleClick = this.handleClick.bind(this);或者handleClick = () => {……}或者button onClick={(e) => this.handleClick(e)}>,这样可以保证函数在实际使用时this不时undefined
Conditional Rendering
  1. 使用js的if 或者条件运算符 创建符合当前状态的元素
  2. 在JSX中插入表达式,&&操作符或者条件表达式编写内联的if逻辑
  3. 根据条件隐藏(返回null)或者显示组件
  4. 返回null,componentWillUpdate()componentDidUpdate()仍然会调用
    componentWillUpdate(object nextProps, object nextState):在接收到新的 props 或者 state 之前立刻调用
    componentDidUpdate(object prevProps, object prevState):在组件的更新已经同步到 DOM 中之后立刻被调用
Lists and Keys
  1. 创建elements列表时,key是一个特殊的属性
  2. react根据keys判断数组的items(项)是否改增删改
  3. 在兄弟节点中,该节点的key是独一无二的
  4. key应该是稳定的(例如不能是通过Math.random()生成)
  5. key是可预测的
  6. 添加一个ID属性或者对部分内容做哈希算法生成一个key,也可以将item在数组中的index作为key,确保index作为key时,这个数组不会重新排序,重新排序可能会很慢
  7. 在JSX中插入map(),生成子组件列表
    <pre>return ( <ul> { numbers.map((item, index) => { return <ListItem value={item} key={index} /> }) } </ul> )</pre>
Forms
  1. controlled component:一个input表单元素,如果它的value是由React控制的,我们就叫它controlled component
  2. form表单,如<input type="text" value={this.state.value} onChange={this.handleChange} />handleChange事件通过setState修改state的值,最后修改表单的值。表单的值由React控制
Lifting State Up

多个不同的component之间可能需要共享一个state,可将state提升至它们共同的最近的component祖先中(从上至下的数据流)

  1. state提升需要写一个共同的模板,可能需要写更多的代码
  2. 如果有些数据,既可以放在props又可以放在state中,那么建议不要放在state中
Composition vs Inheritance

react有强大的组合模型,在react建议使用组合来代替继承。新手在开发过程中经常遇到的,用组合代替继承的案例有:

  1. 组件的孩子节点事先不知道,通过props.children传入
  2. 组件预留一些“洞”(构成组件的部分模块开始未知,在使用时才知道),可以在使用时通过props(props的属性可以是component)传入这些模块(模块可能是组件)
  3. 一个组件是另外一个组件的特例时
JSX In Depth
  1. JSX是React.createElement(component, props, ...children)的语法糖
  2. 可以使用点记法标识一个JSX类型,如<MyComponents.DatePicker color="blue" />
  3. React元素不能是普通表达式,如果想使用普通表达式,可以先赋值给一个大写的变量,SpecificStory = components[props.storyType]; return <SpecificStory />
  4. React元素和自定义组件必须大写
Refs and the DOM

React提供了Refs(引用),用ref来获取组件或者HTML元素的引用,ref有一个属性是一个回调函数,回调函数入参是ref所在的HTML元素或者组件的引用,如<input type="text" ref={input => this.textInput = input} />

  1. refs使用场景:处理焦点、文本选择、媒体播放,触发强制性动画, 集成第三方DOM库
  2. 可以给DOM和类组件refs,函数组件没有实例,不适合使用ref属性
  3. 不要过度使用Refs
Uncontrolled Components
  1. 使用uncontrolled components,可以更容易集成React和非React代码,代码可能会更加轻量,但是会比较“脏”,尽量使用controlled components
  2. 在为form中每一个state变化写一个事件处理器不如使用ref获取DOM表单的值,对表单中的每一个元素,通过ref={(input) => this.input = input}来获取引用
  3. defaultValue指定初始值,在checkbox和radio中,使用defaultChecked,select使用defaultValue ,如<input defaultValue="Bob" …… />
Optimizing Performance
  1. 使用构建工具优化React应用

  2. 使用chrome的Timeline剖析组件

  3. virtual DOM:对被渲染成了UI的组件,React会构建和保存该组件返回的React元素,即virtual DOM

  4. shouldComponentUpdate:生命周期函数shouldComponentUpdate(nextProps, nextState)默认返回true,如果返回一个false,就不会重新渲染组件

  5. 组件渲染时,从上而下遍历该组件树

    should-component-update.png

    a:如果节点N1的shouldComponentUpdate方法返回false,N1及其子节点Ni(i可能是1、2、……)都不会重新渲染,Ni的shouldComponentUpdate也不会触发,停止遍历,否则执行b
    b:依次遍历子节点Ni,如果Ni不是叶子节点,对Ni执行a操作,否则执行c
    c:只有在Ni(叶子节点)的shouldComponentUpdate返回true并且React比较Ni改变前后的值不相等时候,才会重新渲染

  6. ** React.PureComponent**:可使用React.PureComponent来代替shouldComponentUpdate,React.PureComponent会做一个“浅比较”,所以对于props或者state修改前后,浅比较值依旧相等的情况,不要使用React.PureComponent

  7. 修改数组和对象,“浅比较”修改前后值依旧相等
    对数组:可使用concat和es6扩展语法,重新赋值如words: prevState.words.concat(['marklar'])words: [...prevState.words, 'marklar']
    对对象:可使用object.assign或者对象扩展属性重新赋值Object.assign({}, colormap, {right: 'blue'}){...colormap, right: 'blue'}

  8. Immutable.js是另一个解决方案,它通过结构化共享提供一个不变化、持久化的集合

Reconciliation

React使用Diffing Algorithm(差分算法)来考虑如何有效的修改UI来最大程度的匹配现在的树

  1. Diffing Algorithm的启发式设想前提
    a:两个不同的元素会生成两个不同的树
    b:开发者可以通过key暗示在不同的渲染中,哪个孩子元素是稳定不变的
  2. Diffing算法
    a:对于不同类型的根元素,React会销毁旧的树以及它的state,并且安装一颗新的树
    b:相同类型的DOM元素,保留相同的DOM元素,只更新已更改的部分属性(例如class、style属性等)
    c:相同类型的Component元素,新旧Component是同一个对象实例,维持一个state,React更新组件的props来匹配新的元素(componentWillReceiveProps()和componentWillUpdate()事件会执行)
    d:React会同时递归比较新旧孩子列表,一旦有不同的地方,React就会改变
    上述递归新旧孩子列表,如果节点只是挪动了位置,并没有改变,React不会意思到这一点,会造成不必要的销毁与重建,React可以使用key来比较修改前后的孩子节点。
  3. Tradeoffs
    a:这个算法不会试着匹配不同组件类型的子树,有相似输出的组件类型的组件之间可能更应该是同一个类型,事实也是这样
    b:key应该是稳定的,可预测的,和独一无二的
  4. 生命周期事件
    componentWillUnmount():在旧的DOM节点即将销毁时调用
    componentWillMount():即将安装新的DOM时调用
    componentDidMount():新的DOM安装完成是调用
    componentWillReceiveProps():组件即将更新props时调用
    componentWillUpdate():组件接收到新的props或者state但还没有render()时被执行

23. 高阶组件(未完待续)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容

  • 深入JSX date:20170412笔记原文其实JSX是React.createElement(componen...
    gaoer1938阅读 8,048评论 2 35
  • 最近看了一本关于学习方法论的书,强调了记笔记和坚持的重要性。这几天也刚好在学习React,所以我打算每天坚持一篇R...
    gaoer1938阅读 1,666评论 0 5
  • 本笔记基于React官方文档,当前React版本号为15.4.0。 1. 安装 1.1 尝试 开始之前可以先去co...
    Awey阅读 7,649评论 14 128
  • It's a common pattern in React to wrap a component in an ...
    jplyue阅读 3,252评论 0 2
  • 以下内容是我在学习和研究React时,对React的特性、重点和注意事项的提取、精练和总结,可以做为React特性...
    科研者阅读 8,219评论 2 21