React知识点总结——持续更新中……

1、React元素渲染

  • React 元素都是不可变的。当元素被创建之后,你是无法改变其内容或属性的。

    目前更新界面的唯一办法是创建一个新的元素,然后将它传入 ReactDOM.render() 方法。

  • React 只会更新必要的部分,React DOM 首先会比较元素内容先后的不同,而在渲染过程中只会更新改变了的部分。

通常更新分为四种情况,包括

1、REPLACE:内容替换

2、TEXT:文本内容改变

3、PROPS:属性值发生改变

4、REORDER:元素位置发生改变

React知识点总结——持续更新中……_第1张图片

2、React JSX

React 使用 JSX 来替代常规的 JavaScript。

JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。

  • 由于 JSX 就是 JavaScript,一些标识符像 class 和 for 不建议作为 XML 属性名。作为替代,React DOM 使用 className 和 htmlFor 来做对应的属性。
  • 代码中嵌套多个 HTML 标签,需要使用一个标签元素包裹它(只能有一个顶层元素)。
  • JavaScript 表达式:我们可以在 JSX 中使用 JavaScript 插值表达式。表达式写在花括号 {} 中 ,在 JSX 中不能使用 if else 语句,但可以使用 conditional (三元运算) 表达式来替代。

插值表达式类型:

  1. 字符串和数值,直接输出。
  2. 布尔值(ture/false)、空(null)、未定义(undefined),输出空字符串。
  3. 对象,插值表达式不能直接输出对象{{"name":"tom"}}。
  4. 数组:JSX 允许在模板中插入数组,数组会自动展开所有成员,数组输出默认连接符为空字符串。例如:{[1,2,3]},输出123。
  • 样式:React 推荐使用内联样式。我们可以使用 camelCase 语法来设置内联样式,将所有的样式包裹在一个对象中,以类似变量的形式给 style 属性赋值,注意样式属性要用驼峰命名法表示,React 会在指定元素数字后自动添加 px 。如: backgroundColor 而不是 background-colorfontSize 而不是 font-size
  • 注释:注释需要写在花括号中

1、在标签内部的注释需要花括号

2、在标签外的的注释不能使用花括号

ReactDOM.render(
    /*注释 */
    

Hello World {/*注释*/}

, document.getElementById('example') );

3、React 组件

  • 使用函数定义了一个组件:
function HelloMessage(props) {
    return 

Hello World!

; }
  • 使用 ES6 class 来定义一个组件:
class Welcome extends React.Component {
  render() {
    return 

Hello World!

; } }
  • 原生 HTML 元素名以小写字母开头,而自定义的 React 类名以大写字母开头,比如 HelloMessage 不能写成 helloMessage。除此之外还需要注意组件类只能包含一个顶层标签,否则也会报错。

在什么情况下你会优先选择使用 Class Component 而不是 Functional Component? 

     在组件需要包含内部状态或者使用到生命周期函数的时候使用 Class Component ,否则使用函数式组件。

React State(状态)

        React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。React 里,只需更新组件的 state,然后根据新的 state 调用render()方法,重新渲染用户界面(不要操作 DOM)。

关于setState

1、不要直接更新状态

例如,此代码不会重新渲染组件:

// Wrong
this.state.comment = 'Hello';

应当使用 setState():

// Correct
this.setState({comment: 'Hello'});

构造函数是唯一能够初始化 this.state 的地方。

2、状态更新可能是异步的

React 可以将多个 setState() 调用合并成一个调用来提高性能。

因为 this.props 和 this.state 可能是异步更新的,你不应该依靠它们的值来计算下一个状态。

例如,此代码可能无法更新计数器:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

要修复它,请使用第二种形式的 setState() 来接受一个函数而不是一个对象。 该函数将接收先前的状态作为第一个参数,将此次更新被应用时的props做为第二个参数:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

上方代码使用了箭头函数,但它也适用于常规函数:

// Correct
this.setState(function(prevState, props) {
  return {
    counter: prevState.counter + props.increment
  };
});

setState 函数可以接收两个参数,第二个参数是一个回调函数 
该函数会在setState函数调用完成并且组件开始重渲染的时候被调用,我们可以用该函数来监听渲染是否完成。也可以用来获取修改后的counter值。

