React组件与JSX语法

virtual DOM

真实页面对应一个DOM树。在传统页面的开发模式中,每一次需要更新页面的时候,都需要手动操作DOM来进行更新。

传统DOM更新

DOM的操作是十分昂贵的,我们在前端开发中,性能消耗最大的就是DOM操作,而且这部分的代码会让整体项目的代码变得难以维护。React把真实的DOM树转换为JavaScript对象树,也就是virtual DOM

React DOM更新

每一次数据更新后,重新计算Virtual DOM,并和上一次生成的Virtual DOM进行比对,对发生变化的部分进行批量更新。Rect也提供直接的shouldComponentUpdate声明周期回调,来减少数据变化后的不必要的Virtual DOM对比的过程,用来保证性能。

JSX语法

JSXReact有什么关系?简单的来说,React为了方便view层组件化,承载了构建HTML结构化页面的职责,React通过创建于与跟新虚拟元素(virtual DOM)来管理整个Virtual DOM
React创建虚拟元素可以划分为两类,DOM元素(DOM element)与组件元素(component element),分别对应原生的DOM元素和自定义元素,而JSX与创建元素有很大的关系。
JSX的官方定义是类XML语法的ECMAScript扩展。它完美的利用了JavaScript自带的语法和特性,并且使用大家熟悉的HTML语法来创建虚拟元素。可以说,JSX基本语法被XML囊括了,但是也有少许不同的地方。

XML基础语法

使用类XML语法的好处是标签可以任意嵌套,我们可以像HTML一样清晰看到DOM树结构和其属性,比如我们构建一个List组件。

const List = () =>{
  <div>
    <Title>This is Title</Title>
    <ul>
      <li>list item</li>
    </ul>
  </div>
}

List的过程就像写HTML一样,只不过它被包裹在JavaScript的方法中,但是在这个过程中需要注意以下几点:

  • 标签一定要闭合
  • 定义标签的时候,只允许被一个标签包裹。所以上面的写法是错误的。
const List = () =>{
  <div>
    <Title>This is Title</Title>
    <ul>
      <li>list item</li>
    </ul>
  </div>
 <div>
    <Title>This is Title</Title>
    <ul>
      <li>list item</li>
    </ul>
  </div>
}
元素类型

我们都知道JSX语法中的元素分为DOM元素(DOM element)与组件元素(component element),JSX对应的规则是HTML标签是否为小写字母,其中小写字母对应DOM元素,而逐渐元素自然对应的是首字母大写。

注释

事实上JSX还是JavaScript,依然可以用简单的方法使用注释,唯一需要注意的是,在一个组件的子元素位置使用注释需要{}进行包裹,实例代码如下:

const App = (
  <Nav>
    {/*节点注释*/}
    <Person
      /*多行
        注释*/
      name =  {window.isLoggedIn?window.name : ''}
    />
  </Nav>
)
元素属性

JSX中,不论是DOM元素还是组件元素,它们都是有属性的,不同的是,DOM元素的属性是标准规范属性,但是有两个例外--classfor,这是因为在JavaScript中这两个单词是关键词,因此我们这么转换。

  • class属性修改为className
  • for属性改为htmlFor

而组件元素的属性是完全自定义的,也可以理解成组件需要的参数,举个栗子:

const Header = ({title,children})=>{
  <h3 title = {title}>{children}</h3>
};
<Header title='hello world'>hello world</Header>

我们可以对属性进行展开展开,这个应用场景主要是,当我们知道组件的全部属性的时候,使用JSX可以这么写:

//方法一
const component = <Component name = {name} value = {value}/>;

//方法二
const component = <Component / >;
component.props.name = name;
component .props.value = value;

// 方法三:使用ES6特性来提高效率
const data = {name:'foo', value:'bar'};
const component = <Component name = {data.name} value = {data.value}/>;
//方法三可以使用ES6来进行简写
const data = {name:'foo', value:'bar'};
const component = < Component  {...data} />;
javaScript属性表达式

属性值要使用表达式的话,只要使用{}进行替换即可。

//输入(JSX)
const person = <Person name ={window.isLoggedIn ? window.name:''} />
//输出(JavaScript)
const person = React.createElement (
  person,
  {name:window.isLoggedIn ? window.name:' '}
);

其中子组件也可以作为表达式使用:

//输入(JSX)
const content = <Container>{window.idLoggedIn ? <Nav  /> :<login />}</Container>
//输出(JavaScript)
const content = React.createElement (
  Container,
  null,
  {name:window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)}
);

小结:

  • JSX是一个看起来很像XMLJavaScript语法扩展,这种语法允许你在写JavaScript中写可嵌套的闭合标签。
  • JSXHTML语法很像,可以嵌套,可以自定义属性。
  • JSX允许在闭合标签中使用JavaScript表达式,但是要被{}所包裹
  • JSX中的内联样式也是通过style属性来定义的,但属性值不能是字符串而必须为对象,而且要注意对象中的属性名需要使用驼峰命名法。
  • JSX中,标签子节点内的注释应该写在{}内。
  • JSX中的数组会自动的展开所有的成员,但是需要注意的是,如果数组或是迭代器中的每一项都是HTML标签或是组件的话,那么他们必须要拥有唯一的key属性

