美文网首页
React组件与JSX语法

React组件与JSX语法

作者: kim_jin | 来源:发表于2018-12-06 17:32 被阅读0次

    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;
    

    相关文章

      网友评论

          本文标题:React组件与JSX语法

          本文链接:https://www.haomeiwen.com/subject/pmcvcqtx.html