这是学习react小书的第一个demo
demo1
changeLikeText中的DOM操作还有优化的空间。应该尽量减少这种手动DOM操作
demo2
优化了之前demo1中的DOM操作,每当setState中构造完新DOM元素后,就通过onStateChange告知外部插入新DOM元素然后删除旧的元素,页面就更新了,不需要手动更新页面了。
但是如果重新做一个如评论组件,就要重写一遍setState方法,就很麻烦
抽离出来一个类,帮助我们更好的做组件化.组件化可以更好的帮我们解决前端复用性问题,页面可以由这样的不同的组件组合、嵌套构成。
JSX
思考:把下面对象用JS对象表现一个DOM元素结构.
<ul class="suggestion" id="su">
<li class="cur">选项1</li>
<li>选项2</li>
<dl id="gg">
<dd>滴滴1</dd>
<dd>滴滴2</dd>
</dl>
</ul>
JS对象来表示:
{
tag:'ul',
attrs:{className:'suggestion',id:'su'},
children:[
{
tag:'li',
arrts:{className:'cur'},
children:['选项1']
},
{
tag:'li',
arrts:null,
children:['选项2']
},
{
tag:'dl',
arrts:{id:'gg'},
children:[
{
tag:'dd',
arrts:null,
children:['滴滴1']
},
{
tag:'dd',
arrts:null,
children:['滴滴2']
}
]
}
]
}
为什么要经过中间层渲染DOM?
- 当拿到一个表示UI的结构和对象后,不一定渲染在浏览器上.可能到canvas(react-canvas),手机App(react-app),但是通过react-xxx可以渲染到对应端上
- 当数据产生变化时,可以通过比较快的算法操作JS对象,不用直接操作页面上的DOM,就可以尽量少的减少浏览器重排,极大的优化性能.
要记住几个JSX的点:
- JSX 是 JavaScript 语言的一种语法扩展,长得像 HTML,但并不是 HTML。
- React.js 可以用 JSX 来描述你的组件长什么样的。
- JSX 在编译的时候会变成相应的 JavaScript 对象描述。
- react-dom 负责把这个用来描述 UI 信息的 JavaScript 对象变成 DOM 元素,并且渲染到页面上。
组件的render方法
React中一切皆组件,一般需要继承Component.一个组件类必须要实现一个render方法,render方法必须要返回一个JSX元素,这里必须要用一个外层JSX元素将内瓤包裹起来.返回并列多个JSX是不合法的
如
render () {
return (
<div>第一个</div>
<div>第二个</div>
)
}
必须用外层元素将内容进行包裹
render () {
return (
<div>
<div>第一个</div>
<div>第二个</div>
</div>
)
}
在render里可以根据不同条件返回不同JSX,也可以像JS对象那样自由赋值给变量或者作为参数传递
组件可以 自由的组合嵌套,并且构成组件树
理解组件树的概念,对后面理解数据是如何在组件树内自上往下流动过程很重要
事件监听
react不需要手动调用addEventListener进行事件监听,
,React.js帮我们封装好了一系列的on*
属性,必须使用驼峰命名法,并且on*
事件监听只能用在普通HTML标签上,不能用在组件标签上
event对象
react内部构建了event对象,与浏览器所提供的基本一致
由于react内部封装了浏览器原生的event,对外提供统一的API和属性
关于事件中的this
一般this指的是实例本身,但是在react里不是通过对象方法的方式调用(this.handleClick),而是直接通过函数调用(handleClick),所以事件监听函数内不能通过this获取到实例.
bind
如果想要获取实例,需要手动将实例方法bind到当前实例,再传入给React.js
bind在react事件监听中非常常见,bind不仅可以把事件监听方法中this绑定到当前组件实例上,还可以帮助我们在渲染列表元素时,将列表元素传入时间监听函数
组件的state和setState
react中state存储可变化状态
如isLiked:false
点赞和未点赞两种状态
isLiked存在state对象中,这个对象在构造函数里初始化.组件的render函数内,根据isLiked不同显示取消或点赞内容.并给button加了点击的事件监听
setState接收一个对象或者函数作为参数
handleClickOnLikeButton () {
this.setState((prevState) => {
return { count: 0 }
})
this.setState((prevState) => {
return { count: prevState.count + 1 } // 上一个 setState 的返回是 count 为 0,当前返回 1
})
this.setState((prevState) => {
return { count: prevState.count + 2 } // 上一个 setState 的返回是 count 为 1,当前返回 3
})
// 最后的结果是 this.state.count 为 3
}
利用上次setState结果进行计算
setState合并
虽然用了三次setState,但是React会先把同一个消息中的setState进行合并再重新渲染.
配置组件的props
- 为了使得组件的可定制性更强,在使用组件的时候,可以在标签上加属性来传入配置参数。
- 组件可以在内部通过 this.props 获取到配置参数,组件可以根据 props 的不同来确定自己的显示形态,达到可配置的效果。
- 可以通过给组件添加类属性 defaultProps 来配置默认参数。
- props 一旦传入,你就不可以在组件内部对它进行修改。但是你可以通过父组件主动重新渲染的方式来传入新的 props,从而达到更新的效果。
state vs props
二者职责非常分明:
state是让组件控制自己的状态,
props是让外部组件对自己进行配置
所以我们为了增强组件复用性,降低代码维护难度,
要尽可能的少用state,多用props
函数式组件
.函数式组件只能接受props而无法跟类组件一样在constructor里面初始化state,只能接受props和render方法的类组件
渲染列表数据
渲染存放JSX元素的数组
-往{}
放一个数组,React.js会帮你把数组里面一个个元素罗列并且渲染出来
继续优化
将jsx结构抽离成一个组件User,通过props把user数据作为组件的配置参数传进去
关于key:对于用表达式套数组罗列到页面上的元素,都要为每个元素加上 key 属性,这个 key 必须是每个元素唯一的标识。
标准做法是最好是后台数据返回的 id 作为列表元素的 key。
通过这个commentsDEMO使我复习了之前所学过的内容.,还有一些新的知识点:
- 做功能之前先理解分析需求,划分组件的基本原则:可复用,可维护性
- 受控组件如, <input /> 、<textarea />、<select />等元素value值如果收到React.js控制,那就是受控组件
- 组件间使用props通过父元素传递数据