本文系统的将react的语法以最简练的方式列举出来

此文更新于2019/1/18

安装

npx create-react-app my-app
cd my-app
npm start

写在前面

1. react中state的属性,不要直接修改,而要使用替换的方式

2. 只做渲染处理的组件,尽量使用函数式组件,如下
function Square(props) {
return (
<button className="square" onClick={() => props.onClick()}>
{props.value}
</button>
);
} 3. 相同的一组组件必须要添加key 4. jsx中的属性值必须使用花括号包裹 5. jsx中的属性名必须使用驼峰命名法 6. 用户自定义的组件名必须使用大写开头 7. 组件内部不能修改props 8. 事件内部不能使用return false而只能使用e.preventDefault()阻止默认行为 9. 在组件中使用key,是不能通过props访问到的 10. false,true,null,undefined 使用{}都不会显示 11. ref的回调函数,在组件载入和销毁的时候都会调用 12. react中,你要为表单元素添加默认值,必须使用defaultValue 13. props和state属性如果是引用类型,不能直接改变,否则不会触发react的刷新机制 14. context的更新没有很好的办法,因为context的更新是依赖于state和props的更新 15. 在react里面引用类型中的属性修改了,照样可以更新视图,下面这段代码是会更新的,这也是为什么要有PureComponent的目的,减少不必要的人为更新
constructor(props){
super(props);
this.state = {
obj: {
name: "叶家伟"
}
}
}
componentDidMount(){
var obj = this.state.obj;
obj.name = "哈哈哈";
window.setTimeout(() => {
this.setState({
obj: obj
});
}, 2000)
} 16. 之前写代码,如果要返回多个元素需要单独添加一个div去包裹,现在可以使用Fragments
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>

JSX

简单明了的概括:jsx就是将html当作表达式使用

const text = "啊哈哈哈哈";
const cn = "App";
const element = <div className={cn}>{text}</div>;
class App extends Component {
render() {
return (
element
);
}
}

组件的定义

function Fc(props){
return <h1>我是props, {props.data}</h1>
} // 函数式组件
class App extends Component { // 类定义的组件
render() {
return (
<div className="App">
<Fc data="啊哈哈哈哈" />
</div>
);
}
}

state

class MyComponent extends React.Component {
constructor (props) {
super(props);
this.state = {name: "yejiawei"}
}
componentDidMount() {
this.setState({
name: "haha" // 修改值
})
this.setState({
name: this.state.name + "haha" // 异步刷新,无法展示最新值
})
this.setState((prevState,props) => ({
name: prevState.name + "haha" // 等待异步刷新完成,展示最新值
}))
}
render() {
return (
<p>{this.state.name}</p>
)
}
}

生命周期

componentWillMount() {} 挂载之前
componentDidMount() {} 挂载
componentWillUnmount() {} 销毁
componentWillReceiveProps(){} 接受props
componentWillUpdate() {} 更新

方法

  1. 使用bind

    class MyComponent extends React.Component {
    constructor () {
    super();
    this.state = {name: "yejiawei"};
    this.alertInfo = this.alertInfo.bind(this);
    }
    alertInfo(){
    alert(this.state.name)
    }
    render() {
    return (
    <p onClick={this.alertInfo}>{this.state.name}</p>
    )
    }
    }
  2. 使用箭头函数

    class MyComponent extends React.Component {
    constructor () {
    super();
    this.state = {name: "yejiawei"};
    }
    alertInfo = () => {
    alert(this.state.name)
    }
    render() {
    return (
    <p onClick={this.alertInfo}>{this.state.name}</p>
    )
    }
    }
  3. 不推荐的语法

    class MyComponent extends React.Component {
    constructor () {
    super();
    this.state = {name: "yejiawei"};
    }
    alertInfo(){
    alert(this.state.name)
    }
    render() {
    return (
    <p onClick={() => {this.alertInfo()}}>{this.state.name}</p>
    )
    }
    }

