【React】React之从基础到放弃

React之从基础到放弃 

  生命的过程,无论是阳春白雪,青菜豆腐,我都得尝尝是什么滋味,才不枉来走这么一遭啊!      ——三毛


前言

本文非从零开始学习react,只针对新手在使用时务必知晓的知识点,若要学习从零开始使用react,可移步react中文教程,再来查看此文章


正文

1、父组件调用子组件方法

通过props传入方法,接收子组件传回的this。其实就类似react的ref属性的使用

import React, { Component } from "react";

export default class Parent extends Component {
  render() {
    return (
      <div>
        <Child onRef={this.onRef} />

        <button onClick={this.click}>click</button>
      </div>
    );
  }

  onRef = ref => {
    this.child = ref;
  };

  click = e => {
    this.child.myName();
  };
}

class Child extends Component {
  componentDidMount() {
    this.props.onRef(this);
  }

  myName = () => alert("xiaohesong");

  render() {
    return "woqu";
  }
}

2.JSX中事件直接传参

<button onClick={this.handleClick.bind(this, props0, props1, ...}></button> handleClick(porps0, props1, ..., event) { // your code here }

3.显示html

4.聚焦

 

5.单向数据流

props传的属性是只读对象

为什么需要单向,不让子组件修改?

 

答:A,B,C,D中操作数据时,发生错误,不好定位是哪里修改了父组件数据(list),数据操作也更加清晰

6.react是视图层框架

 

紫色组件想与右上角组件数据通信,只能通过一层一层调用上面的组件方法传值,再通过属性向下传递。解决方法是与redux,mobx等数据层框架进行搭配,更加灵活。

7.函数式编程,更容易自动化测试

8.属性类型校验

 

9.由于 JSX 编译后会调用 React.createElement 方法,所以在你的 JSX 代码中必须首先声明 React 变量。

推荐去在线编译网站实践:babel在线编译

10.在运行时动态渲染组件不同类型

你不能使用表达式来作为 React 元素的标签。如果你的确想通过表达式来确定 React 元素的类型,请先将其赋值给大写开头的变量。这种情况一般会在你想通过属性值条件渲染组件时出现:

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // 错误!JSX 标签名不能为一个表达式。
  return <components[props.storyType] story={props.story} />;
}

要解决这个问题,我们需要先将类型赋值给大写开头的变量。

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // 正确!JSX 标签名可以为大写开头的变量。
  const SpecificStory = components[props.storyType];
  return <SpecificStory story={props.story} />;
}

11.子代

在包含开始和结束标签的 JSX 表达式中,标记之间的内容作为特殊的参数传递:props.children。有几种不同的方法来传递子代:

  • 字符串常量

你可以在开始和结束标签之间放入一个字符串,则 props.children 就是那个字符串。这对于许多内置 HTML 元素很有用。例如:

<MyComponent>Hello world!</MyComponent>

这是有效的 JSX,并且 MyComponent 的 props.children 值将会直接是 "hello world!"。因为 HTML 未转义,所以你可以像写 HTML 一样写 JSX:

<div>This is valid HTML &amp; JSX at the same time.</div>
  • 函数

通常情况下,插入 JSX 中的 JavaScript 表达式将被认作字符串、React 元素或这些内容的列表。然而,props.children 可以像其它属性一样传递任何数据,而不仅仅是 React 元素。例如,如果你使用自定义组件,则可以将调用 props.children 来获得传递的子代:

// Calls the children callback numTimes to produce a repeated component
function Repeat(props) {
  let items = [];
  for (let i = 0; i < props.numTimes; i++) {
    items.push(props.children(i));
  }
  return <div>{items}</div>;
}

function ListOfTenThings() {
  return (
    <Repeat numTimes={10}>
      {(index) => <div key={index}>This is item {index} in the list</div>}
    </Repeat>
  );
}

传递给自定义组件的子代可以是任何元素,只要该组件在 React 渲染前将其转换成 React 能够理解的东西。这个用法并不常见,但当你想扩展 JSX 时可以使用。

  • 布尔值、Null 和 Undefined 被忽略

falsenullundefined 和 true 都是有效的子代,但它们不会直接被渲染。下面的表达式是等价的:

<div />

<div></div>

<div>{false}</div>

<div>{null}</div>

