React转小程序现状

React转小程序现状

2018/09/05 · JavaScript
· React,
小程序

原文出处: 司徒正美   

今昔做React转小程序,2个是taro,1个是anujs。

anujs的React小程序一伊始是群的纯正搞的,后来神烦IT狗接手。当我们想抄袭时,已经有一个可以运转的demo。taro这时声誉很大,但精神并不如意。小编讨论了好久taro的源码,发现能够采取tempate成分避开小程序的自定义组件不可以在构造器传参的难点,就正式动工了。

小程序的自定义组件不只怕在构造器传参的标题,
用过React的同班都了解,React的零部件构造器有多少个传参props与context,那都以react帮你传入的。props是JSX中同名的标签的性质组成的目标,context是上边组件的getChildContext()爆发的靶子的并集。而小程序的Component只是3个方法,你传什么它就有啥样,不会帮你加东西。

支出了大致有多少个星期,已经退出方正大大的源码。组件的笔触使用双模板机制——即用户编写时是React风格编写的(es6与jsx),通过大家一番神操作,它会发出多少个文件,第多少个是js文件,es5与createElement风格,类机制改由ReactWX的miniCreateClass方法完成,第1个是json配置对象,涉及路由的title与窗口颜色的概念,第多少个是wxml文件,大家将render方法的jsx抽取出来,变成那一个文件。

明日我们的React小程序有如下优势

  1. 支持npm安装
  2. 支持less与sass
  3. 支撑小程序的自带UI库
  4. 扶助在JSX直接使用p, div, i,
    b等HTML标签,它们会在wxml转换来view与text标签。
  5. 扶助在JSX中动用函数体与复杂的靶子传参,即onClick={function(){ console.log() }}onClick={this.changeAge.bind(this, index, {aaa:111,bbb: 222})}
  6. 支撑React完整的生命周期,并确保顺序。
  7. 对wx全体接口进行再一次包新,将回调风格转换到Promise风格

澳门葡京 1

anu的React转小程序的属性是有保障的,它不会mpvue或taro这样使用nextTick,而是在1个页面的杜撰DOM更新完才发一次setData。那样就防止了复杂data
diff与data 系列化。

小程序的setData质量很差,无法流传过大的目的,它会对data进行体系化。
因而一些转译框架会进展diff操作。但假使减缓它setData的效能,这一步就能够略去。

澳门葡京 2

事件系统上,匡助onXXX与catchXXX。catchXXX是效仿阻止事件冒泡完毕的API。微信小程序的校友说,用户事件是异步的,所以那里唯有定义式接口,没有进程式的

澳门葡京 3

澳门葡京 4

与React的差异

1.
微信小程序的轩然大波机制有瑕疵,不扶助stopPropagation与preventDefault。大家将e.detail当成事件目的,在它基础上添加type,target,touches,timeStamp等品质与空的stopPropagation与preventDefault方法
2.
事变的绑定,不要选用this.props.fn或this.state.fn,要用this.fn那种情势,微信在给模板填数据时,会对数码进行JSON.stringify,清掉全部事件。
3.
零件系统是根据小程序的template成分,由于不资助slot,由此不能运用{this.props.children}八面驶风显式的机件套嵌

  1. 不完整资助ref机制(refs可以放入组件实例,但不可以放DOM,因为没有DOM)
  2. 无状态组件还尚无落成
    6 还未曾援救findDOMNode
  3. 不支持render props
  4. 不支持dangerouslySetInnerHTML属性

有关组件标签套组件标签,须要合法的slot机制扶助,近来收获的死灰复燃是如此的:

澳门葡京 5

JSX是React的宗旨组成部分,它使用XML标记的措施去一直表明界面,界面组件之间能够互相嵌套。能够领略为在JS中编辑与XML类似的言语,一种概念带属性树结构(DOM结构)的语法,它的目标不是要在浏览器照旧引擎中贯彻,它的目的是由此各样编译器将这一个标记编译成标准的JS语言。

  1. react 基本概念解析
  2. react 的零件表明周期
  3. react 高阶组件,context, redux 等高档进阶

1.React 的上学财富

  • react官方首页
    https://facebook.github.io/react/

  • react中文
    http://reactjs.cn/react/index.html

  • React Gitbook 翻译
    https://hulufei.gitbooks.io/react-tutorial/content/introduction.html

  • react粤语导航
    http://nav.react-china.org/

  • jsx首页
    https://facebook.github.io/jsx/

  • react教程
    http://www.runoob.com/react/react-tutorial.html

  • 现阶段各大商厦的接纳景况
    https://github.com/facebook/react/wiki/Sites-Using-React

使用

从“RubyLouvre/anu下”
git clone下来, 命令行定义到packages/cli目录下,执行npm link
采纳mpreact <project-name> 创制工程
固定到 <project-name> 目录下 mpreact start 开端监听文件变化,
用微信开发工具打开当中的dist目录,本身收在src目录中展开开发.

小程序在它的体量还是1mb时,开发体验是很好的,品质也很好。但随着体量的范围松手了,产品经营早先乱搞,小程序原生的API与组件机制就跟不上了。不容许1个APP上有12个弹层,每两个都写一回啊。缺少继承是它的硬伤。事件机制与我们耳熟能详的编制差太远。createSelectQuery也布署得至极弱智,wxs过于奇怪。由此有了webview标签后,许五个人一向引入页面了。。。由此才有那般转译框架的出世,蕴涵TX内部的weby。

日前市面上许多转译框架是vue风格的,那对React技术栈的同学不公道,于是有了taro与anu的转译器。anu保留了虚拟DOM的模版,因而会比taro,mpvue更能突破小程序的桎棝。

1 赞 收藏
评论

澳门葡京 6

虽说你可以完全不利用JSX语法,只使用JS语法,但要么引进使用JSX,能够定义包涵属性的树状结构的语法,类似HTML标签那样的行使,而且更方便代码的翻阅。


2.React

什么是React?

  • React 是多个用来打造用户界面的 JAVASC卡宴IPT 库。
  • React主要用于打造UI,很四个人以为 React 是 MVC 中的 V(视图)。
  • React 起点于 Facebook 的中间项目,用来架设 Facebook 的网站,并于
    二〇一三 年 5 月开源。
  • React
    拥有较高的性质,代码逻辑万分简单,愈来愈多的人已初叶关心和拔取它。
  • 既可以支付浏览器采取,又有啥不可付出活动使用

React 特点

  • 1.表明式设计 −React采取注明范式,可以轻松描述应用。
  • 2.高效 −React通过对DOM的效仿,最大限度地压缩与DOM的竞相。
  • 3.灵活 −React可以与已知的库或框架很好地协作。
  • 4.JSX − JSX 是 JavaScript 语法的增添。React 开发不肯定使用 JSX
    ,但我们指出接纳它。
  • 5.组件 − 通过 React
    创设组件,使得代码特别不难获取复用,可以很好的拔取在大项目的支付中。
  • 6.单向响应的数目流 − React
    落成了一边响应的数据流,从而收缩了再也代码,那也是它为啥比古板数码绑定更简约。