条件渲染

  1. if切换


    function MyComponent1() {
    return (
    <p>我是组件1</p>
    )
    }
    function MyComponent2() {
    return (
    <p>我是组件2</p>
    )
    }
    class MyComponent extends React.Component {
    constructor() {
    super();
    this.state = {
    isComponent1: true
    }
    }
    changeComponent = () => {
    this.setState({
    isComponent1: !this.state.isComponent1
    })
    }
    render() {
    let Comp = null;
    if(this.state.isComponent1) {
    Comp = <MyComponent1 />
    } else {
    Comp = <MyComponent2 />
    }
    return (
    <div>
    <button onClick={this.changeComponent}>切换</button>
    {Comp}
    </div>
    )
    }
    }
  2. 短路操作

    function MyComponent1(props) {
    return (
    <div>
    {props.isShow && <p>我是组件1</p> }
    </div>
    )
    }
    class MyComponent extends React.Component {
    constructor() {
    super();
    this.state = {
    isComponent1: true
    }
    }
    changeComponent = () => {
    this.setState({
    isComponent1: !this.state.isComponent1
    })
    }
    render() {
    return (
    <div>
    <button onClick={this.changeComponent}>显示隐藏</button>
    <MyComponent1 isShow={this.state.isComponent1} />
    </div>
    )
    }
    }
  3. 三元运算符

    function MyComponent1(props) {
    return (
    <div>
    { props.isShow? <p>我是组件1</p>: <p>我是组件2</p> }
    </div>
    )
    }
  4. 返回null

    function MyComponent1(props) {
    if(!props.isShow) {
    return null;
    }
    return (
    <div>
    <p>我是组件1</p>
    </div>
    )
    }

列表

基本原理
class MyComponent extends React.Component {
render() {
let arr = [1,2,3,4,5];
const componentArr = arr.map((item,index) => {
return <li key={index}>{item}</li>
})
return (
<ul>
{componentArr}
</ul>
)
}
}
必须指定key

表单

// 现实开发中,由于都是用ui框架处理,这部分很少涉及,了解下即可

实现自己的双向数据绑定
class MyComponent extends React.Component {
constructor () {
super();
this.state = {
name: '',
age: ''
}
}
setValue = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
sendData = (e) => {
e.preventDefault();
alert('提交的数据:' + this.state.value)
}
render() {
return (
<form onSubmit={this.sendData}>
<label>Name: <input name="name" type="text" value={this.state.name} onChange={this.setValue} /></label>
<label>Age: <input name="age" type="text" value={this.state.age} onChange={this.setValue} /></label>
<input type="submit" value="提交" /><br />
{this.state.name + ':' + this.state.age}
</form>
)
}
}

组合嵌套

这部分内容和vue的slot很像
组件嵌套的元素使用 props.children 表示
function MyComponent1 (props) {
return (
<div>{props.children}</div>
)
}
function MyComponent (props) {
return (
<MyComponent1>
<h1>我是嵌套的元素</h1>
</MyComponent1>
)
}
子嵌套
function MyComponent1 (props) {
return (
<div>
<div>{props.left}</div>
<div>{props.right}</div>
</div>
)
}
function MyComponent (props) {
return (
<MyComponent1 left={<h1>我是左边嵌套的元素</h1>} right={<h1>我是右边嵌套的元素</h1>}/>
)
}

扩展语法

当你的组件属性过多时,可以使用 ... 语法
function MyComponent () {
let props = {
a: 'a',
b: 'b'
};
return <SomeComponent {...props}>
}

context传递props

const TestContext = React.createContext('test'); // 创建一个上下文属性,默认值是test

class FcPre extends Component {
render() {
return ( // 将上下文属性传递给FcMiddle组件以及它的所有子组件
<TestContext.Provider value="啊哈哈哈哈哈">
<FcMiddle />
</TestContext.Provider>
);
}
} function FcMiddle(props){ // 随便写的中间层,可以有n层
return <h1><FcEnd /></h1>
} class FcEnd extends Component {
static contextType = TestContext; // 将上下文属性读取到组件中来,使用this.context访问属性值 render() {
return (
<p>{this.context}</p>
);
}
} class App extends Component {
render() {
return (
<div className="App">
<FcPre />
</div>
);
}
}

错误拦截

class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
} static getDerivedStateFromError(error) {
// 拦截错误,将state中的hasError修改成true,从而渲染错误页面,而不是整个前端项目挂了
return { hasError: true };
} componentDidCatch(error, info) {
// 打印错误信息
console.log(error, info);
} render() {
if (this.state.hasError) {
// 渲染错误页面
return <h1>Something went wrong.</h1>;
} return this.props.children;
}
} class App extends Component {
render() {
return (
<div className="App">
<ErrorBoundary><h1>aaa</h1></ErrorBoundary>
</div>
);
}
}

