React自学笔记(一)
JSX(需要babeljs转译)
看起来像html,但是它其实是JS,他并不是标准的js语法, 在webpack打包的时候,会把jsx语法转成纯的js代码,所以在浏览器就可以运行。
什么叫React元素
是react应用的最小单位,它描述了你在屏幕上看到的内容 react元素的本质是一个普通的JS对象, reactDOM会保证浏览器中的DOM和你的react元素一致。
JSX表达式
表达式就是变量和操作符的结合,可以计算结果
如:1+2;let a=1;a+2 。
在JSX中可以任意使用表达式,表达式要放在大括号内。
JSX更像js,而非js
React 如何区分是JSX元素还是表达式呢?
以> 开头的就是JSX元素; {}就是表达式 等同于Vue中的{{}}
给JSX赋值时,尽量避免使用JS关键字。如果一个React元素属性名是class的话,要改名为className。如果是关键字的话 for,要改名为htmlFor
Each child in a list should have a unique “key” prop. (Key值作用)
当map的时候,是把一个字符串数组映射为一个li的react元素数组 在列表中的每一个子元素都应该有一个唯一的key属性。
原因是:
为了高效的dom diff(dom比较)
let name = ['zhangsan','lisi','wangwu']
let element = name.map(item=> {
return <li key="item">{item}</li>
})
ReactDOM.render(
<ul>{element}</ul>,
document.getElementById('root')
)
( 尽量复用老DOM)
key属性如果为映射中的index,新的DOM生成会删除老的DOM重新生成 domdiff 是新的DOM与老的DOM对比,只要key一样,类型一样,就是同一个DOM
注意: reactDOM.render并不是完全重建的,也是要进行dom diff的
react元素是不可变对象
要想修改react元素,则需要每次都创建一个新的react元素出来
react只会更新必要的部分
如果说新老的虚拟DOM是一样的,则不做任何操作
如何定义组件 和组件的属性
函数式组件 就是一个函数 接受一个属性对象,返回一个react元素。
类组件 就是一个类,需要有一个render方法,react方法需要返回一个并且仅能返回一个顶级React元素。
组件的渲染
React元素不但可以是DOM标签,还可以是用户自定义的组件
function Welcome1(props) {
return <h1>hello {props.name}</h1>
}
class Welcome2 extends React.Component {
constructor(props){
// this.props = props
super(props)
}
render() {
return <h1>hello {this.props.name}</h1>
}
}
let element = <Welcome2 name="title"/>
ReactDOM.render(element,document.getElementById('root'))
如何渲染函数组件?
1.封装函数组件的属性对象 props={name:‘title’}
2.把props传递给Welcome1这个函数,返回一个React元素
3.把这个react元素,也就是虚拟DOM渲染到真实DOM上
如何渲染类组件?
1.封装函数组件的属性对象 propS={name:‘title’}
2.new Welcome2(props); 创建Welcome2这个类的实例,传递props进去 this.props
3.调用实例的render方法,得到返回的react元素
4.把这个react元素,也就是虚拟DOM渲染到真实DOM上
1.不管类组件还是函数组件,首字母必须大写
react通过首字母来区分到底是自定义组件(大写)还是原生DOM组件(小写)
2.组件必须在使用的时候先定义
3.渲染方法只能返回一个顶级元素
4.props
props具有只读性
不管以何种方式声明组件,都不能修改自己的props
纯函数 1.不能改变输入的值;2.如果输入的值相同,输出结果也一定相同
如何 对属性进行类型校验?
组件封装好是给别人用的
react不知道怎么渲染对象
类型检查为什么是静态属性
什么时候静态,
什么时候动态
有些需要动态和静态都可以,那你会用哪个?
如果能用类的静态属性实现,就不要用实例属性。
1. 使用方便 Person.PropTypes
2.只会有一份,节约内存 实例属性:每new一个实例,都要创建一份。但是静态永远只有一份
能共用就共用,节约资源;不能共用才会每个一份
class Person extends React.Component{
static defaultProps={
name: '默认名字'
}
static propTypes = {
name: PropTypes.string.isRequired, //name是一个字符串类型的必填字段
gender:PropTypes.oneOf(['male','female']), //枚举值
hobby: PropTypes.arrayOf(PropTypes.string), //字符串的数组
position:PropTypes.shape({ //position的值是一个对象 key x y 值是number
x:PropTypes.number,
y:PropTypes.number
}),
//属性对象 属性名称 组件名称 age是设置了一个函数,这是一个自定义的校验器
age(props,propName,componentName) {
let age = props[propName]
if(age < 0||age>120){
throw new Error('报错')
}
}
}
render(){
let { name,age,gender,hobby,position,friends } = this.props
return (
<table>
<thead>
<tr>
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
<td>爱好</td>
<td>位置</td>
<td>爱好</td>
</tr>
</thead>
<tbody>
<tr>
<td>{name}</td>
<td>{age}</td>
<td>{gender}</td>
<td>{hobby.join(',')}</td>
<td>{`x:${position.x},y:${position.y}`}</td>
</tr>
</tbody>
</table>
)
}
}
let props = {
name: 'xixi',
age: 80,
gender:'male',
hobby:['smoking','drinking'],
position:{x:10, y:10}
}
// let element = <Person {...props}/>
let componentInstance = new Person(props)
let propTypes = Person.propTypes;
if(propTypes.name === PropTypes.string.isRequired) {
if(!props.name) {
throw new Error('baocuo')
}
}
ReactDOM.render(element,document.getElementById('root'))