真实DOM
DOM 全称是 Document Object Model,指的是文档对象模型,是HTML和XML文档的编程接口,是W3C指制定的标准;HTML DOM简单理解就是HTML被加载时,浏览器会创建这个文档对象模型。
DOM提供了对整个文档的访问模型,将文档作为一个树形结构,树的每个结点表示了一个HTML标签或标签内的文本项。DOM树结构精确地描述了HTML文档中标签间的相互关联性
虚拟DOM
一个普通的 JavaScript 对象,包含了 tag、props、children 三个属性
-
优点:
-
减少DOM 操作;可以将多次操作合并为一次操作;DOM diff 算法可以减少多余操作
-
比如需要添加1000个节点时,DOM是一个一个添加的,而虚拟DOM 可以一次添加1000 个
-
比如添加1000个节点,其实只有10个是新增的
-
-
跨平台 虚拟DOM 不仅可以变成DOM,还可以变成小程序,iOS应用,安卓应用,因为虚拟DOM上本质只有一个JS对象,
-
-
缺点:
需要额外的创建函数,如React.createElement(),可用JSX简化语法
<div>这种JSX语法就是简化了 React.createElement()的写法
React 组件传值
-
父给子传值靠
Props -
子组件时不能操作父组件里的数据,需要通过调用父组件的方法来实现;否则违背了React 当向数据流
eg:子组件通过调用父组件的方法修改数据
父组件
<ul ref={(ul) => { this.ul = ul; }} > {this.state.list.map((item, index) => ( // 子组件 <TestItem key={index.toString()} prefix={"React base"} content={item} suffix={"有默认值的"} index={index} // 删除时子组件不能操作数据,只能将删除方法传递给子组件,让其调用 deleteItem={this.deleteItem} list={this.state.list} ></TestItem> ))} </ul>子组件
render() { return ( <li onClick={this.handleClick}> {this.props.prefix} - {this.props.content} - {this.props.suffix} </li> ); } handleClick() { // 调用父组件的删除方法来删除,不能操作数据 this.props.deleteItem(this.props.index); } -
绑定
this尽量在构造函数中,这样会提高性能 -
使用PropTypes 来定义组件的值
使用PropTypes校验传递值
TestItem.propTypes = { content: PropTypes.string, index: PropTypes.number, deleteItem: PropTypes.func, prefix: PropTypes.string.isRequired, // 必须传值的属性,不传回报错 };定义默认值
TestItem.defaultProps = { suffix: "Demo", }; -
ref的使用- 使用前需要绑定DOM,建议使用箭头函数(ES6)
<input className="input" id="Action" // -------- 箭头函数绑定DOM元素 ref={(input) => { this.input = input; }} value={this.state.inputV} onChange={this.inputChange} ></input>- ref 使用遇到的坑
setState()方法是异步的,会导致ref的值更新不是最新的,应该在setState()回调函数中来获取this.setState( { list: [...this.state.list, this.state.inputV], inputV: "", }, () => { const children = this.ul.querySelectorAll("li"); console.log("setState 执行完毕---" + children.length); // 准确的值 } ); const children = this.ul.querySelectorAll("li"); console.log("ref 使用注意事项---" + children.length); -
PureComponent和Component的区别
PureComponent通过prop和state的浅比较来实现shouldComponentUpdate,可以用PureComponent提升性能
-
React只对一个
<div>其他的DOM 不受影响 -
npm install用法npm install xxx: 安装到项目目录下,不会将模块依赖写入devDependencies或dependencies。npm install -g xxx:-g将模块安装到全局,具体安装到磁盘哪个位置,要看npm cinfig prefix的位置npm install -save xxx:-save将模块安装到项目目录下,并在package文件的dependencies节点写入依赖,线上也会依赖此开源库,打包时资源会包含在内npm install -save-dev xxx:-save-dev将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖,只有开发debug 模式才会安装依赖,release模式不会打包此资源。不影响包大小
-
使用
axiso请求数据
...
React 中避免直接对数据修改
两种改变数据的方式。
-
直接修改变量的值,
-
使用新的一份数据替换旧数据
优点:
-
简化复杂的功能
-
跟踪数据的改变
-
确定在 React 中的重新渲染时机,提高性能
-
函数组件
如果组件只包含一个 render 方法,并且不包含 state,可使用函数组件更简单
通过map()构建动态列表时,都要指定一个合适的 key
-
如果要对列表进行重新排序、新增、删除操作时,把数组索引作为 key 是有问题的
因为每当一个列表重新渲染时,React 会根据每一项列表元素的 key 来检索上一次渲染时与每个 key 所匹配的列表项。如果 React 发现当前的列表有一个之前不存在的 key,那么就会创建出一个新的组件。如果 React 发现和之前对比少了一个 key,那么就会销毁之前对应的组件。如果一个组件的 key 发生了变化,这个组件会被销毁,然后使用新的 state 重新创建一份
-
如不需要重新排序、新增、删除,使用索引作为
key是安全的
组件的数据定义为props还是state?
通过以下三个问题,可得知数据是否属于 state:
- 该数据是否是由父组件通过 props 传递而来的?如果是,那它应该不是 state。
- 该数据是否随时间的推移而保持不变?如果是,那它应该也不是 state。
- 你能否根据其他 state 或 props 计算出该数据的值?如果是,那它也不是 state。
ReactNode 和 ReactElement 区别
查看声明文件如下~
ReactNode: 包括了 ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
ReactElement: ReactElement是含有 props 和 type 属性的对象
JSX.Element: J继承React.Element. 并且函数式组件一般返回JSX.Element