ref获取dom元素

使用新版的ref可以更加直接的获取到子组件的dom元素
const rf = React.createRef();
const Fc = React.forwardRef((props, ref) => {
return (
<button ref={ref}>
{props.children}
</button>
)
}) class App extends Component { componentDidMount() {
console.log(rf.current)
}
render() {
return (
<div className="App">
<Fc ref={rf}>点我</Fc>
</div>
);
}
}

自带的类型检查

安装 cnpm install --save prop-types
react系统自带的类型验证功能,没有typescript强大,可以当做编译过程中的一个补充检查
import PropTypes from 'prop-types';
function MyComponent (props){
return (
<div>
<div>{props.name}</div>
</div>
)
}
MyComponent.propTypes = { // 大小写看清楚
name: PropTypes.number
}
完整的类型
MyComponent.propTypes = {
// 你可以将属性声明为以下 JS 原生类型
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// 任何可被渲染的元素(包括数字、字符串、子元素或数组)。
optionalNode: PropTypes.node,
// 一个 React 元素
optionalElement: PropTypes.element,
// 你也可以声明属性为某个类的实例,这里使用 JS 的
// instanceof 操作符实现。
optionalMessage: PropTypes.instanceOf(Message),
// 你也可以限制你的属性值是某个特定值之一
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
// 限制它为列举类型之一的对象
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),
// 一个指定元素类型的数组
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// 一个指定类型的对象
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
// 一个指定属性及其类型的对象
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// 你也可以在任何 PropTypes 属性后面加上 `isRequired`
// 后缀,这样如果这个属性父组件没有提供时,会打印警告信息
requiredFunc: PropTypes.func.isRequired,
// 任意类型的数据
requiredAny: PropTypes.any.isRequired,
// 你也可以指定一个自定义验证器。它应该在验证失败时返回
// 一个 Error 对象而不是 `console.warn` 或抛出异常。
// 不过在 `oneOfType` 中它不起作用。
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},
// 不过你可以提供一个自定义的 `arrayOf` 或 `objectOf`
// 验证器,它应该在验证失败时返回一个 Error 对象。 它被用
// 于验证数组或对象的每个值。验证器前两个参数的第一个是数组
// 或对象本身,第二个是它们对应的键。
customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
})
};
MyComponent.defaultProps = {
// 当属性没有指定的时候,自动添加此默认值,然后再进行验证
name: 'yejiawei'
}

shouldComponentUpdate的应用

react本来的刷新机制,是根据props和state的变化,来更新虚拟dom树从而比较差异,这会导致子组件没有更新也被纳入比较中,浪费性能
所以,你可以在每一个组件中添加shouldComponentUpdate钩子函数,来手动控制更新,减少没必要的内部算法消耗
shouldComponentUpdate(nextProps, nextState) {
return false;
}
当然,如果你知道只需要根据某些props或者state的变化更新组件,那么shouldComponentUpdate无疑是最佳的体验
如果你就是想单纯的避免因为父组件的更新而导致子组件的更新,那么使用PureComponent将是更好的选择

PureComponent纯组件

PureComponent的设计目的就是根据组件自身的state和prop的变化,判断自己是否应该更新,而不是解析成虚拟dom树,这样会大大降低性能消耗
应用类型数据更新应该使用新的引用类型
对于数组,可以使用concat或者扩展运算符
对于对象,可以使用Object.assign或者扩展运算符
另外,还可以使用 Immutable.js 插件

子组件移形换位

class MyComponent1 extends React.Component {
render() {
return ReactDOM.createPortal(
<h1>{this.context.text}</h1>,
document.getElementById('haha')
)
}
}
可以将组件的元素渲染到页面上已经存在的其他的dom容器中,使用createPortal方法即可

