React-基础教程完整版

目录:

1 组件和组件属性(Component and Props)

1.1 组件定义方式

React 基于组件开发,而组件可以使UI进行分离,并且高可复用性,从概念上来说,更像是 js 的函数,往组件传入参数(也就是 this.props)然后返回整个组件对象,通过 ReactDOM.render 渲染到网页中。

组件定义方式应该有三种:

  1. 函数式

    定义

    // test.html
    
    <div id="root"></div>
    
    <script type="text/babel">
    
    function Welcome( props ) {
          
        return (<h1>Hello React.js, {props.name}<br /></h1>);
    }
    
    </script>

    渲染

    ReactDOM.render( <Welcome name="Welcome" />, document.getELementById('root') );

    最终会输出结果:‘Hello React.js, Welcome’

    上面函数的参数 props 也就是组件 render 时候内部的一些属性值集合

    这种方式会发现并不需要组件函数中存在 render 方法,这个应该只在 类继承和React.createClass 中才需要。下面看看类继承方式

  2. 类继承

    类继承需要用到 ES6 语法中的 class,通过 React.Component 来创建被继承的组件对象,如下:

    类继承方式定义组件:(这里注意, React.Component 是个组件类,不是构造函数,直接使用 {} 即可)

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

    渲染方式都是一样的,通过组件名 Welcome 去渲染即可

    ReactDOM.render( <Welcome name="Welcome" />, document.getELementById('root') );

    最终结果和函数式组件定义一样

  3. React.createClass

    这里使用的是 React 自己的创建组件类的方法去实现,如果对 es6 不太熟悉的话,这种方式更容易接受点

    定义:

    var Welcome = React.createClass({
        render: function () {
         
            return (<h1>Hello React.js, {
        this.props.name}<br /></h1>);
        }
    });

    渲染:

    ReactDOM.render( <Welcome name="Welcome" />, document.getELementById('root') );

其实不管使用上面哪种方式,最后生成的组件在 DOM 树中呈现的结果都是一致的,如下:

<h1 data-reactid=".1">
    <span data-reactid=".1.0">Hello React.js, </span>
    <span data-reactid=".1.1">Welcome</span>
    <br data-reactid=".1.2">
</h1>

还有需要注意的是,不论上面那种方式,Welcome 组件名的首字母一定要大写,否则会报错,并且报错内容都是一样的:‘Uncaught ReferenceError: Welcome is not define’

我们看到上面的 ReactDOM.render 方法里面是直接传的组件形式,事实上 react 也只是变量,比如:

上面的 <Welcome name="Welcome" /> 可以定义成变量,再传入到渲染函数

const element = <Welcome name="Welcome" />;

ReactDOM.render( element, document.getElementById( 'root' ) );

结果显示上面方式也是 OK 的,那后面的 id 肯定也是可以通过变量传入的,最后就变成如下:

const element = <Welcome name="Welcome" />;
const id = document.getElementById( 'root' );

ReactDOM.render( element, id );

这样是不是就清爽许多了……

从官文上有一段注意点:

Caveat:
Always start component names with a capital letter.
For example,

represents a DOM tag, but represents a component and requires Welcome to be in scope.

这里也说明了为什么组件首字母要大小写原因之一:意思就是说 react 会把消息开头的当作 DOM 标签,而把大写开头的才会当成是个组件名称。

1.2 组件嵌套使用

由于组件一旦定义完成,它就是个以独立的个体形式存在,也就是说它可以被单独渲染到 DOM 树中,同时也可以被其它组件引用,作为其输出,并且支持多次使用

如示例:(不仅被其他组件引用,还能多次重复使用)

// test.html

// Welcome 组件上面已经定义好,直接拿来使用即可

var Wrap = React.createClass({
    return (
        <div>
            <Welcome name="Lizc" />
            <Welcome name="Fll" />
            <Welcome name="Liwy" />
        </div>
    );
});

const element = <Wrap />;
const id      = document.getElementById( 'root' );

ReactDOM.render( element, id );

输出结果:

Hello React.js, Lizc

Hello React.js, Fll

Hello React.js, Liwy

1.3 提取组件

官文上有这么一句话:‘Don’t be afraid to split components into smaller components.’
意思就是告诉我们不要害怕将组件分割成更小的组件,也就是说我们可以根据我们的需求尽可能的将内容进行组件化,我们来看下官网的示例程序

// extract-component.html

// 样式
<style>
    .avatar {
        width : 100px;
        height : 100px;
    }   
</style>