<div>{undefined}</div>

<div>{true}</div>

这在根据条件来确定是否渲染React元素时非常有用。以下的JSX只会在showHeadertrue时渲染<Header />组件。

<div>
  {showHeader && <Header />}
  <Content />
</div>

值得注意的是,JavaScript 中的一些 “falsy” 值(比如数字0),它们依然会被渲染。例如,下面的代码不会像你预期的那样运行,因为当 props.message 为空数组时,它会打印0:

<div>
  {props.messages.length &&
    <MessageList messages={props.messages} />
  }
</div>

要解决这个问题,请确保 && 前面的表达式始终为布尔值:

<div>
  {props.messages.length > 0 &&
    <MessageList messages={props.messages} />
  }
</div>

相反,如果你想让类似 falsetruenull 或 undefined 出现在输出中,你必须先把它转换成字符串 :

<div>
  My JavaScript variable is {String(myVariable)}.
</div>
  • 限制单个子代

使用 PropTypes.element 你可以指定只传递一个子代

import PropTypes from 'prop-types';

class MyComponent extends React.Component {
  render() {
    // This must be exactly one element or it will warn.
    const children = this.props.children;
    return (
      <div>
        {children}
      </div>
    );
  }
}

MyComponent.propTypes = {
  children: PropTypes.element.isRequired
};

12.React 组件也可以通过数组的形式返回多个元素:

 

render() {
  // 不需要使用额外的元素包裹数组中的元素
  return [
    // 不要忘记 key :)
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

 

13.虚拟Dom的性能提升:

  • 在js中创建js对象(虚拟dom) 性能消耗是很低的,而创建dom需要调用底层webapplication的api,需要消耗更多性能。
  • 修改数据后更新dom:两个真实dom的比对是很耗性能,而通过js的虚拟dom进行比较就节约很多。

缺陷版:

优化版(react):

原生应用通过解析虚拟dom创建出真实原生组件:例如android的layout->view。可以说虚拟dom是一个中间层(描述界面结构的对象),哪个端使用就解析渲染成哪个端的界面结构表示方法(浏览器:dom,android:window-view)

14.diff算法(难点):优化新旧虚拟dom的比对

diff:

同层比对->有一层比对不同就将后面删除,直接渲染新的dom

key值比对->dom对应关系确定,好复用

15.setState设计成异步:为了减少虚拟dom的比对次数,周期性的将多次setState合并成一次setState,然后触发比对

setState((prevState,props)=>{
      a:2
},callBack);
{
    a:1
}

+ 合并
{
    b:2
}
=>{
    a:1,
    b:2    
}

16.ref属性可以获得真实dom的节点,不建议直接使用ref操作dom。

例:获得input标签

何时使用 Refs

下面是几个适合使用 refs 的情况:

  • 处理焦点、文本选择或媒体控制。
  • 触发强制动画。
  • 集成第三方 DOM 库

如果可以通过声明式实现,则尽量避免使用 refs。

注意

如果 ref 回调以内联函数的方式定义,在更新期间它会被调用两次,第一次参数是 null ,之后参数是 DOM 元素。这是因为在每次渲染中都会创建一个新的函数实例。因此,React 需要清理旧的 ref 并且设置新的。通过将 ref 的回调函数定义成类的绑定函数的方式可以避免上述问题,但是大多数情况下无关紧要。

原生方法获得真实dom

const appRoot = document.getElementById('app-root');

17.react生命周期

componentWillReceiveProps():

执行条件:

  • 子组件接收父组件参数
  • 父组件重新render

shouldComponentUpdate(nextProps,nextState):可以用来避免父组件render后自动调用子组件render,但是子组件并没有数据变动

18.实现组件间直接通信的context,而不需要使用props一级一级传递。redux的实现原理

19.不需要使用额外父组件(div等)包裹的方法:Fragments

React 中一个常见模式是为一个组件返回多个元素。Fragments 可以让你聚合一个子元素列表,并且不在DOM中增加额外节点。

Fragments 看起来像空的 JSX 标签:<></>是<React.Fragments></React.Fragments>的语法糖。

render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}

 20.将子组件渲染到父组件以外的地方:Portals

ReactDOM.createPortal(child, container)

第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或碎片。第二个参数(container)则是一个 DOM 元素。

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值