什么是JSX?
React 使用 JSX(JavaScript XML) 来替代常规的 JavaScript。JSX
是贰个看起来很像 XML 的 JavaScript 语法增加。我们不须求一定使用
JSX,但它有以下优点:

  • JSX 执行更快,因为它在编译为 JavaScript 代码后开展了优化。
  • 它是项目安全的,在编译进度中就能发现错误。
  • 使用 JSX 编写模板尤其简明便捷。

运用JSX语法后,你不只怕不要引入babel的JSX解析器,把JSX转化成JS语法,这几个工作会由babel自动已毕。同时引入babel后,你就足以使用新的es6语法,babel会帮您把es6语法转化成es5语法,兼容更多的浏览器。

特意指示:

3.React的HelloWorld

打开网址:https://facebook.github.io/react/docs/installation.html
官网中有如何搭建React的Helloworld。
index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/react@latest/dist/react.js"></script>
    <script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
    <script type="text/babel" src="01.js"></script>

</head>
<body>
<div id="root"></div>

</body>
</html>

01.js:

//React组件化(可以重用),即自定义组件
class TextCompat extends React.Component{
    //组件的内容
    render(){
        return <div>Hello world!!!</div>
    }
}


class WrapperText extends React.Component{
    render(){
        //虚拟DOM(Document Object Model)
        //html标签,小写开头
        //自定义组件:大写开头
        return <p>
            <TextCompat></TextCompat>
            jarry
        </p>
    }
}


//绘制到页面中
//ReactDOM.render(<WrapperText></WrapperText>, document.body);
ReactDOM.render(<TextCompat/>, document.getElementById('root'));

流程:
1.编制组件
2.绘制到页面

ReactDOM.render(<TextCompat/>, document.getElementById('root'));

虚拟DOM
DOM:html标签
编造DOM即包蕴DOM又嵌套组件,和一般性DOM的分别:html标签是小写,组件是大写开端
虚拟DOM的好处:

  • 1.跨平台(讲虚拟DOM翻译成对应平台的言语)
  • 2.组件化管理,适合大型项目

缺点:

咱俩从最简单易行的2个官网例子helloworld开首:

  1. 新本子更新
    React转小程序现状。React.createClass({ ….. }) 为es5 的写法,新版已经被放弃
    class { ….. } 为 es6 的写法,推荐应用

  2. create-react-app 工程为电动创制新 react
    工程的工具项目,该工具蕴含了包装、 测试、sourceMap、等职能。

  3. react 使用全家桶( react 项目中不可或缺的工具 )
    React 在付出/生产 阶段须要一大堆的工具库帮忙开发
    编译:babel
    动静管理工具:redux
    单页应用:react-route

  4. dangerouslySetInnerHTML 用于安装不受爱戴的HTML
    <div dangerouslySetInnerHTML = {{ __html:
    this.state.不受爱惜的代码片段 }}></div>

  5. 好的 React 命名习惯

    • 自定义的零部件使用 首字母大写的驼峰命名 (eg:
      InputComponent….. )
    • 自定义的习性使用 小驼峰命名 ( eg: this.state.getDate….. )
    • 事件尽恐怕以 handle… 先河命名 (eg: handleChange….)
    • 组件私有的自定方法以下划线 _….. 开端命名 (eg:
      _getLocalDate…… )
  6. react 概念大全
    事件系统 + 表单应用 + 样式处理 + 组件通信 + 组件抽象 +
    组件品质优化 + 动画 + 自动化测试

4.React的状态

State(状态)
React 把组件看成是多少个状态机(State
Machines)。通过与用户的互相,落成差异情状,然后渲染
UI,让用户界面和数目保持一致。
React 里,只需革新组件的 state,然后依据新的 state
重新渲染用户界面(不要操作 DOM)。
不要求间接操作DOM,而是经过改动state,自动更新界面

1.起头化状态
2.变更状态
3.获取状态,当状态改变的时候,会重绘页面

只顾必要设置React dev tools的插件,来查阅错误日志
急需用React.createClass,而不是用持续的办法,因为那一个会走生命周期流程。

案例:
点击切换,喜欢不希罕?

//实例化组件对象过程中,调用getInitialState设置state对象的初始值
var Text = React.createClass({
    //设置状态的初始值
    getInitialState : function(){
        return {isLike:false};
    },
    //点击事件回调
    handleClick : function(){
        //改变状态
        this.setState({isLike:!this.state.isLike});
    },
    //当状态改变时,会重新调用render函数,重绘
    render : function(){
        //获取状态
        var text = this.state.isLike ? "喜欢" : "不喜欢";
        return <p onClick={this.handleClick}>你{text}吗?</p>
    }
});

ReactDOM.render(<Text/>, document.getElementById("myDiv"));

上边例子的加载流程:
1.getInitialState(开始化,设置组件的state的值,给了多个对象)
2.render(不喜欢)

点击之后的流水线
1.handleClick(点击回调)
2.setState(改变状态)
3.render(喜欢)

  <!DOCTYPE html>
    <html>
    <head>
      <meta charset="UTF-8" />
      <title>Hello React!</title>
      <script src="vendor-js/react.js"></script>
      <script src="vendor-js/react-dom.js"></script>
      <script src="vendor-js/babel-core/browser.min.js"></script>
    </head>
    <body>
      <div id="example"></div>
      <script type="text/babel">
        ReactDOM.render(
          <h1>Hello, world!</h1>,
          document.getElementById('example')
        );
      </script>
    </body>
  </html>
一:react 基本概念解析

  1. react 描述 DOM 的 格局 (JSX)jsx 其实就是 JavaScript 对象
  • 在 javascript 中应用类似于 HTML 结构和新闻的语法为 JSX 语法。

    很容易转换编译成为 于 HTML 信息的 JavaScript 表示形式( `HTML 的 对象形式` )。
    
    可以根据平台 编译成为 第三方页面 UI 结构
    

澳门葡京 7

jsx编译进度.png

  • ReactDOM 解析
    ReactDOM 是 react 提供的 WEB 页面打造对, 在 移动端 该目的是
    ReactApp
    ReactDom 有五个办法:
    findDomNode( this ) // 用于获取页面中的DOM 成分
    UnmountComponentAtNode()
    render() // 用于页面渲染

  • ref 和 findDomNode 获取页面成分辨析
    ref 添加到 Component 上得到的是 Component 实例,
    ref 添加在 原生的 HTML 上收获的是 DOM 节点

        findDomNode 当参数是 DOM 时 就返回一个 DOM( 貌似没什么用 )
        findDomNode 当参数是 Component 时返回 Component 中的 render 中的 DOM
    
        <div>
            <div ref={div => {
                  this._div = div
                 }}>app
            </div>
            <Child ref={child => this._child = child}/>
            <button onClick={()=> {
                        console.log(ReactDOM.findDOMNode(this._div) === this._div);
                        console.log(ReactDOM.findDOMNode(this._child));
                 }}>log refs
            </button>
        </div>
    

    特点

    1. react 使用 jsx 描述 DOM / UI 结构
    2. jsx 预防在编译阶段 会转换为 DOM 的 JavaScript 表现格局
    3. ReactDom 对象唯有一个效果 —> 负责将 JavaScript 对象
      渲染成为 真正的页面 DOM
    4. 在渲染进程中 react-dom( web ) ,react-canvas( canvas )
      ,react-app (react-native) 可分别将该 JS 对象渲染到不一样的平台上
  1. render 函数中都可以写什么

