react的浅谈--组件

达芬奇密码2018-06-21 17:09
React 作为最热门的前端框架之一,已经被很多人了解。
它起源于 Facebook 的内部项目,因为该公司对市场上所有  JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月 开源了。而之所以开发React最主要解决的问题是:构建随着时间数据不断变化的大规模应用程序。

那么React是如何解决这个问题了?

1:组件化:React组件化使得场景树可以随着数据量的增多而不断扩大,且重复使用组件。
React的组件可以组合(并不是继承),那么React是如何实现组件,又是如何实现组件的组合,组合后的父子是如何通讯的?今天我们就来简单解析下。

(1)用户可定义自己的组件
注意,原生 HTML 元素名以小写字母开头,而自定义的 React 类名以大写字母开头。
如何实现一个组件?
var Hello = React.createClass({
  render: function() {
    return (
      <div className="HelloBox">
        Hello, world! I am a HelloBox.
</div> ); } }); React.render( <Hello />,
document.getElementById('content') );
上述到底做了什么?

1):createClass: 创建React组件对应的类,描述你将要创建组件的各种行为,其中只有当组件被渲染时需要输出的内容的render接口是必须实现的,其他都是可选.组件与标准原型类的不同之处在于,你不需要使用 new 来实例化。

1.1):createClass中的输入render:该方法返回一颗React组件树,这颗树最终会被渲染成HTML。其中,这里的<div> 标签不是真正的 DOM 节点;他们是 React div 组件的实例。你可以认为这些标签就是一些标记或者数据, React 知道如何处理它们。React 是安全的,不会生成 HTML 字符串,因此默认阻止了 XSS 攻击。

2):render:实例化根组件,启动框架,把标记注入到第二个参数指定的原生的 DOM 元素中。如果 ReactElement 之前就被渲染到了container中,该函数将会更新此 ReactElement,仅改变需要改变的 DOM 节点以展示最新的 React 组件。


番外:既然上述叙述了创建React组件对应的类,那么很多人会想到如何依据类创建实例?

3):createElement,创建并返回一个新的指定类型的 ReactElement,支持type,config,children三个参数:

ReactElement.createElement = function(type, config, children) {
  ...
}
上述在jsx中描述的 <Hello /> ,编译后就是 React.createElement(Hello),可以理解为是一个对象实例的创建。

4):createFactory,返回一个生成指定类型 ReactElements 的函数,在js里要实现工厂方法只需创建一个带type参数的createElement的绑定函数:
ReactElement.createFactory = function(type) {
  var factory = ReactElement.createElement.bind(null, type);
  return factory;
};
创建模式目的是隔离与简化创建组件的过程,模式的东西自然是可用可不用,如果需要批量创建某个组件时,可以通过工厂方法来实现:
var h = React.createFactory(Hello);
h({x:1})
h({x:2})
h({x:3})
(2)组件的组装:既然是组件那么一定是可以组装的。
如何将组件组装起来?
React既可以组装HTML标签也可以组装用户所创建的组件。
var CommentList = React.createClass({
  render: function() {
    return (
      <div className="commentList">
        Hello, world! I am a CommentList.
      </div>
    );
  }
});

var CommentForm = React.createClass({
  render: function() {
    return (
      <div className="commentForm">
        Hello, world! I am a CommentForm.
      </div>
    );
  }
});
var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList />
        <CommentForm />
      </div>
    );
  }
});
上述将原生的HTML标签与用户自定义的组件进行了组装,那么具体内部是做了什么了?JSX 编译器会自动重写 HTML 标签为 React.createElement(tagName)表达式,其它什么都不做。这是为了避免全局命名空间污染。

(3)组件的通讯:组件可以组合,组合的父子通过组件的属性来相互通讯,且是唯一通讯渠道。
组件属性的实现方法是:从父组件传入的数据会做为子组件的 属性( property ),这些 属性( properties )可以通过 this.props访问到。
例如:
var Comment = React.createClass({
  render: function() {
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2>
        {this.props.children}
      </div>
    );
  }
});
上述,通过 this.props来访问传入组件的数据,键名就是对应的命名属性,也可以通过 this.props.children访问组件内嵌的任何元素。
在 JSX 中,通过使用大括号包住一个 JavaScript 表达式(例如作为属性或者儿子节点)(eg:{this.props.author}),你可以在树结构中生成文本或者 React 组件
现在定义了Comment组件,我们想传递给它不同的名字和内容,以便于我们能够对每一个独立的Comment重用相同的代码。
var CommentList = React.createClass({
  render: function() {
    return (
      <div className="commentList">
        <Comment author="Pete Hunt">This is one comment</Comment>
        <Comment author="Jordan Walke" >This is *another* comment</Comment>
      </div>
    );
  }
});
上述:组合的父组件传递给子组件一些数据,例如,我们传递了 Pete Hunt (通过属性)和  This is one comment (通过类似于 XML 的子节点)给第一个 Comment 组件。comment组件通过this.props.author和this.props.children来访问这些"属性"。

  • 子组件向父组件发送消息
eg:子组件要知道父组件的edit事件,那么父组件就可以传递一个props.onEdit方法给子组件,子组件就可以通过调用this.props.onEdit就可以通知父组件。
  • 父组件向子组件发送消息
父组件可以直接修改props,从而直接给子组件发送消息。

var Hello = React.createClass({
  render: function() {
    return (
      <div className="HelloBox">
        {this.props.name}
      </div>
    );
  }
});
var helloWorld = React.render(
  <Hello name="hl" />,
  document.getElementById('content')
);
helloWorld.setProps({name:'violin'}

结束语:

     初学react,文中如有不妥之处请大家指出,后期会进一步讲解react是如何实现:构建随着时间数据不断变化的大规模应用程序。^_^。


参考资料:
1: http://www.ruanyifeng.com/blog/2015/03/react.html
2: http://www.zhihu.com/question/27602269/answer/40168594,
3:http://reactjs.cn/react/docs/thinking-in-react.html#

本文来自网易实践者社区,经作者王海玲授权发布。