react核心知识点高度总结的更多相关文章

  1. javascript中的一些核心知识点以及需要注意的地方

    前言 近期杂事甚多,这些事情的积累对知识体系的提升有好处,但是却不能整理出来,也整理不出来 比如说我最近研究的Hybrid在线联调方案便过于依赖于业务,就算分享也不会有人读懂,若是抽一点来分享又意义不 ...

  2. 你要的 React 面试知识点,都在这了

    摘要: 问题很详细,插图很好看. 原文:你要的 React 面试知识点,都在这了 作者:前端小智 Fundebug经授权转载,版权归原作者所有. React是流行的javascript框架之一,在20 ...

  3. 2019年Spring核心知识点整理,看看你掌握了多少?

    前言 如今做Java尤其是web几乎是避免不了和Spring打交道了,但是Spring是这样的大而全,新鲜名词不断产生,学起来给人一种凌乱的感觉,在这里总结一下,理顺头绪. Spring 概述 Spr ...

  4. Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍

    1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...

  5. Java核心知识点学习----使用Condition控制线程通信

    一.需求 实现线程间的通信,主线程循环3次后,子线程2循环2次,子线程3循环3次,然后主线程接着循环3次,如此循环3次. 即:A->B->C---A->B->C---A-> ...

  6. Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统

    理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...

  7. Java核心知识点 --- 线程中如何创建锁和使用锁 Lock , 设计一个缓存系统

    理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...

  8. React 核心思想之声明式渲染

    React 发展很快,概念也多,本文目的在于帮助初学者理清 React 核心概念. React 及 React 生态 React 的核心概念只有 2 点: 声明式渲染(Declarative) 基于组 ...

  9. 【SpringBoot MQ 系列】RabbitMq 核心知识点小结

    [MQ 系列]RabbitMq 核心知识点小结 以下内容,部分取材于官方教程,部分来源网络博主的分享,如有兴趣了解更多详细的知识点,可以在本文最后的文章列表中获取原地址 RabbitMQ 是一个基于 ...

随机推荐

  1. win7下users用户文件转移到其他盘符

    在安装完的系统中, 1.重启按F8键到修复系统界面: 2.下一步->下一步->运行dos窗口,打开dos窗口: 3.拷贝命令:robocopy "C:\Users" & ...

  2. Kafka详解六:Kafka如何通过源码实现监控

    问题导读: 1.kafka的消费者组的消费偏移存储,kafka支持两个版本?        2.ConsumerOffsetChecker类的作用是什么?        3.Kafka如何通过源码实现 ...

  3. 字符在内存中最终的表示形式是什么?是某种字符编码还是码位(Code Point)?

    字符在内存中最终的表示形式是什么?是某种字符编码还是码位(Code Point)? 根据我的了解,编码中有三个核心概念:1. 字符集(Character Set),可以说是一个抽象概念,字符的合集2. ...

  4. mac 下面配置gradle

    最近刚开始用gradle,先向大家介绍一下怎么配置gradle的环境变量吧: 1.下载最新安装包gradle-xxx-all.zip:http://www.gradle.org,并解压到/Users/ ...

  5. review07

    java类可以有两种重要的成员:成员变量和方法,实际上java还允许有一种成员:内部类.内部类是在一个类中定义另一个类.内部类和外嵌类的关系如下: (1)内部类的外嵌类的成员变量在内部类中仍然有效,内 ...

  6. Web API 接口-JavaScript全部api接口文档

    当使用JavaScript编写网页代码时,有很多API可以使用.以下是所有对象.类型等接口的列表,你在开发网页应用程序或站点时使用它们. API文档地址:https://developer.mozil ...

  7. 1009 失恋的小 T(后缀数组¥)

    1009: 失恋的小 T 时间限制: 1 Sec  内存限制: 128 MB提交: 160  解决: 76[提交][状态][讨论版] 题目描述 小 T 最近失恋了,开始怀疑人生和爱情,他想知道在这世界 ...

  8. New Concept English three (46)

    27w/m 66 error So great is our passion for doing things for ourselves, that we are becoming increasi ...

  9. jmeter请求中上传图片

    1.请求中上传图片 把图片放在bin目录下:multipart/form-data 先把照片发送给阿里,阿里返回image_id:然后用后置条件正则表达式匹配并保存image_id 下次请求直接用im ...

  10. SaaS模式实现架构

    SaaS模式实现架构 https://blog.csdn.net/xwq911/article/details/50630266 1. 数据库层: 数据库这一层的设计模式是很清晰的,无外乎只有3种方案 ...