// 脚本
<script type="text/babel">

    const rootEle = document.getElementById( 'root' );

    var Comment = React.createClass({

        render: function () {
     
            return (
                <div className="comment">
                    <div className="user-info">
                        <img className="avatar" 
                            src={this.props.author.avatarUrl} 
                            alt={this.props.author.name}
                        />
                    </div>
                    <div className="user-info-name">
                        作者:{this.props.author.name}
                    </div>
                    <div className="comment-text">
                        问候语:{this.props.text}
                    </div>
                    <div className="comment-date">
                        日期:{this.props.date}
                    </div>
                </div>
            );
        }
    });

    var element = <Comment 
            author={
   { avatarUrl:'./images/ygr-01.jpg', name: 'lizc' }} 
            text='hello react.js' 
            date={
    new Date().toString()}
        />

    ReactDOM.render( element, rootEle );
</script>

从上面的 Comment 组件看,其实里面包含四个部分(头像,作者,问候语,日期),本着官文给我们的注解,尽可能的组件化,那么这四个部分也就应该成为独立的组件,下面来实现下这四个组件,而数据这块,依然采用父组件中的属性

这里只是个示范,更多的组件化可以根据自己的需求来进行分割

  1. 头像组件

    // extract-component.html
    
    // 父组件
    var Comment = React.createClass({
    
        render: function () {
         
            return (
                // 父组件 Comment 中引用子组件:头像组件(AvatarComp)
                <div className="comment">
                    <AvatarComp author={
        this.props.author} />
    
                    // ... 其他
                </div>
            );
        }
    
    });
    
    // 子组件
    var AvatarComp = React.createClass({
        render: function () {
         
            return (
                <div className="user-info">
                    <img className="avatar" 
                        src={
        this.props.author.avatarUrl} 
                        alt={
        this.props.author.name}
                    />
                </div>
            );  
        }
    });

    最终运行结果和之前一致,说明头像组件化成功,另外可以发现,我们的 AvatarComp 组件是定义在父组件 Comment 之后的,但是依然可以运行。

  2. 作者组件

    作者组件:

    // 父组件中引用作者组件
    <AuthorComp name={
        this.props.author.name} />
    
    var AuthorComp = React.createClass({
        render: function () {
         
            return (
                <div className="user-info-name">
                    作者:{
        this.props.name}
                </div>
            );
        }
    });
    
  3. 问候语组件

    var WelcomeComp = React.createClass({
        render: function () {
         
            return (
                <div className="comment-text">
                    问候语:{
        this.props.text}
                </div>
            );
        }
    });
    
    // 引用
    <WelcomeComp text={
        this.props.text} />
  4. 日期组件

    var DateComp = React.createClass({
        render: function () {
         
            return (
                <div className="comment-date">
                    日期:{
        this.props.date}
                </div>
            );
        }
    });
    
    // 引用
    <DateComp date={
        new Date().toString()} />

最终完整代码:虽然在代码量上貌似多了点,可是这样依赖每个功能都成为了单独的一个组件,可以在任何地方使用它,而父组件中直接引用子组件,也让父组件更容易维护,修改,并且更加直观,总之好处多多。

<script type="text/babel">

    const rootEle = document.getElementById( 'root' );

    var Comment = React.createClass({

        render: function () {
   
            return (
                <div className="comment">
                    <AvatarComp author={
  this.props.author} />
                    <AuthorComp name={
  this.props.author.name} />
                    <WelcomeComp text={
  this.props.text} />
                    <DateComp date={
  new Date().toString()} />
                </div>
            );
        }
    });

    var AvatarComp = React.createClass({
        render: function () {
   
            return (
                <div className="user-info">
                    <img className="avatar" 
                        src={
  this.props.author.avatarUrl} 
                        alt={
  this.props.author.name}
                    />
                </div>
            );  
        }
    });

    var AuthorComp = React.createClass({
        render: function () {
   
            return (
                <div className="user-info-name">
                    作者:{
  this.props.name}
                </div>
            );
        }
    });

    var WelcomeComp = React.createClass({
        render: function () {
   
            return (
                <div className="comment-text">
                    问候语:{
  this.props.text}
                </div>
            );
        }
    });

    var DateComp = React.createClass({
        render: function () {
   
            return (
                <div className="comment-date">
                    日期:{
  this.props.date}
                </div>
            );
        }
    });

    var element = <Comment 
            author={
  { avatarUrl:'./images/ygr-01.jpg', name: 'lizc' }} 
            text='hello react.js' 
            date={
  new Date().toString()}
        />

    ReactDOM.render( element, rootEle );
</script>

2 状态和声明周期(State and LifeCycle)

2.1 状态值

React 的数据传递都是单向传递的,而对于需要变化的值,则是通过 state 对象来控制,比如下面的时钟例子,就是通过每秒更新 state 状态的值去刷新显示结果

这有个时钟计时的组件示例:

// lifecycle-state.html

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若叶岂知秋vip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值