美文网首页React NativeJavaScript学习
React,我从未见过如此好看的教程(1)

React,我从未见过如此好看的教程(1)

作者: Nodelover | 来源:发表于2015-11-03 17:10 被阅读27560次
    跟我一起学 React 😄,只为了缓解大家学习React的痛苦。
    懂得也不多,所以有神马我理解错误的地方,请指正。
    React 各大BAT都在用的框架,学到就是赚到。
    

    这是我的 Learn 笔记,同样也是一份简明教程。

    列一下资料:
    React英文版指南

    # 先来准备一个基本页面
    已经替换为国内的 CDN。
    react.js -> React主要核心
    react-dom.js -> React DOM 操作
    browser.min.js -> 将 babel 转换成浏览器可用的 ES5
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>Hello React</title>
        <script src="http://cdn.bootcss.com/react/0.14.1/react.js"></script>
        <script src="http://cdn.bootcss.com/react/0.14.1/react-dom.js"></script>
        <script src="http://cdn.bootcss.com/babel-core/5.8.32/browser.min.js"></script>
      </head>
      <body>
        <div id="example"></div>
        <script type="text/babel">
    
          // ** Your code goes here! **
    
        </script>
      </body>
    </html>
    
    # 写一个简单时间(它看起来想这样)
     props -> properties 属性们
     render -> 渲染
     ReactDom.render(实例化的组件,要渲染到得对象)
    
     在HelloWorld组件中,传入了一个data属性,对应的是一个Date对象。
     在组件中,通过 this.props.date 拿到Date对象,调用它的toTimeString方法。
     而且本例中我们是用了一个定时器,每500ms我们实例化渲染一次组件,更新时间的值。
     <HelloWorld date={new Date()}/> 这是jsx语法,有点类似于HTML5自定义语义标签吧。
     可以这么理解,每一个标签就是一个组件,一个对象,因为我们是用的React.createClass方法去创建的,从方法名上就可以看出。
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>Hello React</title>
        <script src="http://cdn.bootcss.com/react/0.14.1/react.js"></script>
        <script src="http://cdn.bootcss.com/react/0.14.1/react-dom.js"></script>
        <script src="http://cdn.bootcss.com/babel-core/5.8.32/browser.min.js"></script>
    
      </head>
      <body>
        <div id="example"></div>
        <script type="text/babel">
    
          var HelloWorld = React.createClass({
            render: function() {
              return (
                <p>
                  你好, <input type="text" placeholder="输入你的名字"/>! <br/><br/>
                  现在的时间是:{this.props.date.toTimeString()}
                </p>
              );
            }
          });
    
          setInterval(function() {
            ReactDOM.render(
              <HelloWorld date={new Date()}/>,
              document.getElementById('example')
            );
          }, 500);
    
        </script>
      </body>
    </html>
    
    # 让我们细化知识点吧(JSX语法)
    var myDivElement = <div className="foo" />;
    // className 就代表 class属性,因为怕属性冲突,所有就另外给了一个名字。
    ReactDOM.render(
      myDivElement, 
      document.getElementById('example')
    );
    
    // 输入:
    React.createElement(Profile, null, "click")
    // 转义输出为:
    <Profile>click</Profile>
    
    var Nav, Profile;
    // 输入 (JSX):
    var app = <Nav color="blue"><Profile>click</Profile></Nav>;
    
    // 转义输出为 (JS):
    var app = React.createElement(
      Nav,
      {color:"blue"},
      React.createElement(Profile, null, "click")
    );
    
    # 组件的命名空间(JSX语法)
    // App组件就把这几个组件整合,打包起来了。
    var Form = MyFormComponent;
    var FormRow = Form.Row;
    var FormLabel = Form.Label;
    var FormInput = Form.Input;
    
    var App = (
      <Form>
        <FormRow>
          <FormLabel />
          <FormInput />
        </FormRow>
      </Form>
    );
    
    //用子组件的方式去整合打包
    var MyFormComponent = React.createClass({ ... });
    
    MyFormComponent.Row = React.createClass({ ... });
    MyFormComponent.Label = React.createClass({ ... });
    MyFormComponent.Input = React.createClass({ ... });
    
    //使用 React.createElement 的第三个参数
    var App = (
      React.createElement(Form, null,
        React.createElement(Form.Row, null,
          React.createElement(Form.Label, null),
          React.createElement(Form.Input, null)
        )
      )
    );
    
    # 布尔属性、表达式与注释(JSX语法)
    // 禁用样式的按钮
    <input type="button" disabled />;
    <input type="button" disabled={true} />;
    
    // 正常使用的按钮
    <input type="button" />;
    <input type="button" disabled={false} />;
    
    // 输入 (JSX):
    var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
    // 三元运算符,window.isLoggedIn 存在输出<Nav />组件,否则输出<Login/>组件
    
    // 输出 (JS):
    var content = React.createElement(
      Container,
      null,
      window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
    );
    
    
    var content = (
      <Nav>
        {/* 子组件注释,加上 {} 花括号 */}
        <Person
          /* 组件
             属性
             注释
           */
          name={window.isLoggedIn ? window.name : ''} // end of line comment
        />
      </Nav>
    );
    
    # 属性传入组件的多种方式(JSX语法)
    //变量放在{}中
    var component = <Component foo={x} bar={y} />;
    
    
    var component = <Component />;
    component.props.foo = x; // 不推荐,最丑的做法
    component.props.bar = y; // 不推荐,颜值低得人可以这么干
    
    //传入对象的方式传入属性
    var props = {};
    props.foo = x;
    props.bar = y;
    var component = <Component {...props} />;
    
    //注意,后面会覆盖前面的
    var props = { foo: 'default' };
    var component = <Component {...props} foo={'override'} />;
    console.log(component.props.foo); // 输出为'override'
    
    # JSX 陷阱(JSX做了一些处理防止XSS攻击)
    // 会显示 “First · Second” 
    <div>{'First · Second'}</div>
    
    // 它会显示 "First · Second"
    <div>First · Second</div>
    
    // 正确做法,帅的人都这么干
    <div>{'First \u00b7 Second'}</div>
    <div>{'First ' + String.fromCharCode(183) + ' Second'}</div>
    // 同时你还可以这样玩,加上[],以数组的形式。
    <div>{['First ', <span>·</span>, ' Second']}</div>
    
    //但是有的适合,我的项目中就需要这样干,就要原来的。
    //给dangerouslySetInnerHTML传入一个对象,其中有一个__html属性,其中写了你的文本。
    <div dangerouslySetInnerHTML={{__html: 'First · Second'}} />
    
    //假如你想加上自定义属性,必须加上data-前缀
    //以aria-开头的属性页可以被渲染出来
    <div data-custom-attribute="foo" />
    <div aria-hidden={true} />
    
    # 组件生命周期(别纠结这是干什么,纠结你就输了,先看一看文字,不用去弄懂他们,跳过都行,细节后面在讲解)
    初始化阶段
    getDefaultPropos:只调用一次,实力之间共享引用
    getInitialState:初始化每个实例特有的状态
    componentWillMount:render之前最后一次修改状态的机会
    render:只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出
    componentDidMount:成功render并渲染完成真实DOM后触发,可以修改DOM
    
    运行中阶段
    componentWillReceiveProps:父组件修改属性触发,可以修改新属性,修改状态
    shouldComponentUpdate:返回false会阻止render调用
    componentWillUpeate:不能修改属性和状态
    render:只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出
    componentDidUpdate:可以修改DOM
    
    销毁阶段:
    componentWillUnMount:在删除组件之前进行清理操作,比如计时器和事件监听器。
    

    附上一些我当初的截图笔记,可以看出他们运行顺序(当初用的是JSX转换库):

    初始化阶段

    <script type="text/jsx">
    $(function(){
          var count = 0;
          var style={
            color:"red",
            border:"1px #000 solid"
          };
          var HelloWorld = React.createClass({
            getDefaultProps:function(){
              console.log(1);
              return {name:"Yugo"};
            },
            getInitialState:function(){
              console.log(2);
              return {
                  myCount: count = count+1 ,
                  ready: "false"
                };
            },
            componentWillMount:function(){
              console.log(3);
              // 修改状态
              this.setState({ready:"true"});
              },
            render:function(){
              console.log(4);
              return <p ref="childp">Hello,{this.props.name?this.props.name:"World"}<br/> {this.state.ready} {this.state.myCount}</p>;
            },
            componentDidMount:function(){
              console.log(5);
              //改变DOM
              $(React.findDOMNode(this)).append("666666");
            },
          })
          React.render(<div style={style}><HelloWorld></HelloWorld></div>,document.body)
    });
    </script>
    
    初始化阶段事件顺序

    运行中阶段

         var style={
            color:"red",
            border:"1px #000 solid"
          };
          var HelloWorld = React.createClass({
              componentWillReceiveProps:function(){console.log(1);},
              shouldComponentUpdate:function(){console.log(2);return true;},
              componentWillUpdate:function(){console.log(3);},
              render:function(){
                console.log(4);
                return <p>Hello,{this.props.name?this.props.name:"World"}</p>;
              },
              componentDidUpdate:function(){console.log(5);},
          });
          var HelloUniverse = React.createClass({
            getInitialState:function(){
              return {name:''};
            },
            handleChange:function(event){
              this.setState({name: event.target.value})
            },
            render:function(){
              return <div>
              <HelloWorld name={this.state.name}></HelloWorld>
              <br/>
              <input type="text" onChange={this.handleChange} />
              </div>
            },
          });
          React.render(<div style={style}><HelloUniverse></HelloUniverse></div>,document.body)
    
    运行中阶段事件顺序

    销毁阶段

     var style={
            color:"red",
            border:"1px #000 solid"
          };
          var HelloWorld = React.createClass({
              render:function(){
                console.log(4);
                return <p>Hello,{this.props.name?this.props.name:"World"}</p>;
              },
              componentWillUnmount:function(){
                console.log("Delete`````````!");
              },
          });
          var HelloUniverse = React.createClass({
            getInitialState:function(){
              return {name:''};
            },
            handleChange:function(event){
              if(event.target.value == 123){
                React.unmountComponentAtNode(document.body);
                return;
              }
              this.setState({name: event.target.value})
            },
            render:function(){
              return <div>
              <HelloWorld name={this.state.name}></HelloWorld>
              <br/>
              <input type="text" onChange={this.handleChange} />
              </div>
            },
          });
          React.render(<div style={style}><HelloUniverse></HelloUniverse></div>,document.body)
    
    销毁阶段
    # 来一个简单小栗子(根据状态去做不同的行为)
    state -> 状态
    React.createClass方法,我们是传入的一个对象。
    而这个对象的生命周期分为三个,初始化、运行中、销毁阶段。
    再介个栗子中,getInitialState是属于初始化阶段的。
    他返回了一个对象,这个对象中包含组件的状态。
    我们可以通过this.state去获得这个对象。
    通过setState(data, callback)方法去设置状态,同样是传入对象。
    onClick就是鼠标单击事件喽,鼠标单击执行自定义函数handleClick。
    
    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('example')
    );
    
    什么时候使用状态(百度翻译了一下原文)?
    你的大部分组件应该只需从props中取一些数据并渲染它。然而,
    有时你需要对用户输入、服务器请求或时间的推移作出反应。为此您使用state状态。
    尽可能保持尽可能多的组件成为可能的state状态。
    通过这样做,您将分离到它最合乎逻辑的地方,并尽量减少冗余。
    一个常见的模式是创建多个无状态的组件,只是提供props数据,
    并有一个有state状态的组件上面,通过其state状态通过子组件的层次。
    有状态组件封装了所有的交互逻辑,而无状态的组件专注呈现数据。
    建设一个有状态的组件时,考虑其状态的最小可能性,
    this.state应该只包含需要代表你的UI状态的最小数据量,不要包含计算数据、反应元件(基于基本的道具和状态建立他们)
    

    用我自己的话说吧(2个小栗子):
    我能吐槽这个最小可能性,和最小数据量吗?


    
    当需要改变组件的行为的时候,我们可能要去判断状态。
    🌰一:有病状态就该吃药,没病也别没事瞎嗑药,容易出事,但是有病的还是少数人。
    
    🌰二:师傅有五个徒弟,分为大师兄徒弟(武力值最高),和其他徒弟俩类。
    师傅出去云游,估计某处青楼里创作惊世神功,大师兄通常是代理师傅。根据门派的状态去给其他师弟师妹派任务。
    大师兄:二师弟,厨房木有米了,你负责下山去买米。
           只见大师兄拿出笔和纸,写了一大页满的。考虑到师傅10年后回来的概率(20%),与各位师兄弟的饭量,刚刚好200万。
           买200万斤吧!,多一斤也不要,我就要这个最小数据量,不包含其他算法处理,不要因为价格,带的钱不够,就买少了,就要实实在在的这么多,带上神兽麒麟,驼回来,考虑到200年之后没米吃,对,就这么干。
           还有你不要有反应元件,我知道你比较冲动,不能用为老板给的价格不合理,你就砍了他,咱门派的人不乱杀人,摊上事了,别冲动,好好解决。跟他谈个好几年的价格也是可以的。
    二师弟:( ⊙ o ⊙ )啊!!!,师兄高瞻远就,我这就去办。
          (尼玛,考虑最小可能性也没必要这么干吧,200年啊!!!,还最小数据量,尼玛怎么算得啊!拉格朗日一下就出来了?)
    大师兄:三师妹,你就负责服侍大师兄我吧!来,先捶捶腿。
    三师妹:~~~~(>_<)~~~~ 
    大师兄:四师弟,马桶堵了,你去掏马桶。
    四师弟:哦!(逼了狗了~,还不如买米去。)
    大师兄:五师弟,念你年纪小,上山去砍柴,多锻炼才能长得结实。
    五师弟:.....(默默背上柴刀走了)
    故事就是这样,这个故事告诉我们,要么做大师兄,要么回家种田。
    (管事的,管状态的越少越好,一个最好,这样才不会乱。)
    
    # 看看大师兄和师弟们是如何协作的。

    介个是一个评论中的头像组件

    // Avatar组件包含2个子组件 ProfilePic、ProfileLink。
    // ProfilePic:个人头像
    // ProfileLink:个人主页链接
    // Avatar组件传入了username属性props
    // 通过 this.props.username 再传递给子组件
    var Avatar = React.createClass({
      render: function() {
        return (
          <div>
            <ProfilePic username={this.props.username} />
            <ProfileLink username={this.props.username} />
          </div>
        );
      }
    });
    
    var ProfilePic = React.createClass({
      render: function() {
        return (
          <img src={'https://graph.facebook.com/' + this.props.username + '/picture'} />
        );
      }
    });
    
    var ProfileLink = React.createClass({
      render: function() {
        return (
          <a href={'https://www.facebook.com/' + this.props.username}>
            {this.props.username}
          </a>
        );
      }
    });
    
    ReactDOM.render(
      <Avatar username="pwh" />,
      document.getElementById('example')
    );
    
    就如同大师兄知道没米,叫二师弟去买米。
    师傅留下麒麟,没带走,然后又交给二师弟去驮米一样。
    (不知道师傅回来会不会一巴掌打屎他)
    
    # 关于子组件
    <Parent><Child /></Parent>
    //通过 this.props.children 可以操作子组件
    
    // 第一次输出
    <Card>
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
    </Card>
    
    // 第二次更新输出
    <Card>
      <p>Paragraph 2</p>
    </Card>
    
    //Paragraph 1 将会被移除掉
    
    今天是第二天,时间是1点半。
    惆怅,今天11点钟起来,帮管朋友的Server2003服务器(老的不像样)挂掉了。
    最近逃课也经常被点到,我也是醉了。
    言归正传,继续学习。
    
    # 动态组件
    array.map(value)函数遍历一个数组。
    result.id 是起了标识作用
    
    render: function() {
        var results = this.props.results;
        return (
          <ol>
            {results.map(function(result) {
              return <li key={result.id}>{result.text}</li>;
            })}
          </ol>
        );
      }
    
    标识id应该在组件上,
    
    // 错误!丑的人都这样干,反正我是不这样干。
    var ListItemWrapper = React.createClass({
      render: function() {
        return <li key={this.props.data.id}>{this.props.data.text}</li>;
      }
    });
    var MyComponent = React.createClass({
      render: function() {
        return (
          <ul>
            {this.props.results.map(function(result) {
              return <ListItemWrapper data={result}/>;
            })}
          </ul>
        );
      }
    });
    
    // 正确 :)
    var ListItemWrapper = React.createClass({
      render: function() {
        return <li>{this.props.data.text}</li>;
      }
    });
    var MyComponent = React.createClass({
      render: function() {
        return (
          <ul>
            {this.props.results.map(function(result) {
               return <ListItemWrapper key={result.id} data={result}/>;
            })}
          </ul>
        );
      }
    });
    
    # PropTypes,类型约束
    为了性能考虑,只在开发环境验证 propTypes
    对于我这种没有队友的人来说,感觉鸡肋,多此一举,大家不喜欢就跳过吧~我也跳了。
    
    React.createClass({
      propTypes: {
        // 可以声明 prop 为指定的 JS 基本类型。默认
        // 情况下,这些 prop 都是可传可不传的。
        optionalArray: React.PropTypes.array,
        optionalBool: React.PropTypes.bool,
        optionalFunc: React.PropTypes.func,
        optionalNumber: React.PropTypes.number,
        optionalObject: React.PropTypes.object,
        optionalString: React.PropTypes.string,
    
        // 所有可以被渲染的对象:数字,
        // 字符串,DOM 元素或包含这些类型的数组。
        optionalNode: React.PropTypes.node,
    
        // React 元素
        optionalElement: React.PropTypes.element,
    
        // 用 JS 的 instanceof 操作符声明 prop 为类的实例。
        optionalMessage: React.PropTypes.instanceOf(Message),
    
        // 用 enum 来限制 prop 只接受指定的值。
        optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
    
        // 指定的多个对象类型中的一个
        optionalUnion: React.PropTypes.oneOfType([
          React.PropTypes.string,
          React.PropTypes.number,
          React.PropTypes.instanceOf(Message)
        ]),
    
        // 指定类型组成的数组
        optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
    
        // 指定类型的属性构成的对象
        optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
    
        // 特定形状参数的对象
        optionalObjectWithShape: React.PropTypes.shape({
          color: React.PropTypes.string,
          fontSize: React.PropTypes.number
        }),
    
        // 以后任意类型加上 `isRequired` 来使 prop 不可空。
        requiredFunc: React.PropTypes.func.isRequired,
    
        // 不可空的任意类型
        requiredAny: React.PropTypes.any.isRequired,
    
        // 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接
        // 使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
        customProp: function(props, propName, componentName) {
          if (!/matchme/.test(props[propName])) {
            return new Error('Validation failed!');
          }
        }
      },
    });
    
    
    # 把自身所有属性,传给子组件
    var CheckLink = React.createClass({
      render: function() {
        // 这样会把 CheckList 所有的 props 复制到 <a>
        return <a {...this.props}>{'√ '}{this.props.children}</a>;
      }
    });
    
    ReactDOM.render(
      <CheckLink href="/checked.html">
        Click here!
      </CheckLink>,
      document.getElementById('example')
    
    # Mixins(学过less、sass可能对这个比较熟悉)
    说白了这货就是一个代码块,在哪用,就原封不动复制到哪。
    不过要放在这个 mixins 对应的数组里面。
    假如传入的多个mixins里面包含多个生命周期函数。
    保证都会执行到得,首先按 mixin 引入顺序执行 mixin 里方法,
    最后执行组件内定义的方法。
    
    第一步,从getInitialState 得到初始化 seconds = 0
    第二步,componentWillMount 中给当前对象挂了一个intervals数组。
    第三步,render渲染模板到页面
    第四步,componentDidMount,DOM渲染完毕后。
           调用 this.setInterval(this.tick, 1000)。
    第五步,this.intervals.push(setInterval.apply(null, arguments));
           给intervals数组推入一个函数。里面一直就只有一个元素。
           至于为什么推入数组中,是为了闭包,更好的销毁。
           这个函数是系统的setInterval定时器函数。
           用apply触发,第一个参数是this代表的值,第二个是参数。
           setInterval是在全局window对象下面的。
           而当前环境的this,是 React 组件对象,所以才用apply方法。
           每一秒调用一次 this.tick,更新 seconds的状态值。
    第六步,更新状态重新渲染。       
    第七步,1秒后继续更新状态再渲染。
    
    在控制台中的输出顺序是: 1234563636363....
    
    var SetIntervalMixin = {
      componentWillMount: function() {
        console.log(2);
    
        this.intervals = [];
      },
      setInterval: function() {
        console.log(5);
    
        this.intervals.push(setInterval.apply(null, arguments));
      },
      componentWillUnmount: function() {
        console.log(7)
        this.intervals.map(clearInterval);
      }
    };
    
    var TickTock = React.createClass({
      mixins: [SetIntervalMixin], // 引用 mixin
      getInitialState: function() {
        console.log(1);
        return {seconds: 0};
      },
      componentDidMount: function() {
        console.log(4);
    
        this.setInterval(this.tick, 1000); // 调用 mixin 的方法
      },
      tick: function() {
        console.log(6);
    
        this.setState({seconds: this.state.seconds + 1});
      },
      render: function() {
        console.log(3);
        // console.log(this.intervals);
        return (
          <p>
            React has been running for {this.state.seconds} seconds.
          </p>
        );
      }
    });
    
    ReactDOM.render(
      <TickTock />,
      document.getElementById('example')
    );
    
    # 把自身部分传给子组件
    利用了ES6的析构特性
    var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
    x; // 1
    y; // 2
    z; // { a: 3, b: 4 }
    
    
    关于bind方法
    this.x = 9; 
    var module = {
      x: 81,
      getX: function() { return this.x; }
    };
    
    module.getX(); // 81
    
    var getX = module.getX;
    getX(); // 9, 因为在这个例子中,"this"指向全局对象
    
    // 创建一个'this'绑定到module的函数
    var boundGetX = getX.bind(module);
    boundGetX(); // 81
    
    var FancyCheckbox = React.createClass({
      render: function() {
        var { checked, ...other } = this.props;
        var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
        // `other` 包含 { onClick: console.log } 但 checked 属性除外
        return (
          <div {...other} className={fancyClass} />
        );
      }
    });
    ReactDOM.render(
      <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
        Hello world!
      </FancyCheckbox>,
      document.getElementById('example')
    );
    
    # 事件与表单组件
    event.target -> 代表事件产生的对象(事件目标)
    event.target.value -> 事件目标的value属性值
    
    //受限组件,你要是把值直接写成Value属性。
    //那你就什么都输入不了。
    var FancyCheckbox = React.createClass({
      render: function() {
        return <input type="text" value="Hello!" />;
      }
    });
    ReactDOM.render(
      <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
        Hello world!
      </FancyCheckbox>,
      document.getElementById('example')
    );
    
    //设置初始值用 defaultValue
     render: function() {
        return <input type="text" defaultValue="Hello!" />;
      }
    
    // 多选
      <select multiple={true} value={['B', 'C']}>
    
    // 这样使用更为优雅,这是一个受限组件
    <textarea name="description" value="This is a description." />
    
    //正确的做吧是把它定义为状态,当值改变触发更新
     getInitialState: function() {
        return {value: 'Hello!'};
      },
      handleChange: function(event) {
        this.setState({value: event.target.value});
      },
      render: function() {
        var value = this.state.value;
        return <input type="text" value={value} onChange={this.handleChange} />;
      }
    
    # React的虚拟DOM
    我们可以知道React显示出来是在render渲染到页面之后。
    而在之前的DOM标签全是虚拟的,所以才能让运行速度非常的快。
    但是我们也可以照样操作DOM,不过要等真实DOM渲染之后。
    
    # ref 属性
    <input ref="myInput" />
    var input = this.refs.myInput; // 得到实例
    // this.refs['myInput'] 也可以
    var inputValue = input.value; // 得到value属性值
    var inputRect = input.getBoundingClientRect();  //得到React实例
    
    ES6新特性
    (ref) => this.myTextInput = ref
    
    等于
    
    function(ref){
      return this.myTextInput = ref
    }
    
    var MyComponent = React.createClass({
      handleClick: function() {
        //使得实例获得焦点
        this.myTextInput.focus();
      },
      render: function() {
        // 假如ref是一个函数,那么会传一个this对象到为参数传进去
       //(好像这样才解释的通)
        return (
          <div>
            <input type="text" ref={(ref) => this.myTextInput = ref} />
            <input
              type="button"
              value="Focus the text input"
              onClick={this.handleClick}
            />
          </div>
        );
      }
    });
    
    ReactDOM.render(
      <MyComponent />,
      document.getElementById('example')
    );
    
    这几天,有点忙,老是被朋友叫去帮他们调试JSP,一调一晚上。
    对此事,我只想说一句,我在北方的寒夜里,玩着灵车漂移。
    突然想多看看视频,自己了解深刻一点在写。
    So Sorry!朋友们
    接下来会有React事件,Mixin深入(源码阅读,双向绑定),动画,尽请期待。
    

    相关文章

      网友评论

      • 839731219a2b:啥时候写React事件呢?:smile:
      • 昆吾kw:非常棒
      • Yi罐可乐:我确实从未见过如此好看 React 教程
      • eadd5a91ff4d:怎么把一个dom中的数据传到另一个dom,比如,第一个dom中有按钮,点击触发事件使用Ajax获取数据,然后需要把数据传到显示数据的那个dom中。
        Nodelover: @shmily笙箫 状态state,可以把父主件的状态作为属性props传给子主件,同时也可以把改变state的函数ajax作为属性传给子主件

      本文标题:React,我从未见过如此好看的教程(1)

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