前端React框架基础语法

一、ReactDOM.render()方法

ReactDOM.render()方法是React框架中最最最基础的方法,这个方法的作用是将模板转化为HTML的语法,然后插入到指定的 DOM 节点中。

<script type="text/babel">
   ReactDOM.render(
      <p>Hello, world!</p>,
      document.getElementById('test')
    );
</script>

上面的代码将一个

插入到 test 的节点中,其中document.getElementById(‘test’)指定被插入的节点。

二、JSX的语法

我们上面就在将JSX语法,那么到底什么是JSX语法呢,其实我们可以简单的认为将HTML语言直接写在JavaScript语言之中,不加任何的引号,JSX语法允许HTML和JavaScript的混写。

var name =['kim' , 'tom' , 'tony'];
ReactDOM.render(
  <div>
  {
      name.map(function(name){
        return <div> hello {name}!</div>
      })
  }
  </div>,
  document.getElementById('test');
);

总结一下:遇到HTML标签,就使用HTML的规则解析;遇到代码块,使用{}包裹的代码,就用JavaScript规则进行解析。
当然JSX允许直接在模板中插入JavaScript变量,如果这个变量是一个数组的话,我们会展开这个数组的所有的成员。

var arr = [
  <h1>Hello world!</h1>,
  <h2>React is awesome</h2>,
];
ReactDOM.render(
  <div>{arr}</div>,
  document.getElementById('example')
);

会在结果中打出Hello world!,React is awesome两个标题。

三、组件

React框架允许我们将代码封装成组件,然后像插入普通的HTML标签一样,在网页中插入这个组件。

var HelloMessage = React.creatClass({
  render :function(){
    return <h1>hello {this.props.name}</h1>
  }
});
ReactDOM.render(
  <HelloMessage name ='kim' />
  document.getElement('test');
)

在上面的代码里面,HelloMessage 就是一个组件类,我们在模板中直接插入了就会自动的生成HelloMessage 的实例,在React中所有的组件都必须有自己的render方法,这个方法的目的是输出组件。
ps:组件的第一个字母必须大写,否则就会报错,而且一个组件类智能包含一个顶级标签,否则也会报错。举个栗子:

var HelloMessage = React.createClass({
  render: function() {
    return <h1>
      Hello {this.props.name}
    </h1><p>
      some text
    </p>;
  }
});

上面的代码就会报错,以为在一个组件类中包含了2个顶层标签,<p><h1>标签。组件的用法和原生的 HTML 标签相比没有任何的区别,可以加入任意的属性,上例中我们就在 HelloMessage 标签中加入了 name 属性。其中组件的属性可以在组件类的 this.props 对象上获取。在添加组件属性的时候,也需要注意class要写成 className ,for 方法要写成 htmlFor ,因为 class 和 for 是 JavaScript 的保留字。this的指向:this指向的是组件类。
this.props.children
this.props 对象的属性和组件的属性是一一对应的,但是还是有一个例外的,那就是 this.props.children 实行。他表示组件所有的子节点。

var NotesList = React.createClass({
  render: function() {
    return (
      <ol>
      {
        React.Children.map(this.props.children, function (child) {
          return <li>{child}</li>;
        })
      }
      </ol>
    );
  }
});

ReactDOM.render(
  <NotesList>
    <span>hello</span>
    <span>world</span>
  </NotesList>,
  document.body
);

实现的结果是:

this.props.children的实现结果
ps:this.props.children 的值可能存在三种情况,第一种就是当前的组件没有子节点,那么 this.props.children 返回的就是 undefined,如果只有一个节点的话,那么返回的数据类型就是Object;如果有多个节点的话,返回的数据类型就是一个数组 array,所以处理 this.props.children 的时候要格外的小心。
为了解决上述的问题,React框架为我们提供了一个 React.Children 的方法来处理 this.props.children 。我们可以根据 React.Children.map 来进行子节点的遍历。不用再担心 React.Children 的数据类型究竟是undefined还是 object

PropTypes

