React特点
- 数据驱动页面(vm),是单向数据流
- 操作虚拟DOM,而不是真实DOM,避免重绘重排
- Diffing算法(key)
npx create-react-app my-app
虚拟DOM
- 渲染页面时,在中间添加了一层虚拟DOM(只有第一次渲染效率不高)
- 虚拟DOM本质是Object
- 虚拟DOM上的属性很少
- 最终都会转为真实DOM
key
- key是虚拟DOM对象的标识
- 当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】,
- 随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较
- 旧虚拟DOM中找到了与新虚拟DOM相同的key:
- 若虚拟DOM中内容没变, 直接使用之前的真实DOM
- 若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
- 旧虚拟DOM中未找到与新虚拟DOM相同的key:
- 根据数据创建新的真实DOM,随后渲染到到页面
不推荐使用index作为key
- 性能问题:
- 前插时会影响性能,会把所有的dom都重新渲染一遍
- 使用了指定的key,就只渲染对应的
- 数据错乱
- 前插时,如果内部还有子结点,会导致数据错乱
- 使用了指定的key,数据则会一一对应
jsx规范
-
jsx:是一种语法糖,需要通过babel转为createElement方式
-
写法改变:
-
在jsx里可以写 js 表达式,但必须写在
{}
内表达式:能拿变量接收到
const VDOM = ( <ul> { data.map((item,index)=>{ return <li key={index}>{item}</li> }) } </ul> )
-
class
->className
-
内联样式:写在对象
{}
中,因为是表达式,所以还需要一层{}
style={{color:red}}
-
样式如果有多个单词,需要使用小驼峰形式
style={{fontSize:'29px'}}
-
事件绑定也需要使用小驼峰形式
-
-
只能有一个根标签
-
标签小写识别为html标签
-
标签大驼峰式识别为组件
-
className写法:
-
三元表达式
<i className={value.checked ? "active" : null} />
-
函数
getStyle() { return this.value.checkedr ? 'active' : ''; } //... <i className={this.getStyle()} />
-
字符串拼接
<i className={`check-radio ${ value.checked ?"active":null}`} />
-
事件
-
React采用小驼峰写法封装了所有事件,并使用事件委托定义在了其副元素上
onClick={demo}
-
回调函数:
{demo()}
写法会被立刻调用- 注意:事件触发时,调用对象为window
-
React没有双向绑定的概念,默认的事件写法叫非受控组件,带有绑定的叫受控组件
-
处理表单时,设置了checked 属性就必须设置 onChange 事件
this指向
show(){
console.log(this);
}
render() {
return <>
//点击后this为undefined
<h1 onClick={this.show}>Hello</h1>
</>
}
原因:
- 通过onclick点击时,调用对象是window
- 又因为类中自动调用严格模式,所以会返回undefined
三种解决方法:
-
定义成箭头函数(推荐)
show=()=>{ console.log(this);//this指向所在作用域,所在类 }
-
使用函数包裹一下
onClick={()=>this.show()}
-
bind
- bind会生成新函数,并绑定this
constructor(props){ super() this.show=this.show.bind(this) }
事件绑定的两种写法
-
柯里化(每个参数只有一个)
show = (type) => { return function (e) { console.log(type,e.target.value); } }
<input onChange={this.show("username")} type="text"></input>
-
不用柯里化(接受多个参数)
show = (e,type) => { console.log(type,e.target.value); }
<input onChange={e=>this.show(e,"username")} type="text"></input>