生命的过程,无论是阳春白雪,青菜豆腐,我都得尝尝是什么滋味,才不枉来走这么一遭啊! ——三毛
本文非从零开始学习react,只针对新手在使用时务必知晓的知识点,若要学习从零开始使用react,可移步react中文教程,再来查看此文章
1、父组件调用子组件方法
通过props传入方法,接收子组件传回的this。其实就类似react的ref属性的使用
import React, { Component } from "react";
export default class Parent extends Component {
render() {
return (
);
}
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中事件直接传参
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 ;
}
要解决这个问题,我们需要先将类型赋值给大写开头的变量。
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 ;
}
11.子代
在包含开始和结束标签的 JSX 表达式中,标记之间的内容作为特殊的参数传递:props.children
。有几种不同的方法来传递子代:
你可以在开始和结束标签之间放入一个字符串,则 props.children
就是那个字符串。这对于许多内置 HTML 元素很有用。例如:
Hello world!
这是有效的 JSX,并且 MyComponent
的 props.children
值将会直接是 "hello world!"
。因为 HTML 未转义,所以你可以像写 HTML 一样写 JSX:
This is valid HTML & JSX at the same time.
通常情况下,插入 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 {items};
}
function ListOfTenThings() {
return (
{(index) => This is item {index} in the list}
);
}
传递给自定义组件的子代可以是任何元素,只要该组件在 React 渲染前将其转换成 React 能够理解的东西。这个用法并不常见,但当你想扩展 JSX 时可以使用。
false
、null
、undefined
和 true
都是有效的子代,但它们不会直接被渲染。下面的表达式是等价的:
{false}
{null}
{undefined}
{true}
这在根据条件来确定是否渲染React元素时非常有用。以下的JSX只会在showHeader
为true
时渲染
组件。
{showHeader && }
值得注意的是,JavaScript 中的一些 “falsy” 值(比如数字0
),它们依然会被渲染。例如,下面的代码不会像你预期的那样运行,因为当 props.message
为空数组时,它会打印0
:
{props.messages.length &&
}
要解决这个问题,请确保 &&
前面的表达式始终为布尔值:
{props.messages.length > 0 &&
}
相反,如果你想让类似 false
、true
、null
或 undefined
出现在输出中,你必须先把它转换成字符串 :
My JavaScript variable is {String(myVariable)}.
限制单个子代
使用 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 (
{children}
);
}
}
MyComponent.propTypes = {
children: PropTypes.element.isRequired
};
12.React 组件也可以通过数组的形式返回多个元素:
render() {
// 不需要使用额外的元素包裹数组中的元素
return [
// 不要忘记 key :)
First item ,
Second item ,
Third item ,
];
}
13.虚拟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。
如果 ref 回调以内联函数的方式定义,在更新期间它会被调用两次,第一次参数是 null ,之后参数是 DOM 元素。这是因为在每次渲染中都会创建一个新的函数实例。因此,React 需要清理旧的 ref 并且设置新的。通过将 ref 的回调函数定义成类的绑定函数的方式可以避免上述问题,但是大多数情况下无关紧要。
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 标签:<>>是
render() {
return (
<>
>
);
}
20.将子组件渲染到父组件以外的地方:Portals
ReactDOM.createPortal(child, container)
第一个参数(child
)是任何可渲染的 React 子元素,例如一个元素,字符串或碎片。第二个参数(container
)则是一个 DOM 元素。