React组件

其实对组件的封装很类似与面向对象的思想,交互基本上以操作DOM为主,逻辑上是结构上哪里需要变,我们就操作哪里。此外,对于JavaScript的结构,我们得到了几项规范标准组件的信息。

  • 基本的封装性:尽管说JavaScript没有真正的面向对象的方法,但是我们还是可以通过实例化的方法来制造对象。
  • 简单的生命周期:最明显的两个方法是:constructordestroy,代表了组件的挂载卸载的过程,但是除此之外,其他过程(如更新时的声明周期)并没有体现。
  • 明确的数据流动:这里的数据指的是地道用组件的参数。一旦确定参数的值,就会解析传进来的参数,根据参数的不同做出不同的响应,从而得到渲染的结果。

Web Components规范:这个规范想要同意web端关于组件的定义,它可以通过定义Custom Elements(自定义元素)的方式来统一组件。每一个自定义元素可以定义自己对外提供的属性、方法、还有事件,内部可以像写一个页面一样,专注于实现功能来完成对组件的封装。

Web Components组成

Web Components定义了一切我们想要的组件化的概念,其中HTML Template定义了之前的模板概念,Customer Element定义了组件的展现形式,shadow DOM定义了组件的作用域范围,可以包括样式,HTML Imports提出了新的引入方式。

React组件的构建

React组件即为组件元素:组件元素描述成纯粹的Json对象,意味着可以使用方法或是类来构建。React组件即为组件元素,组件基本上由3个部分组成-- 属性(props)、状态(state)以及生命周期方法,这里我们从一张图来简单的概括React

React组件的组成

React组件可以接受参数,也可以有自身的状态,一旦接受到的参数或是自身的状态有所改变,React组件就会执行相对应的生命周期的方法,最后渲染,整个过程完全符合传统组件所定义的组件职责。
React和web component的关系
Reactweb component传达的理念是一致的,但是二者的实现方式是不同的,

  • React自定义元素的库是自己构建的,与web component规范是不一致的
  • React渲染过程包含了模板的概念,也就是之前说的JSX
  • React组件的实现均在方法和类中,因此做到了相互的隔离,但是不包含样式。
  • React引用方式遵循ES6标准

官方在React组件构建上提供了3种不同的方法:React.createClass,ES6 classes 和无状态函数。
React.createClass方法是构建组件最传统,也是兼容性最好的方法,实例代码如下:

const Button = React.createClass({
  getDefaultProps(){
    return {
      color:'red',
      text:'cancle',
    };
  },
  render(){
    const {color, text} = this.props;
    return (
      <button className ={`btn btn - ${color}`}>
        <em>{text}</em>
      </button>
    );
  }
});

当组件需要调用Button组件的时候,只需要写<Button />,就可以被解析成React.createElement(Button)方法来创建Button实例,这意味着在一个应用中调用几次Button,就会创建几次Button的实例。

ES6 classes

ES6 classes的写法是通过ES6标准的类语法的方式来构建方法:

import React, {Component } from 'react';

class Button extends Component{
  constructor (props){
    super(props);
  }
  static defaultProps ={ // 用来设置默认属性
    color:'blue',
    text:'Confirm',
  };
  render(){
    const {color,text} = this.props;

    return (
      <button className = {`btn btn-${color}`}>
        <em>{text}</em>
      </button>
    );
  }
}

这里的直观感受是从调用内部方法变成了类来实现,与createClass的结果相同的是,调用类实现的组件会创建实例对象。在React组件开发中,常用的方式是将组件拆分到合理的粒度,用组合的方式合成业务组件。

无状态函数

使用无状态函数构建的组件称为无状态组件,这样的写法比较受官方推崇。我们看一下示例代码:

function Button({color = 'blue',text = 'confirm'}){
  return (
    <button className = {`btn btn-${color}`}>
      <em>{text}</em>
    </button>
  );
}

无状态组件只传入propscontext两个参数;也就是说,它不存在state,也没有生命周期方法,组件本身即上面两种React组件构建方法中的render方法。不过,像propTypesdefaultProps还是可以通过向方法设置静态属性来实现。
我们使用React实现Tabs组件:

import React,{Component,PropType} from 'react';

class Tabs extends Component {
  constructor(props){
    super(props);
  }
  //...
  render(){
    return <div className = 'ui-tabs'></div>
  }
};
export defaults Tabs;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,810评论 1 18
  • 40、React 什么是React?React 是一个用于构建用户界面的框架(采用的是MVC模式):集中处理VIE...
    萌妹撒阅读 1,005评论 0 1
  • 1.1React 简介 React 把用户界面抽象成一个个组件,开发者通过组合这些组件,最终得到功能丰富、可交互的...
    sylvia_yue阅读 459评论 2 1
  • 你知道吗,现在看到很多虐待儿童,虐待女性,虐待动物等等这些新闻,我会逃避性的马上忽略过去。 以前会看,看完了生气流...
    miss番小薯阅读 479评论 0 0
  • 秋摊开了难言的色彩 仿佛这一切 刚发生 又好像曾经 一直都存在着 这古色古香的小径 为你的憧憬 解决了最佳方案 银...
    江城妖怪阅读 283评论 0 0