this.setState(function(prevState, props) {
  return {
    counter: prevState.counter + props.increment
  };
},()=>{
  console.log("组件开始重新渲染之前 count的值:"+this.state.counter);
});

3、状态更新合并

当你调用 setState() 时,React 将你提供的对象合并到当前状态。

例如,你的状态可能包含一些独立的变量:

constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }

你可以调用 setState() 独立地更新它们:

componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }

这里的合并是浅合并,也就是说 this.setState({comments}) 完整保留了 this.state.posts,但完全替换了 this.state.comments。

调用 setState 之后发生了什么? 
        在代码中调用setState函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个UI界面。在 React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。

4、自定义配置和配置按需加载

  • 自定义配置

使用 react-app-rewired (一个对 create-react-app 进行自定义配置的社区解决方案)

  • 配置按需加载

babel-plugin-import 是一个用于按需加载组件代码和样式的 babel 插件

  • 安装
npm install [email protected] babel-plugin-import --save
  • 配置 package.json和config-overrides.js

1.修改package.json,将启动方式改为react-app-rewired,取代react-scripts

React知识点总结——持续更新中……_第2张图片

2.在项目根目录创建一个 config-overrides.js 用于修改默认配置。通过react-app-rewired启动时会将webpack中的配置与自定义配置合并。

config-overrides.js

const { injectBabelPlugin } = require('react-app-rewired');

module.exports = function override(config, env) {
    config = injectBabelPlugin([
        'import', {
            libraryName: 'antd',
            libraryDirectory: 'es',
            style: 'css'
        }
    ], config);
    return config;
}

通过以上代码实现antd库的按需加载,例如使用Button组件,则会自动导入Button的样式,不会导入全部样式,影响性能。

5、PureComponent & React.memo

PureComponent组件重新定义了shouldComponentUpdate,针对以下的情况可以不用自己重写shouldComponentUpdate,使用PureComponent

  1. 数据类型是值类型的情况
  2. 如果是引用类型,确保地址不变,同时不能有深层次的数据变化,因为只能比较一层

注意:PureComponent使用浅比较判断组件是否需要重绘

要判断组件是否需要渲染,则需要用到生命周期,则组件需要用class方式编写,但是展示型组件一般用于函数

Reactv16.6.0之后的版本添加了一个新功能React.memo,让函数式组件也具备了PureComponent的功能

const Comment = React.memo(({body,author})=> {
    console.log('render');
    return (
        

{body}

----------------{author}

) }); export default class CommentList extends Component { constructor(props) { super(props) this.state = { comments: [] } } componentDidMount() { setTimeout(() => { this.setState({ comments: [ { body: 'my name is lilei', author: 'lilei' }, { body: 'my name is hanmeimei', author: 'hanmeimei' } ] }) }, 1000); } render() { return (
{this.state.comments.map((v, idx) => ( // // ))}
) } }

6、组件复合

React中使用组件复合实现组件的复用,而非继承。将每个组件尽可能拆分成小的、独立的功能块,这样就可以像拼积木似的组装代码,实现组件的复用。

组件复合例子:

  • 首先封装了一个对话框组件
function Dialog(props) {
    return (
        
{/* 相当于vue中匿名插槽 */} {props.children} {/* 相当于vue中具名插槽 */}
{props.footer}
) }
  • 基于对话框封装了一个欢迎对话框组件
function WelcomDialog(props) {
    //jsx
    const button = 
    return (
        

我是欢迎对话框!

) }
  • 还可以基于对话框组件写一个警告提示框组件
function AlertDialog(props) {
    //jsx
    const button = 
    return (
        

我是警告提示框!

) }
  • 使用封装后的欢迎组件和警告组件
// 组件复合,用复合实现组件的复用而非继承
export default class Composition extends Component {
    render() {
        return (
            
) } }

页面显示效果如下

React知识点总结——持续更新中……_第3张图片

7、高阶组件&装饰器

 

8、组件通信

 

参考文章:http://www.runoob.com/react
参考文章:https://blog.csdn.net/H1069495874/article/details/54967244 

你可能感兴趣的:(#,React,react,知识点)