ReactJS入门

标签:前端开发 ReactJS


官网
官网中文镜像(推荐)
阮一峰老师的教程
菜鸟网的教程
一看就懂的ReactJS入门教程(语法有点过期了)

关键库:
react.js; react-dom.js; browser.min.js;


前言: ReactJS产生的原因背景

在Web开发中,我们总需要将变化的数据实时反应到UI上,这时就需要对DOM进行操作。而复杂或频繁的DOM操作通常是性能瓶颈产生的原因(如何进行高性能的复杂DOM操作通常是衡量一个前端开发人员技能的重要指标)。React为此引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。而且React能够批处理虚拟DOM的刷新,在一个事件循环(Event Loop)内的两次数据变化会被合并,例如你连续的先将节点内容从A变成B,然后又从B变成A,React会认为UI不发生任何变化,而如果通过手动控制,这种逻辑通常是极其复杂的。尽管每一次都需要构造完整的虚拟DOM树,但是因为虚拟DOM是内存数据,性能是极高的,而对实际DOM进行操作的仅仅是Diff部分,因而能达到提高性能的目的。这样,在保证性能的同时,开发者将不再需要关注某个数据的变化如何更新到一个或多个具体的DOM元素,而只需要关心在任意一个数据状态下,整个界面是如何Render的。
如果你像在90年代那样写过服务器端Render的纯Web页面那么应该知道,服务器端所要做的就是根据数据Render出HTML送到浏览器端。如果这时因为用户的一个点击需要改变某个状态文字,那么也是通过刷新整个页面来完成的。服务器端并不需要知道是哪一小段HTML发生了变化,而只需要根据数据刷新整个页面。换句话说,任何UI的变化都是通过整体刷新来完成的。而React将这种开发模式以高性能的方式带到了前端,每做一点界面的更新,你都可以认为刷新了整个页面。至于如何进行局部更新以保证性能,则是React框架要完成的事情。


1.代码生成标签,插入到指定位置

jsx/babel语言 JS,HTML混写

<body>  
   <div id="example"></div>  
   <script type="text/babel">     
    ReactDOM.render(
       <h2>Hello,world</h2>, 
      document.getElementById('example')
    );  
    </script>
</body>

div#example 作为容器存放生成的元素,
生成元素:ReactDOM.render(<tag>{codehere}</tag>, container);

注意:语句结尾可以不加分号,不会出错,有些语句加了分号之后就会出错,因此加分号要小心。


2.自定义标签(组件)

<script type="text/babel"> 
var MyTag = React.createClass({  
    render:function(){ return<h1>{this.props.name}</h1> }  
 }); //this.props.xxx 调用自定义属性;
ReactDOM.render(<MyTag name="zhe" />, document.getElementById('example') );  
</script> 

自定义标签要一定要用在render中,直接用在html无效。
后面demo为了方便就不写ReactDOM.render()了,实际练习时要加上
注意类名一定要首字母大写,createClass参数是一个对象,
添加组件属性,有一个地方需要注意,对于要调用class属性与for属性,属性名不能直接写 class 或者for,这是因为 class 和 for 是 JavaScript 的保留字。用className="" htmlFor=""代替,这样css一样可以.class找到该元素


3.可嵌套子元素的自定义标签

<script type="text/babel">
var MyList = React.createClass({  
     render:function(){ 
         return( 
          <ul>{ React.Children.map(this.props.children,
                 function(child){return<li>{child}</li>} ) }</ul>
         )} //注意大小写,props.children 用于获取子元素
});

// 使用
// <MyList> 
//  <span>item1</span> 
//  <span>item2</span>
//</MyList> 

</script>

一种映射的方法:array.map(function(item){console.log(item)})遍历array每次输出一个item。
另外如果数组是一系列标签,可以写在容器标签内自动展开,如<div>{array}</div>
React.Children.map该方法遍历children,而不用理会children因size不同(0,1,1+)而返回的不同类型(undefine,object, array)