render 函数能且不得不 再次来到贰个 jsx 对象, 就是必须 重回三个值,并且那些值
是三个 类似于 DOM 的 jsx 语法

  • jsx 结构中可以采用 { } ( 大括号 ) 插入 表明式

    { } 大括号中 可以放置任何表明式内容( 包蕴 函数,jsx
    结构,变量,对象,表明计算式 )

      ...
      render () {
          const isGoodWord = true
          return (
                      <div>
                            React 小书
                            {
                                // jsx 中的注释 只能写在 大括号中
                                // 下面表示一个三目表达式
                                // 这里不能写 JavaScript 的 多行表达式
                                isGoodWord ? <strong> is good</strong> :  is not good 
                            }
                            {
                                  // 下面表示一个自执行函数,函数中可以做任何你想做的事,也可以有多行代码
                                 (function() {
                                           .... doSomething
                                 })
                            }
                      </div>
                  )
      }
      ...
    
  • jsx 结构中的 null
    表示什么都不出示,相当于忽略了该表明式的插入,可以利用这一个特性来 隐藏元素

  • jsx 结构完整当做变量用于 参数传递可能使用

    jsx 语法其实就是一个个 js
    的目标,所以可以应用其余变量能选拔的方法传递大概使用它们

     ...
      render () {
          const isGoodWord = true
          const goodWord = <strong> is good</strong>    // 这是一个 jsx 变量
          const badWord =  is not good   // jsx 变量还可以当做 函数参数传递
          return (
              <div>
                    React 小书
                    {isGoodWord ? goodWord : badWord}
              </div>
         )
      }
      ...
    
  • 在 render 的 {} 中 可以动用 map 等 返回 DOM LIST 的函数方法

      // 必须返回一个 表示 DOM LIST 
     const arr = [1, 2, 3, 4, 5];
     render () {
          return (
                <select>
                      this.arr.map((item) => 
                          <option>item</option>
                      )
                </select>
            )
      }
      ...
    
  • jsx 中的 安慕希表明式 其实就是一句完整的表明式,所以可以被 识别

  1. jsx 语法中 注释的写法

    评释只好写在 JavaScript 表明体 中( 即只能 写在 { } 大括号中
    ),写在 大括号外面的评释不被辨认
    倘诺实在想写注释,可以给有个别或然某条语句外面添加3个大括号,然后在进展诠释

  2. 零件嵌套

零件和组件之间可以 嵌套使用。可是富有的自定义组件都不可以不是以
大写字母初阶的组件。

  1. 事件系统

    • 各样 jsx 成分下面都得以团结定义 on*
      类型的风云监听函数,只好用在平常的 html
      成分标签上,无法应用在自定义的因素标签上

    • 每一个事件监听函数 都有三个默许的 event
      对象。一个经过 react 包装的 event 对象

    • react 的轩然大波代理体制
      react 将事件处理函数统一绑定在最外层上边
      react 对于原生的 DOM 节点可以书写原生的轩然大波
      ** 特别注意 **:
      因为 react 的事件代理机制,注意 stopPropagation() 阻止事件冒泡的时机

    • 瞩目 逐个 事件监听函数 若内部有利用到 this
      的情事,需求在表明函数的地点,动态的绑定 this

      // bind this 的时候 可以 传递默认的 参数
      render () {
          return (
              <h1 onClick={this.handleClickOnTitle.bind(this, 'Hello')}>React 小书</h1>
          )
      }
      
    • react 的 this 自动绑定区域
      A. class 内部自行绑定 this (
      class 的 { } 大括号这一层级 自动绑定 this )
      B. 构造函数 constructor 中并未自行绑定this
      C. 箭头函数自动绑定this
      D. 使用 bind 展现绑定 this

  2. state 的 使用

    • 历次调用 setState 都会触发 react 的再次渲染,并且重新调用 render
      方法 **
  • setState 函数执行时方可承受三个参数(prevState)
  • 多少个 setState 执行须求统一时半刻 须要 prevState 参数的增援。并且
    react 会将 多个 setState 操作合并为一个最终的状态进行一次性渲染
  • react 自身的 diff 算法有限支撑只会渲染更改的地点
  1. props 的使用
  • props 带来更好的复用性和 可配置性

  • defaultProps设置组件默许的 props, 和 this.props 获取配置参数,设定
    组件的暗中同意 props 数据

  • 零件内部一旦传递进 props 不可以在组件内部更改 props
    但是 零件内部 可以拿到 props. 将其予以 state 或者别的变量举办数量的增删改。

5.Props(属性)

state 和 props 首要的分别在于 props 是不可变的,而 state
可以根据与用户交互来改变。那就是为啥有个别容器组件必要定义 state
来更新和修改数据。 而子组件只好通过 props 来传递数据。
可以透过 getDefaultProps() 方法为 props 设置暗中认同值

var Text = React.createClass({
    render : function(){
        return <p>I love {this.props.name}</p>;
    }
});

ReactDOM.render(<Text name="Jason"/>, document.getElementById("myDiv"));

案例:
贯彻在输入框中,输入内容,上面的文字控件也随之变动

//子组件
var TextComponent = React.createClass({
    render : function(){
        return <div>Hello {this.props.text}!</div>;
    }

});

//父组件
var WrapperComponent = React.createClass({
    //state初始化
    getInitialState : function(){
        return {text:''};
    },
    //内容改变回调
    handleChange : function(e){
        //e 是Event事件对象,target是指事件的目标对象
        //改变状态
        this.setState({text:e.target.value});
    },
    render : function(){
        return <div>
            <TextComponent text={this.state.text}/>
            <input type="text" onChange={this.handleChange}/>
        </div>;
    }

});

ReactDOM.render(<WrapperComponent/>, document.getElementById("myDiv"));

事例中传参流程
1.handleChange(父组件回调)
2.setState(修改父组件的处境)
3.render(父组件重新渲染,子组件也会渲染)
3.把父组件的动静值,作为子组件的属性值传入
4.render(子组件内容改动)

在那么些大概的例子中,看不出来有其余jsx语法的地方,当其中<h1>Hello,world</h1>尽管使用到了jsx语法。HTML
语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX
的语法,它同意 HTML 与 JavaScript 的混写。尽管转化成纯JavaScript
的话,就是:

组件的生命周期


  1. 前端的情事数据管理, – 状态进步

将零件之间共享的数据抽象并提取出来放到近日的 公共父节点上,然后经过
props 将数据传递给子组件, 那样就是二个场所数据的升迁。

那就是说难点来了? 怎么样管理 三个层次的组件 所倚重的情状呢 ?
( **澳门葡京, 请大家关切 context 和 redux 的相干内容 ** )

  1. 零件的底蕴生命周期

澳门葡京 8

零件声明周期进度.png

react 将零件渲染 并塞到 DOM 成分中然后绘画在页面上的过程称为组件的挂载

为此 由挂载的历程你能够很好的知晓上边的零部件处理进度

constructor() // 起初化状态数据
component威尔Mount() // 组件的挂载进度
render()
// 构造 DOM 成分 插入页面
componentDidMount() // 组件的挂载进程
。。。。。
// 即将从页面中删除成分
componentWillUnmount()
// 从页面中去除成分

