前言

上一篇介绍了Reactjs的项目目录结构以及他的工作模式。这篇文章将会通过阅读官方文档,学习Reactjs的语法,逻辑,思想等内容。

文章目录

1、JSX
2、元素
3、组件

一、JSX

1、JSX

前面我们了解到React是通过js来构造html,实际上React就是通过JSX来渲染元素,那么什么是JSX,它跟JS和HTML有什么关联呢?

2、JSX简介

JSX(JavaScript XML)是 js 内定义的一套类 XML 语法,可以解析出目标 js 代码,颠覆传统 js 写法。初接触JSX的语法,可能会让人联想到html模板语言,其实JSX做的工作与HTML所做的工作有一定的相似之处,不用的地方在于,HTML 由浏览器解析,而 JSX 是由 js 解析。

使用JSX可以生成React元素。JSX在被编译后也会转化成js代码执行。React中用不用JSX不是一个硬性条件,只是说使用JSX会有更多的好处。

总而言之,能有JSX做的事,用javascript都能做到。

3、举个栗子(在html文档中创造一个列表)
3.1 JS
var child1 = React.createElement('li', null, '这是列表下的第一条元素');
var child2 = React.createElement('li', null, '这是列表下的第二条元素');
var new_list = React.createElement('ul', { className: 'my-list' }, child1, child2);
3.2 JSX
const new_list = (
  <ul className="my-list">
    <li>这是列表下第一条元素</li>
    <li>这是列表下第一条元素</li>
  </ul>
)

Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。上述两种方法实现的效果是一样的。

4、JSX语法
4.1 JSX 的基本语法规则:

1)遇到 HTML 标签(以 < 开头),就用 HTML 规则解析
2)遇到代码块(以 { 开头),就用 JavaScript 规则解析

4.2 JSX 语法示例:
const element = <h1>Hello, world!</h1>;

/* 若一个标签里面没有内容,可以使用 /> 来闭合标签 */
const element = <img src={user.avatarUrl} />;
4.3 表达式嵌套

1、在JSX中,我们还可以使用表达式

/* 通过 { } 接收参数 name  */
const name = 'Reactjs';
const element = <h1>Hello, {name}</h1>;

2、在JSX中,我们可以在大括号内放置任何有效的 JavaScript 表达式。这些表达式可以为:

(1)变量名 (2)函数定义表达式 (3)属性访问表达式 (4)函数调用表达式 (5)算数表达式 (6)关系表达式 (7)逻辑表达式

1、放置算数表达式:
const element = <h1>计算10+5的结果:{10+5}</h1>;

2、放置调用函数:

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = <h1>Hello, {formatName(user)}</h1>;

3、JSX作为表达式返回

/* 可以在其他 javascript 中返回 JSX 生成的 DOM 对象 */
function getGreeting(user) {
  if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
  }
  return <h1>Hello, Stranger.</h1>;
}
4.4 命名规则

因为 JSX 语法上更接近 JavaScript 而不是 HTML,所以 React DOM 节点使用 camelCase(小驼峰命名)来定义属性的名称,而不使用 HTML 属性名称的命名约定。

例如,JSX 里的 class 变成了 className,而 tabindex 则变为 tabIndex

4.5 JSX 对象
const element = <h1 className="greeting">Hello, world!</h1>;

上述JSX语法生成的对象结构:

const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

这些对象被称为 “React 元素”。它们描述了你希望在屏幕上看到的内容。React 通过读取这些对象,然后使用它们来构建 DOM 以及保持随时更新

二、元素

元素是构成 React 应用的最小砖块。它描述了你在屏幕上想看到的内容。也就是我们日常浏览网页时看到的网页上的图片,文字,表格,列表等等,这些都是由一个或者多个元素组成。

例如:<a><h1><div><span><img>

渲染元素也就是画画,将定义的元素在网页中绘制出来,将react渲染成为一个html DOM

1、ReactDOM

我们在使用react开发网页时,会下载两个包,一个是react,一个是react-dom,其中react包是react的核心代码,react-dom则是React剥离出的涉及DOM操作的部分。

react的核心思想是虚拟DOM,react包含了生成虚拟DOM的函数react.createElement,及Component类。当我们自己封装组件时,就需要继承Component类,才能使用生命周期函数等。

react-dom包的核心功能就是把这些虚拟DOM渲染到文档中变成实际DOM。下面学习 ReactDOM 的 API 函数

1.1 render()

render用于将React渲染的虚拟DOM渲染到浏览器DOM,一般在顶层组件使用

(1)语法

render(ReactElement element,DOMElement container,[function callback])
@param:
ReactElement element:待渲染的元素或者组件
DOMElement container:容器节点(已经存在的DOM节点)
[function callback]:回调函数