4. 组件的参数检查与默认值

<script type="text/babel">
var MyTag = React.createClass({   
    getDefaultProps: function(){ return {title:"hello"}  }, //默认值   
    propTypes: {title: React.PropTypes.string.isRequired }, //表示title是必须,并且是字符串  
    render: function(){ return<h1>{this.props.title}</h1>} 
});

//<MyTag title={123} /> 控制台报错,但一样会显示在页面

</script>



5. 获取组件内部标签的DOM节点

内部标签定义一个ref属性,组件使用this.refs.xxx内获取节点

var MyInput = React.createClass({
    clickEvent:function(){ this.refs.tagInside.focus() }, //clickEvent的名字可随意   
    render:function(){ return(
       <div>
         <input type="text" ref="tagInside"/>
         <input type="button" value="focus" onClick={this.clickEvent} />
       </div> )  
     }
});


6. 组件的状态this.state

标记组件的状态,用于改变显示的文字,样式等。

var MyInput = React.createClass({
    getInitialState: function(){ return { liked: false } },//定义应有的状态与初始化,用键值对形式   
    clickEvent:function() { this.setState({liked: !this.state.liked }) },//this.setState({}) 改变状态值   
    render:function() { 
       var text =this.state.liked ? "liked" : "unliked"; 
       return<input type="button" value={text} onClick={this.clickEvent} />    
    }
});

每次setState后都会自动调用render,因此可以改变样式。
注意this.state与this.props的区别,state可以在交互中改变,可读可写,props定义了了就不能改变,只读。


7. 获取表单的输入

输入表单属于交互,改变this.state

var MyInput = React.createClass({
    getInitialState: function() { return {value: "default"} },   
    changeEvent:function(e) { this.setState({value: e.target.value}) },   
    render:functiion(){ return( 
      <div>  
        <input type="text" value={text} onChange={this.changeEvent} />    
        <p> {text}</p> 
      </div> )  
    } //注意大小写
});

因为每次改变状态都会调用render,因此如果input里的value设为常数,那么输入文本就不会显示改变


8. 组件的生命周期

分为 mounting: 已插入到真实的DOM中;
updating:被渲染中;
unmounting 已经移出真实的DOM
有两种回调函数:will 在进入某一步前调用,did进入某一步后调用,共5个

componentWillMount();
componentDidMount();
componentWillUpdate(oNextProps, oNextState);
componentDidUpdate(oPrevProps, oPrevState);
componentWillUnmount();

这个比较复杂,还是看官网比较好:https://facebook.github.io/react/docs/working-with-the-browser.html#component-lifecycle


9. AJAX

componentDidMount 中可以用jQuery.get() 实现,React 本身没有任何依赖,完全可以不用jQuery,而使用其他库。

<script type="text/babel">
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
);
</script>

10. 传入promise对象

<script type="text/babel">
    var RepoList = React.createClass({
        getInitialState: function() {return {loading:true, data:null, error:null}},
        componentDidMount: function() {
            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) {
                return <span>Error: {this.state.error.message} </span>
            } else {
                var repos = this.state.data.items;
                var list = repos.map(function(repo){
                    return (
                        <li> 
                            <a href={repo.html_url}> {repo.name} </a>
                             ({repo.stargazers_count} stars) <br/> 
                             {repo.description}
                        </li> ) 
                })
            }
            return (<div>
                      <h1>Most Popular JavaScript Projects in Github</h1>
                      <ol>{list}</ol>
                    </div>)

        }

    })

    ReactDOM.render(
        <RepoList promise={$.getJSON('https://api.github.com/search/repositories?q=javascript&sort=stars')} />,
        document.getElementById("example")
    )
    </script>

总结

上面是react的简单用法,更多更详细的解释请看官方文档。
react还可以配合flux框架使用,接下来可以学习这方面的相关知识。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容