上述 的多少个生命周期 都是 组件的 第一阶段的状态管理函数

  • 相似的 getDefaultProps 和 getInitialState 都会放在 constructor
    中做到
  • 零件的隐藏 会触发 页面的 component威尔Unmount()
    函数,所以,在页面被隐形时要留意剩余数据 的拍卖。
  • component威尔Mount() 函数多用来组件的起步,eg: ajax,
    localStore数据的拉取,定时器的运维,等工作。
  • componentDidMount() 函数用于倚重 DOM 的风浪动作或许其余。eg:
    动画的开行需要借助 DOM. component威尔Mount 的时候 DOM
    还未曾挂载已毕,所以动画的运维要求放在 DidMount 函数中做到
  1. 组件更新的生命周期

    shouldComponentUpdate(nextProps, nextState)
    返回一个 boolean 数据。 用于决定组件是或不是 重新渲染。
    component威尔ReceiveProps(nextProps). 多用于拍卖父组件传递过来的
    props
    component威尔Update(); 组件早先更新之前调用。
    componentDidUpdate(); 组件更新还要重新渲染到 DOM 之后调用。

  2. ref 的作用

ref 属性用于获取已经挂载的 DOM 节点(
类似于为元素添加 id 属性,用于表示元素 )
refs 用于引用已经 标识的 DOM 节点,获取其 对象的 属性 和 方法

** 注意: **
多余 的 DOM 操作 会产生代码的噪音,不推荐大量使用 ref 操作 DOM

ref 版本更改:标识 DOM 节点的 ref由原本的字符串改为四个回调函数
旧版本 <input ref=”myinput” />
新版本 <input ref={(input)=>{this.myinput=input;}}/>
可以额外有一个参数 参数有妙用

  1. props.children 和 自定义标签成分中 添加 额外的 HTML DOM 成分

日常的标签成分中内嵌的 DOM
成分可以一向抬高。不过自定义标签组件怎讲将内嵌的 DOM
内容传递到下一层呢?