组件的属性在一定的意义上有一点类似于函数的参数,所以组件的属性值可以接受任意值,字符串、对象、数组、函数等等都可以。所以我们现在需要一种机制来验证别人传过来的值是否符合要求。组件的PropTypes属性,就可以用来检测组件的实例属性是否符合要求。

var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
},

render: function() {
return

{this.props.title}

;
}
});
上面这段代码的意思就是在MyTitle组件有一个title的属性。PropTypes告诉React,这个title的属性是必须的,而且这个属性的数据类型是字符串,如果我们为title的属性设置为number类型的话,验证就无法通过,会在控制台输出一行错误信息。
还有一个关于属性的就是getDefaultProps方法可以用来设置组件属性的默认值。

var MyTitle = React.createClass({
  getDefaultProps : function () {
    return {
      title : 'Hello World'
    };
  },

  render: function() {
     return <h1> {this.props.title} </h1>;
   }
});

ReactDOM.render(
  <MyTitle />,
  document.body
);

这个方法的意思就是在没有显示的对title的值就行定义的话,我们就直接使用默认值,也就是说上面的代码默认显示的是‘Hello World’。

获取真实的DOM节点
我们在写的时候讲组件当做真正的HTML的语法来写,但是其实组件并不是真正的DOM节点,而是存在于内存之后的一种数据机构,也就是虚拟DOM,只有将它插入到文档之后,它才会变成真正的DOM,在React设计的本意是,所有的DOM的变动是先发生在虚拟DOM中的,然后再将实际发生变动的部分,反映在真实的DOM中。
但是,有时候,我们需要从组件中获取真实的DOM,这个时候就要用到ref属性了。

var MyComponent = React.createClass({
  handleClick: function() {
    this.refs.myTextInput.focus();
  },
  render: function() {
    return (
      <div>
        <input type="text" ref="myTextInput" />
        <input type="button" value="Focus the text input" onClick={this.handleClick} />
      </div>
    );
  }
});

ReactDOM.render(
  <MyComponent />,
  document.getElementById('test')
);

组件MyComponent的子节点有一个文本输入框,来得到用户的输入,现在这个情况就是必须获取真实的DOM节点,虚拟DOM对于用户来说是拿不到的,所以我们为了可以获取到这个值,文本框必须有一个ref属性,然后在使用this.refs.[refName]就可以返回这个真实DOM节点。由于this.refs.[refName]属性获取的是真正的DOM,所以一定要等到虚拟的DOM插入文档以后,才可以使用这个属性,要不然就会报错。在上面代码中指定了click回调函数,确保了DOM获取发生在Click之后,才会读取this.refs.[refName]属性。重点就是一定要在虚拟DOM插入到文档之后再进行操作。

this.state

组件是无法避免的要与用户进行互动,我们可以将组件看做是一个状态机,一开始有一个初始状态,然后与用户进行互动,不断的导致状态的改变,从而触发重新的渲染UI。

var LikeButton = React.createClass({
  getInitialState: function() {
    return {liked: false};
  },
  handleClick: function(event) {
    this.setState({liked: !this.state.liked});
  },
  render: function() {
    var text = this.state.liked ? 'like' : 'haven\'t liked';
    return (
      <p onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </p>
    );
  }
});

ReactDOM.render(
  <LikeButton />,
  document.getElementById('test')
);

解释一下上面的代码:LikeButton 这个组件,他有一个getInitialState方法定义了初始状态,这也是一个对象,这个对象可以通过this.state属性读取。当用户点击组件的时候,状态发生了改变,this.setState方法用来进行状态的修改。每一次状态发生改变,就会自动的调用this.render方法,再次进行组件的渲染。
this.props表示哪些属性一旦被定义,就不能被修改;而this.state会随着用户的互动而大声变化的特性。

四、表单

用户在填写表单的时候,属于用户和组件之间的互动,所以不能用this.props来进行读取。

var Input = React.createClass({
  getInitialState: function() {
    return {value: 'Hello!'};
  },
  handleChange: function(event) {
    this.setState({value: event.target.value});
  },
  render: function () {
    var value = this.state.value;
    return (
      <div>
        <input type="text" value={value} onChange={this.handleChange} />
        <p>{value}</p>
      </div>
    );
  }
});