(2)例子

import ReactDOM from 'react-dom';

/* 渲染组件*/
/* <Example /> 为自定义组件 */
ReactDOM.render(<Example />, document.getElementById('root'));

/* 渲染元素 */
const element = <h1>Hello, world!</h1>;
ReactDOM.render(element, document.getElementById('root'));

(3)一些注意事项

1)ReactDOM.render()会控制传入容器节点里的内容。当首次调用时,容器节点里的所有 DOM 元素都会被替换,后续的调用则会使用 React 的 DOM 差分算法(DOM diffing algorithm)进行高效的更新。

2)ReactDOM.render() 不会修改容器节点(只会修改容器的子节点)。可以在不覆盖现有子节点的情况下,将组件插入已有的 DOM 节点中。

1.2 findDOMNode()

当我们通过render()方法将组件渲染成DOM以后,避免不了获取该组件的操作,通过findDOMNode()方法可以返回已经完成渲染的组件对应的DOM节点。

(1)语法

ReactDOM.findDOMNode(component)

(2)注意事项

1)findDOMNode 是一个访问底层 DOM 节点的应急方案。在大多数情况下,不推荐使用该方法,因为它会破坏组件的抽象结构

2)大多数情况下,你可以绑定一个 ref 到 DOM 节点上,可以完全避免使用 findDOMNode。

3)findDOMNode 只在已挂载的组件上可用(即,已经放置在 DOM 中的组件)。如果你尝试调用未挂载的组件(例如在一个还未创建的组件上调用 render() 中的 findDOMNode())将会引发异常。

4)findDOMNode 不能用于函数组件。

1.3 unmountComponentAtNode()

从 DOM 中卸载组件,会将其事件处理器(event handlers)和 state 一并清除。如果指定容器上没有对应已挂载的组件,这个函数什么也不会做。如果组件被移除将会返回 true,如果没有组件可被移除将会返回 false。

(1)语法

ReactDOM.unmountComponentAtNode(container)
2、更新元素

React DOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态。

计时器例子:

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(element, document.getElementById('root'));
}

setInterval(tick, 1000);

对于上述例子,render每次渲染的时候,都只对h2进行更新,对于没有改变的元素,render不会对其进行重新渲染。这里面涉及到一个react的差分算法

三、组件

首先需要区分组件跟元素的概念,组件是由元素构成的。元素数据结构是普通对象,而组件数据结构是类或纯函数。

就拿建造一座大楼来说,

如果说我们最后使用React构建的网页一座辉煌的高楼。

那么,元素就是砖块,组件就是每一间房间,例如厕所组件、卧室组件、厨房组件,这些组件都是一块一块砖构成,这一座楼房又是有这些房间组件构成。

react 服务端 python reactjs python_node.js

1、函数组件

定义组件最简单的方式就是编写 JavaScript 函数:

function Hello(props) {
  return <h1>Hello, {props.name}</h1>;
}

2、class组件

定义 class 组件,需要继承 React.Component:

class Hello extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

3、渲染组件

回顾之前的元素,发现到目前为止,遇到到React元素都是html DOM 标签,例如

const element = <div />;
const element = <a />;
const element = <img />;

React 元素也可以是用户自定义的组件:

const element = <Hello name="Lisa" />;

上面定义了一个名叫Hello的组件

function Hello(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Hello name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

1、调用 ReactDOM.render() 函数,并传入 <Hello name="Sara" /> 作为参数。
2、React 调用 Hello 组件,并将 {name: 'Lisa'} 作为 props 传入。
3、Hello 组件将 <h1>Hello, Lisa</h1> 元素作为返回值。
4、React DOM 将 DOM 高效地更新为 <h1>Hello, Lisa</h1>

4、自定义组件规则

组件名称必须以大写字母开头

以小写字母开头的元素代表一个 HTML 内置组件,比如 <div> 或者 <span> 会生成相应的字符串 ‘div’ 或者 ‘span’ 传递给React.createElement(作为参数)。大写字母开头的元素则对应着在 JavaScript 引入或自定义的组件,如 <Foo /> 会编译为 React.createElement(Foo)。

import React from 'react';

// 错误!组件应该以大写字母开头:
function hello(props) {
  // 正确!这种 <div> 的使用是合法的,因为 div 是一个有效的 HTML 标签
  return <div>Hello {props.toWhat}</div>;
}

// 正确!组件以大写字母开头了:
function HelloWorld() {
  // 错误!React 会认为 <hello /> 是一个 HTML 标签,因为它没有以大写字母开头:
  return <hello toWhat="World" />;
}

5、混合组件

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      /* 调用自定义的 Welcome 组件*/
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);