我们使用 props.children 可以获取到上层的 自定义标签中的内嵌的 DOM 元素

  1. jsx 中任何的 html 格式的 代码都会被转义掉,为了防患 xss 攻击

    为了显得 带有 html 标签的成分大家须要用到元素的
    dangerouslySetInnerHTML (
    这个只是元素的一个属性

    .....
    render() {
          renturn (
             <div
                    className="edit-html"
                     // 按照下面的方法设置元素的 html 的内容
                    dangerouslySetInnerHtml={ { __html: this.state.content } }
             >
        ) 
    }
    .....
    
  2. propsTypes 和 组件的参数验证
    JavaScript 是弱类型的语言,可是为了 **
    幸免和校验上一层传递过来数据的科学,大家拔取 PropTypes
    来做数据类型的校验相当于为数据添加数据类型,强类型的数据 **

     import React, { Component, PropTypes } from 'react'
     ....
     class ChildComponent extends Component {
           // 下面这些是固定的 书写格式
           static propsTypes = {
                 parentAttr: PropTypes. object,
                 parentArr: PropTypes.array
           }
           .........
     }
     ......
    
  3. 高阶组件就是八个函数,你传递给他一个零件对象,他再次回到给您一个经过包装的组件对象
    ** 约等于在原本组件之上 添加了一层经过包装的父组件 **
    功能性的封装

    ** 作用:**

    • 零件状态进步
      将子组件要求操作的数码交由父组件来保管,然后经过 props
      向下传递数据。此为 状态提升
      当某些数据/状态 被五个零部件倚重/使用 时,应该通过情状提高来治本

    • 高阶组件本质就是为着组件之间的复用,将再次的代码
      操作放在高阶组件中,下边的主题组件就足以复用了

       比如数据的 ajax 的读取,事件的统一操作等
      
    • 高阶组件中 通过 props 传递数据

    • 高阶组件可以很好的落到实处 斯玛特 组件( 重视数据操作的机件/ 高阶组件
      ) 和 Dumb 组件( 只须要上层数据props的纯组件 ) 的分别

      Smart 组件和 Dumb 组件( 或者说高阶组件 )的出现,很好的实现了 react 的 mvc 结构,达到了高层次的 组件的复用。

高阶组件知识点

  1. 高阶组件 本质就是一种 组件的 mixin 情势
  2. es7 的装裱着形式可以用来增加高阶组件
  3. 二个 斯马特 组件可以被三个高阶组件装饰,并且根据顺序执行

澳门葡京 9

高阶组件.png

  1. react 的 context 作为全局的靶子,有温馨独特的写法

    ** context 必须和 propType 强制数据类型 共同利用 **

    • 强制数据类型
      import React, { Component, PropTypes } from ‘react’
      ……
      static propsTypes = {
      themeColor: PropTypes. string
      }

    • 定义context 时的写法

      import React, { Component, PropTypes } from 'react'
      ....
      class ParentComponent extends Component {
          // 下面这些是固定的 书写格式
          static propsTypes = {
                themeColor: PropTypes. string
          }
          .........
          // 这里设置了 本组件包括其 所有子组件的 context 
          getChildContext () {
                 return { themeColor: this.state.themeColor }
          }
      }
      ......
      

    context 在概念时,必须有多个步骤
    宣称属性的数据类型
    安装获取全局 Context 的主意 getChildContext

    • 使用 context

            import React, { Component, PropTypes } from 'react'
            ....
            class ChildComponent extends Component {
                  static propsTypes = {
                        themeColor: PropTypes. string
                   }
                  render () {
                          return (
                                <div  style={{ color: this.context.themeColor }}>context 的获取使用地方</div>
                          )
                   }
            }
      

    context 在动用时必须有多个步骤
    声称要采用的 context 数据类型
    运用 this.context.属性 获取属性的值

context 使用手续繁杂是有案由的

  1. context 作为全局全体的靶子,必须保险其数量的不利。
  2. react 官方不引进使用 context, 进而希望我们可以采取更为和谐的
    Redux, Mobx等

6.React零件生命周期

实例化

第一次实例化

  • getDefaultProps
  • getInitialState
  • componentWillMount
  • render
  • componentDidMount

实例化完结后的更新

  • getInitialState
  • componentWillMount
  • render
  • componentDidMount

存在期
组件已存在时的意况改变

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

销毁&清理期

  • componentWillUnmount
    <script type="text/javascript">
      ReactDOM.render(
        React.DOM.h1(null,'hello,world!'),
        document.getElementById('example')
      );
    </script>

React 组件进阶


  1. react 理念分析

    • React 的零部件本质是创制了一个对象,由框架自身添加了 十三个表明周期函数(
      其实就是普通的函数,只是有执行顺序、触发时机、优化处理等特点
      )
      现实参见 React 的初期写法 React.createClass({ …. }),
      中间是三个对象

    • 声称周期函数,就是目的中的普通函数
      传值 + 操作处理 + 再次回到值

    • react 特点:

      1. 简单: 充分的简练,其自身唯有和睦的 api
      2. 非申明式的单项数据绑定
      3. ** 面向 HTML5, 专注视图层操作 ** 将 JavaScript 和 HTML5
        整合在一道。
      4. 高品质的密集 DOM 操作
      5. 帮忙后端渲染。
      6. 跨平台,一种书写,能够编译出多样结出 ** ReactNative **

      react 函数式编程 ( 小函数编程 )

      1. 尽量抽象出国有使用的小函数。
      2. 在贰个零乱的 逻辑体 中可以领到出 功用小函数
    • 组件化
      狭义的组件化:ui组件 —> 具体的零件( Tabs 组件 / Dropdown
      组件 )
      广义的组件化: 业务数据 + UI 组件的重组使用

      组件化的发展进度

      DOM操作为主( 根据逻辑改变 DOM 结构 ) –>
      MVC( 数据和界面解耦 ) –>
      小组件( 数据 + 界面 + 样式的结合体 eg: angular 指令 ) —->
      HTML5 的引入 ( javascript + HTML + css 合为一体)

      HTML Templetes –> custom Element –> shadow DOM –>
      HTML Imports

    • ** 非常首要:**
      ** 组件封装的经过实际就是面向对象的沉思逐步成熟**
      通过实例化的方法制造对象

      三个组件的目标实例: ( 基本的封装性 + 不难的阐明周期 +
      明确的多少流动 )

  2. 表单组件

    表单组件分为受控组件和非受控组件
    受控组件:依靠 state 和其中事件
    改变状态的零件,有很强的耦合性,复用性不高

       非受控组件,通过 defaultProps, props 传值的组件,复用性好
               非受控组件可以通过 事件和 ref 向上传递数据
    
  3. 零件通信 —> 事件订阅
    EventEmitter

  4. 组件品质优化

    1. 引入纯函数( pureRender 函数或然 斯玛特组件 )

    2. 利用 数据比较决定 纯函数零部件是不是渲染 shouldComponentUpdate()

    3. 引入不可变对象 恐怕 es6 对象增加 举行数据相比

         Immutable 不可变对象,对 Immutable 对象的 增 删 改 都会生成一个新对象,类似于对象的深拷贝,但是比对象的深拷贝效率要高
      
         es6 对象扩展 和 对象/数组的解构赋值,也能够得到一个新的对象
      
    4. Immutable 解析

      ** Immutable 可以提供一种崭新的数码相比和转变格局,类似于 es6
      的对象伸张 和 解构赋值 **

         Immutable 三种数据类型 
         Map: 对应于 `Object`, 键值对集合
         List :   对应于 `Array` 有序的重复列表
         ArrayList: 无序不可重复的列表
      
         // 特性应用实例
         import { Map, List, Arraylist } from 'immutable'
         ....
         this.setSatate({
                 data: Map({ times: 0 })      // 得到一个新的 Immutable 对象
         })
      

      Immutable 方法运用实例 ( Immutable.is 可以用来进展比较,比 ===
      全等的频率高 )

         import { is } from 'immutable'
         .....
         shouldComponentUpdate(nextProps, nextState) {
               if( is( nextProps.attr, nextState.attr ) )
                     return false;
              ......
         }
      

.

7.生命周期共提供了拾个例外的API。

1.getDefaultProps
作用于组件类,只调用几回,重临对象用于安装暗中同意的props,对于引用值,会在实例中共享。

2.getInitialState
功用于组件的实例,在实例创设时调用五回,用于初叶化每种实例的state,此时可以访问this.props。

3.componentWillMount
在形成第三回渲染从前调用,此时还能修改组件的state。

4.render
必选的法门,成立虚拟DOM,该格局具有特殊的规则:

  • 只好因而this.props和this.state访问数据
  • 可以回到null、false或任何React组件
  • 只可以出现八个世界级组件(不或然回到数组)
  • 无法更改组件的情状
  • 无法修改DOM的出口

5.componentDidMount
真正的DOM被渲染出来后调用,在该形式中可因而this.getDOMNode()访问到真实的DOM成分。此时已足以应用其余类库来操作这些DOM。
在服务端中,该方法不会被调用。

6.componentWillReceiveProps
组件接收到新的props时调用,并将其当做参数nextProps使用,此时得以变动组件props及state。

    componentWillReceiveProps: function(nextProps) {
        if (nextProps.bool) {
            this.setState({
                bool: true
            });
        }
    }

7.shouldComponentUpdate
零件是还是不是应当渲染新的props或state,重返false表示跳过继续的生命周期方法,日常不需求拔取避防止出现bug。在产出应用的瓶颈时,可通过该办法开展恰当的优化。
在第二回渲染时期如故调用了forceUpdate方法后,该办法不会被调用

8.componentWillUpdate
接受到新的props只怕state后,举行渲染以前调用,此时不允许更新props或state。

9.componentDidUpdate
完了渲染新的props大概state后调用,此时得以访问到新的DOM成分。

10.componentWillUnmount
组件被移除以前被调用,可以用于做一些清理工作,在componentDidMount方法中添加的持有职务都须要在该方法中收回,比如成立的定时器或加上的风云监听器。

在上述JSX语法中有八个要专注的地点:

8.传参

通过品质Props可以在父组件中给子组件设置属性值,约等于将父组件的值传递给子组件。然则要化解子组件访问父组件的方式,可以通过回调函数化解,那就和Java的接口一样。
她的机要思路:子组件委托父组件处理。

上面通过一个案例来落实

  • 下拉列表(子组件)的数额暴发转移,表单(父组件)可以获取到,用于末端的提交子组件向父组件传递参数

1.下拉精选组件:

//表单的子组件
var ChildGenderSelect = React.createClass({
    render : function(){
        return <select onChange={this.props.handleSelectChange}>
            <option value="1">男</option>
            <option value="0">女</option>
        </select>;
    }
});

2.表单的机件:

//提交数据的两种做法:
//1.直接提交表单,跳转,整个页面刷新(过时的做法)
//2.屏蔽表单的默认提交行为,通过ajax提交数据,服务器响应成功之后在跳转(类似于Android)
var ParentForm = React.createClass({
    getInitialState : function(){
        return {gender:0};
    },
    handleChange : function(e){
        //保存到state
        this.setState({gender:e.target.value});
    },
    handleSubmit : function(e){
        //屏蔽表单的默认提交行为
        e.preventDefault();
        //ajax发起请求,提交数据
        /*var request = new XMLHttpRequest();
        request.open("GET","test.json?gender="+this.state.gender);
        request.onreadystatechange = handler;
        request.responseType = "json"; //服务器响应数据的类型 json
        request.setRequestHeader("Accept","application/json");
        request.send();

        //回调
        function handler(){
            //4(完成)响应内容解析完成
            if(this.readyState !== 4){
                return;
            }
            if(this.status == 200){
                //请求成功:显示数据
                console.log("ok");
            }
        }*/
    },
    render : function () {
        return <form onSubmit={this.handleSubmit}>
            <ChildGenderSelect handleSelectChange={this.handleChange}></ChildGenderSelect><br/>
            <button type="submit">提交</button>
        </form>;
    }
});

3.将表单组件渲染到页面:

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

4.案例的流水线:
(1).通过handleSelectChange属性,传入父组件的handleChange函数给子组件。
(2).当子组件的onChange事件触发,调用this.props.handleSelectChange->父组件的handleChange函数。

  • <script> 标签的 type 属性为 text/babel,那是React 独有的 JSX
    语法,跟 JavaScript 不般配。凡是在页面中直接动用 JSX
    的地点,都要添加 type=”text/babel”。
  • 统计用了八个库: react.js 、react-dom.js 和 browser.min.js
    ,它们必须首先加载。其中,react.js 是 React 的基本库,react-dom.js
    是提供与 DOM 相关的功用, browser.min.js的作用是将 JSX 语法转为
    JavaScript 语法。

9.表单提交和函数复用

案例:

  • 点击提交按钮,提交输入框输入的情节,通过Ajax请求提交

1.措施一:不可控组件
驷不及舌思路:通过ref获取组件

var FormComponent = React.createClass({
    //处理表单提交
    handleSubmit : function(e){
        e.preventDefault();
        //ref类似于id,是一个唯一标示 React.findDOMNode
        var text = this.refs.input_name.value;
        alert(text);
    },
    render : function(){
        return <form onSubmit={this.handleSubmit}>
            <input type="text" ref="input_name" defaultValue="Hello..."/><br/>
            <button type="submit">提交</button>
        </form>;
    }
});

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

2.主意二:可控组件(和MVVM data binding很相近)
紧要思路:把数量存储在情状中(通过事件监听,进行数据绑定),须求时,从气象中收获

var FormComponent = React.createClass({
    getInitialState : function () {
        return {text:''};
    },
    handleChange : function(e){
        //保存到state
        this.setState({text:e.target.value});
    },
    handleSubmit : function(e){
        e.preventDefault();
        alert(this.state.text);
    },
    render : function(){
        return <form onSubmit={this.handleSubmit}>
            <input type="text" defaultValue="Hello..." onChange={this.handleChange}/><br/>
            <button type="submit">提交</button>
        </form>;
    }
});

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

随即暴发的题材:三个控件需求八个事件处理函数,怎样形成事件处理函数的复用?

3.艺术三:事件处理函数的复用格局1
在措施二的根底上展开创新,让子控件可以完结复用,并保存对应的属性值。
思路:bind重返改变了左右文this后的函数

var FormComponent = React.createClass({
    getInitialState : function () {
        return {
            username:'',
            gender:0,
            agree:true
        };
    },
    //key ->'username' ....
    handleChange : function(key,e){
        //this->FormComponent对象
        //保存到state
        var obj = {};
        obj[key] = e.target.value;
        this.setState(obj);
    },
    handleSubmit : function(e){
        e.preventDefault();
        console.log(this.state);
    },
    //多个控件的事件响应,共用这个函数
    render : function() {
        return <form onSubmit={this.handleSubmit}>
            <label htmlFor="username">输入用户名:</label>
            <input id="username" type="text" onChange={this.handleChange.bind(this,'username')}/><br/>
            <label htmlFor="gender">请选择性别:</label>
            <select id="gender" onChange={this.handleChange.bind(this,'gender')}>
                <option value="1">男</option>
                <option value="0">女</option>
            </select><br/>
            <label htmlFor="agree">是否同意:</label>
            <input id="agree" type="checkbox" onChange={this.handleChange.bind(this,'agree')} /><br/>
            <button type="submit">提交</button>
        </form>;
    }

});

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

留意:this的效用域难题,若是this内定的函数是非箭头函数,会造成功能域不得法,子控件拿不到相应的函数和属性值。

4.艺术四:事件处理函数的复用格局2
思路:钦赐属性,比如说name属性区分区其他组件

var FormComponent = React.createClass({
    getInitialState : function () {
        return {
            username:'',
            gender:0,
            agree:true
        };
    },

    handleChange : function(e){
        var obj = {};
        obj[e.target.name] = e.target.value;
        this.setState(obj);
    },
    handleSubmit : function(e){
        e.preventDefault();
        console.log(this.state);
    },
    //多个控件的事件响应,共用这个函数
    render : function() {
        return <form onSubmit={this.handleSubmit}>
            <label htmlFor="username">输入用户名:</label>
            <input id="username" type="text" name="username" onChange={this.handleChange}/><br/>
            <label htmlFor="gender">请选择性别:</label>
            <select id="gender" name="gender" onChange={this.handleChange}>
                <option value="1">男</option>
                <option value="0">女</option>
            </select><br/>
            <label htmlFor="agree">是否同意:</label>
            <input id="agree" name="agree" type="checkbox" onChange={this.handleChange} /><br/>
            <button type="submit">提交</button>
        </form>;
    }

});

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

将 JSX 语法转为 JavaScript
语法,这一步很成本时间。以往前端项目,都会接纳前端工程化,不会一直在html页面中一贯写js代码,写好的js代码都会接纳工具进行编译压缩等。那样的话,大家的jsx也会通过编译直接倒车成js语法,让浏览器直接利用。

10.动画

案例:让1个文字,在3秒之类从左到右移动一段距离
思路:用定时器,不断更改属性值,并渲染。

var MyComponent = React.createClass({
    getDefaultProps : function(){
        return {
            position:100, //marginLeft目标值,组件实现可配置
            time:10
        };
    },
    getInitialState : function () {
        return {position:0};  //marginLeft开始值
    },
    render : function(){
        var style = {
            color:'red',
            marginLeft:this.state.position //左外边距
        };
        return <div style={style}>This will animated!</div>;
    },
    //动画函数,不断改变state的position属性
    transformComponnent : function () {
        if(this.state.position < this.props.position){
            this.setState({
                position : ++this.state.position
            });
        }else{
            //动画完成,取消定时器
            clearInterval(this.timer);
        }
        console.log("transformComponnent");
    },
    //渲染完成
    componentDidMount : function () {
        //开启定时器
        this.timer = setInterval(this.transformComponnent,this.props.time);
    }
});


ReactDOM.render(<MyComponent position={200} time={20}></MyComponent>,document.body);

流程
1.起始化控件,执行生命周期中的getDefaultProps 和getInitialState ;
2.控件渲染完结,执行componentDidMount ;
3.拉开定时器,不断推行transformComponnent ;
4.保留情形setState;
5.不断渲染render,渲染的时候marginLeft拿取状态值;

ReactDOM.render 是 React 的最基本格局,将模板转为HTML语言,并插入内定的
DOM 节点。

11.计时器案例

1.模块化
把某些类,函数,变量写到二个文件中,作为3个作用模块,当要利用那么些模块,只需求引用。
nodejs不匡助,用Bable6转es6为es5(js库,已毕模块化),es6模块化(新的语法特性),node和chrome都不接济。

2.创建react工程
协理语法性情,相当有益

npm install -g create-react-app
create-reate-app test
cd test

3.模块引入和导出
创制三个零部件
class TimeDisplay extends React.Component{
}

引入:import React form ‘react’;

导出:export default TimeDisplay;

4.代码

this唯有在运转时才显然
转为箭头函数,因为this的功效域是最外层的,比经常的function少了绑定this步骤;
在构造函数中对事态赋初始值,不可以调用setState
TimeDisplay.js:

import React from 'react';

import DisplayLog from './DisplayLog';
import Button from './Button';
import formatTime from '../utils/formatTime';

class TimeDisplay extends React.Component{
    //在构造函数中对状态赋初始值
    constructor(props){
        super(props);
        //不能调用state
        this.state = {
            time:0,
            on:false,
            log:[] //数组
        };
    }

    //开始按钮
    handleToggle = ()=>{
        //已经开始,取消正在运行的定时器
        if(this.state.on){
            clearInterval(this.timer);
        }else{
            //否则开启
            //定时器,10ms累加1
            this.timer = setInterval(()=>this.setState({time:this.state.time+1}),10);
        }
        this.setState({on:!this.state.on});
    }
    //记录时间
    handleLogTime = ()=>{
        //存储在数组中
        this.state.log.push(this.state.time);
    }
    //清空记录
    handleClearLog = ()=>{
        this.setState({log:[]});
    }
    //重置
    handleReset = () =>{
        this.setState({time:0});
    }

    render(){
        var time = formatTime(this.state.time);
        return <div>
            <h1 className="display-time">{time}</h1>
            <div className="controls">
                <Button className={this.state.on ? "danger" : "success"} text={this.state.on ? "暂停" : "开始"} onClick={this.handleToggle}/>
                <Button className="warning"  onClick={this.handleReset}/>
                <Button className="primary" text="记录" onClick={this.handleLogTime}/>
                <Button className="undefined" text="清空" onClick={this.handleClearLog}/>
            </div>
            <DisplayLog log={this.state.log}/>
        </div>;
    }

    //监听键盘事件
    componentDidMount(){
        //内置对象
        window.addEventListener('keydown', e => e.preventDefault());
        window.addEventListener('keyup', e => {
            e.preventDefault();
            switch (e.keyCode){
                case 32: //space
                    this.handleToggle();
                    break;
                case 82:
                    this.handleReset();
                    break;
                case 13:
                    this.handleLogTime();
                    break;
                case 67:
                    this.handleClearLog();
                    break;
                default:
                    break;
            }
        });
    }

    //组件被移除,事件监听取消
    componentWillUnmount(){
        window.removeEventListener('keydown');
        window.removeEventListener('keyup');
    }

}

//在外部要使用TimeDisplay
export default TimeDisplay;

Button.js:
button的卷入,数据、样式、事件的传递

import React from 'react';

class Button extends React.Component{
    //静态属性,给属性赋默认值
    static defaultProps = {
        onClick : null,
        className : '',
        text : '默认'
    };

    render(){
        return <button className={`Button ${this.props.className}`} onClick={this.props.onClick}>{this.props.text}</button>;
    }
}

export default Button;

DisplayLog.js:

import React from 'react';
import formatTime from '../utils/formatTime';

class DisplayLog extends React.Component{
    //log数组长度等于0,返回“空空如也”
    renderEmpty = () =>{
        return 空空如也...;
    }

    //否则,把元素遍历(时间),得到一系列的<li>
    renderLog = () => {
        //<li>00</li>
        //<li>11</li>
        return this.props.log.map(item => {
            return <li className="log-item" >{formatTime(item)}</li>;
        });
    }

    render(){
        //log数组长度等于0,返回“空空如也”
        //否则,把元素遍历(时间),得到一系列的<li>
        //<ul>
        //  <li>00</li>
        //  <li></li>
        //</ul>
        const log = this.props.log.length === 0 ? this.renderEmpty() : this.renderLog();
        return <ul className="log">
            {log}
        </ul>;
    }
}

export default DisplayLog;

formatTime.js:

//将数组转为字符串,如果数字只有一位,会在第一个位置添加一个0
//9->9->09
const appendZero = n => n.toLocaleString({},{minimumIntegerDigits:2});

export default function(t = 0){
    const msec = appendZero(t % 100),
        sec = appendZero(parseInt((t/100) % 60)),
        min = appendZero(parseInt((t/6000) % 60)),
        hour = appendZero(parseInt(t/360000));
    return `${hour}:${min}:${sec}.${msec}`;
}

App.css

.App {
  text-align: center;
}

ul,li{
  list-style: none; /*去掉列表默认样式*/
  margin: 0px;
  padding: 0px;
}

.display-time{
  font-size: 45px;
  font-weight: bold;
  margin: 60px 0px;
}

.controls{
  background-color: #eee;
}

.Button{
  width: 130px;
  font-size: 20px;
  padding: 10px 20px;
  margin: 20px;
  border: none;
  border-radius: 4px;
  background-color: lightgreen;
  cursor: pointer;
}

.Button:hover{
  /*CSS3阴影*/
  box-shadow: 0 0 25px rgba(0,0,0,0.2);
}

.success{
  background-color: lightgreen;
}
.danger{
  background-color: hotpink;
}
.warning{
  background-color: gold;
}
.primary{
  background-color: skyblue;
}
.undefined{
  background-color: #e1e1e1;
}

.log{
  text-align: center;
  font-size: 30px;
  color: #e1e1e1;
}

/*log和empty-log都会应用这个样式*/
.log .empty-log{
  display: inline-block;
  padding: 50px 10px;
}

/*.log类下的li标签 */
/*.log > li{*/
.log-item{
  font-size: 25px;
  color: #000;
  border-bottom: 1px solid #eee;
  padding: 10px 0px;
}

/*伪类*/
/*悬浮*/
.log-item:hover{
  background-color: rgba(238, 238, 238, 0.5);
}

App.js

import React from 'react';
import './App.css';
import TimeDisplay from './components/TimeDisplay'

class App extends React.Component {
  render() {
    return <div className="App">
      <TimeDisplay />
    </div>;
  }
}

export default App;

JSX的特点:

  1. 类XML语法简单接受,结构清晰
  2. 增强JS语义
  3. 架空程度高,屏蔽DOM操作,跨平台
  4. 代码模块化

12.常用的补充点

1.数组
数组的创立

var a = [];
var b = new Array();

数组的成分赋值

a[0] = 2;
a[1] = 10;
a.push(30);

清空

console.log(a);
a = [];
console.log(a);

map 遍历数组的函数

//item是数组的元素,i数组的索引,b是返回的数组
var b = a.map(function(item,i){
    return ++item;
});
console.log(b);

2.组件的二种创立格局
1.React.createClass
对应的性质和状态开首化方法:

getDefaultProps
getInitialState

2.extends Component
相应的本性和气象先导化方法:

static defaultProps
constructor

3.css样式
.log-item

JSX基本语法规则:

JSX本人就和XML语法类似,可以定义属性以及子成分。唯一特殊的是能够用大括号来参加JavaScript表达式。蒙受HTML 标签(以 < 初叶),就用 HTML 规则解析;境遇代码块(以 {
开首),就用 JavaScript 规则解析。

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

这些就是一个简练的html与js混用的事例。arr变量中留存html成分,div中又采取了arr这一个js变量。转化成纯javascript的话:

var h1=React.DOM.h1(null,'Hello world!');
var h2=React.DOM.h1(null,'React is awesome');
var div=React.DOM.div(null,h1,h2);
ReactDOM.render(
 div,
 document.getElementById('example')
);

React组件

小编们利用jsx来将代码封装成React组件,然后像插入普通 HTML
标签一样,在其余地方插入那几个组件。使用React.createClass用于转移一个零件。

var MyComponent=React.createClass({
  render: function() {
   return <h1>Hello world!</h1>;
 }
});
ReactDOM.render(
 <MyComponent />,
 document.getElementById('example')
);

上边代码中,变量 MyComponent就是二个零部件类。模板插入 <MyComponent
/> 时,会自动生成 MyComponent
的三个实例(下文的”组件”都指组件类的实例)。全部组件类都无法不有友好的
render 方法,用于出口组件。

React 可以渲染 HTML 标签 (strings) 或 React 组件 (classes)。

  • 在react中一般约定组件类的首先个字母必须大写,html标签都是小写。

//要渲染 HTML 标签,只需在 JSX 里接纳小写字母起初的标签名。
var myDivElement = <div className=”foo” />;
React.render(myDivElement, document.getElementById(‘example’));
//要渲染 React 组件,只需制造一个大写字母伊始的地点变量。
var MyComponent = React.createClass({//});
var myElement = <MyComponent />;
React.render(myElement, document.getElementById(‘example’));

* 还有一个注意点:组件类只能包含一个顶层标签,否则会报错。
```javascript

//var myDivElement
=<h1>你好</h1><h1>hello</h1>;
//上述写法是会报错的,要写成唯有一个顶层标签:
var myDivElement
=<div><h1>你好</h1><h1>hello</h1></div>;

上述代码二个静态的机件,上面看3个动态组件:

var MyComponent=React.createClass({
  getInitialState: function() {
       return {clickNum: 0};
  },
  handleClick:function(){
    var num=this.state.clickNum;
    num++;
    this.setState({clickNum:num});
  },
  render: function() {
   return (
      <div>
        <h1 onClick={this.handleClick}>Hello {this.props.name}!</h1>
        <h2 style={{color:'red'}}>点击{this.props.name}次数:{this.state.clickNum}</h2>
      </div>
    );
 }
});
ReactDOM.render(
  <div>
     <MyComponent name="张三" />
     <hr/>
     <MyComponent name="李四" />
  </div>,
 document.getElementById('example')
);

上边代码中定义的MyComponent组件包括属性,状态和事件,是3个简练的相比完好的零部件。使用props通过父组件举办传递值,使用state定义组件自身的情况,组件协助的一大半的DOM操作事件。

至于属性props:

  • class 属性须要写成 className ,for 属性须求写成 htmlFor ,那是因为
    class 和 for 是 JavaScript 的保留字。
  • 直白在标签上采用style属性时,要写成style={{}}是两个大括号,外层大括号是告诉jsx那里是js语法,和真正DOM差其余是,属性值不只怕是字符串而必须为目的,需要专注的是属性名同样要求驼峰命名法。即margin-top要写成marginTop。
  • this.props.children
    不要children作为把目的的属性名。因为this.props.children获取的该标签下的全体子标签。this.props.children
    的值有二种大概:要是当前组件没有子节点,它就是 undefined
    ;即使有1个子节点,数据类型是 object
    ;假设有八个子节点,数据类型就是 array 。所以,处理
    this.props.children
    的时候要小心。官方提出选拔React.Children.map来遍历子节点,而不用担心数据类型。

关于状态state:

  • 零件免不了要与用户互动,React
    将零件看成是七个状态机,一早先有三个先导状态,然后用户互动,导致意况变化,从而触发重新渲染
    UI。
  • getInitialState
    方法用于定义开首状态,约等于一个目的,那个目的可以通过 this.state
    属性读取。当用户点击组件,导致情形变化,this.setState
    方法就修改景况值,每一次修改之后,自动调用 this.render
    方法,再一次渲染组件。

鉴于 this.props 和 this.state
都用来描述组件的表征,大概会发出模糊。1个简易的界别方法是,this.props
表示那一个一旦定义,就不再改变的特点,而 this.state
是会随着用户互动而暴发变化的性格。

注意点:
比方往原生 HTML 成分里传播 HTML 规范里不设有的特性,React
不会展现它们。若是急需利用自定义属性,要加 data- 前缀。

<div data-custom-attribute=”foo” />

PropTypes

零件的属性props还不错任意值,字符串、对象、函数等等都得以。有时,大家须要一种体制,验证别人使用组件时,提供的参数是还是不是符合要求。React中动用PropTypes进行参数的校验。

var MyTitle = React.createClass({
   propTypes: {
     title: React.PropTypes.string.isRequired,
   },
   render: function() {
     return <h1> {this.props.title} </h1>;
   }
});

下边的Mytitle组件有2个title属性。PropTypes 告诉 React,这么些 title
属性是必须的,而且它的值必须是字符串。当我们给title传递二个数字时,控制台就会报错:

Warning: Failed propType: Invalid prop `title` of type `number` supplied to `MyTitle`, expected `string`.

别的,getDefaultProps 方法可以用来安装组件属性的专擅认同值。

取得真实的DOM节点

组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟
DOM (virtual 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>
     );
   }
});

为了获取真是DOM节点,html元素必须有2个 ref 属性,然后
this.refs.[refName] 就会回来这么些实际的 DOM 节点。亟需注意的是,由于
this.refs.[refName] 属性获取的是动真格的 DOM ,所以必须等到虚拟 DOM
插入文档今后,才能使用那性格情,否则会报错。

求值表达式

要使用 JavaScript 表达式作为属性值,只需把那几个表明式用一对大括号 ( { } )
包起来,不要用引号 ( ” ” )。
在编制JSX时,在 { }
中不只怕应用语句(if语句、for语句等等),但能够运用求值表明式,那本身与JSX没有多大关系,是JS中的个性,它是会重回值的表明式。我们不可以一向利用语句,但足以把语句包裹在函数求值表明式中使用。

规范判断的写法

你没办法在JSX中拔取 if-else 语句,因为 JSX
只是函数调用和对象创制的语法糖。在 { }
中应用,是不合规的JS代码,不过可以利用安慕希操作表达式

var HelloMessage = React.createClass({ 
  render: function() { 
    return <div>Hello {this.props.name ? this.props.name : "World"}</div>; 
  }
});
ReactDOM.render(<HelloMessage name="xiaowang" />, document.body);

可以动用相比运算符“ ||
”来书写,尽管左侧的值为真,则直接再次回到左边的值,否则再次回到左侧的值,与if的功效等同。

var HelloMessage = React.createClass({ 
  render: function() { 
    return <div>Hello {this.props.name || "World"}</div>; 
  }
});
函数表明式

( )有强制运算的机能

var HelloMessage = React.createClass({ 
  render: function() { 
    return <div>Hello { 
    (function(obj){ 
        if(obj.props.name) 
          return obj.props.name 
        else 
          return "World" 
      }(this)) 
    }</div>; 
  }
});
ReactDOM.render(<HelloMessage name="xiaowang" />, document.body);

外括号“
)”放在外边和内部都可以举行。唯一的区分是括号放里面实践完结得到的是函数的引用,然后再调用“function(){}(this)()”;括号放在外面的时候得到的事重返值。

零件的生命周期

零件的生命周期分成八个情形:

* 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):组件判断是否重新渲染时调用

注释

JSX 里添加注释很简单;它们只是 JS
表达式而已。你只须要在1个标签的子节点内(非最外层)小心地用 {}
包围要诠释的一部分。

{/* 一般注释, 用 {} 包围 */}

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website