ReactDOM.render(<Input/>, document.body);

文本框中的值,不能用this.props.value来进行读取,而要定义一个onchange事件的回调函数。通过 event.target.value来读取用户输入的值。

五、组件的生命周期

组件的声明周期主要分为3个状态:
Mounting:这个是已经插入的DOM
Updating:正在被重新渲染
Unmounting:已移除的真实DOM
React 为每个状态都提供了两种处理函数,will函数在进入状态之前调用,did函数在进入状态之后调用,三种状态共计五种处理函数。

componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()

React 还提供两种特殊状态的处理函数。

componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用

var Hello = React.createClass({
  getInitialState: function () {
    return {
      opacity: 1.0
    };
  },

  componentDidMount: function () {
    this.timer = setInterval(function () {
      var opacity = this.state.opacity;
      opacity -= .05;
      if (opacity < 0.1) {
        opacity = 1.0;
      }
      this.setState({
        opacity: opacity
      });
    }.bind(this), 100);
  },

  render: function () {
    return (
      <div style={{opacity: this.state.opacity}}>
        Hello {this.props.name}
      </div>
    );
  }
});

ReactDOM.render(
  <Hello name="world"/>,
  document.body
);

did函数在进入状态之后调用,我们在这里调用了 componentDidMount 的方法,也就是在hello组件加载之后,然后在 componentDidMount 方法中设置一个定时器,这个定时器的目的是每隔100毫秒,但是在透明图小于一定值的话,就会重新的渲染。
我们注意到我们对样式的定义是 style={{opacity: this.state.opacity}} ,而不是style="opacity:{this.state.opacity};" ,因为react的组件的样式实质上是一个对象,所以第一重大括号表示的是js的语法,第二重大括号表示的是对象。

Ajax
对于组件的数据来源,通常是通过Ajax请求在服务器获取的,我们依旧可以通过componentDidMount方法来设置Ajax请求,等到请求成功的时候,再使用this.setState方法重新渲染UI。

var UserGist = React.createClass({
  getInitialState: function() {
    return {
      username: '',
      lastGistUrl: ''
    };
  },

  componentDidMount: function() {
    $.get(this.props.source, function(result) {
      var lastGist = result[0];
      if (this.isMounted()) {
        this.setState({
          username: lastGist.owner.login,
          lastGistUrl: lastGist.html_url
        });
      }
    }.bind(this));
  },

  render: function() {
    return (
      <div>
        {this.state.username}'s last gist is
        <a href={this.state.lastGistUrl}>here</a>.
      </div>
    );
  }
});

ReactDOM.render(
  <UserGist source="https://api.github.com/users/octocat/gists" />,
  document.body
);

上面的代码的实现是使用 jquery 来完成 Ajax 的请求,这也就很方便的说明了。react本身是没有任何的依赖的,我们可以不使用 jquery 而是使用其他的库。
我们现在比较经常使用的是使用 promise 来进行操作,而且我们通过查看promise的状态来返回了不同的信息。

var RepoList = React.createClass({
  getInitialState: function() {
    return { loading: true, error: null, data: null};
  },

  componentDidMount() {
    this.props.promise.then(
      value => this.setState({loading: false, data: value}),
      error => this.setState({loading: false, error: error}));
  },

  render: function() {
    if (this.state.loading) {
      return <span>Loading...</span>;
    }
    else if (this.state.error !== null) {
      return <span>Error: {this.state.error.message}</span>;
    }
    else {
      var repos = this.state.data.items;
      var repoList = repos.map(function (repo) {
        return (
          <li>
            <a href={repo.html_url}>{repo.name}</a> ({repo.stargazers_count} stars) <br/> {repo.description}
          </li>
        );
      });
      return (
        <main>
          <h1>Most Popular JavaScript Projects in Github</h1>
          <ol>{repoList}</ol>
        </main>
      );
    }
  }
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值