美文网首页思沃大讲堂2018
React.js的基础知识及一些demo(一)

React.js的基础知识及一些demo(一)

作者: 初漾流影 | 来源:发表于2018-01-27 21:50 被阅读50次

    React是什么

    React 是一个用于构建用户界面的 JAVASCRIPT 库。
    React主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图)。
    React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。

    React的特点

    1.声明式设计 −React采用声明范式,可以轻松描述应用。
    2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
    3.灵活 −React可以与已知的库或框架很好地配合。
    4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
    5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
    6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

    React的实现机制

    1.Virtual DOM

    Virtual DOM 是一个模拟 DOM 树的 JavaScript 对象。 React 使用 Virtual DOM 来渲染 UI,当组件状态 state 有更改的时候,React 会自动调用组件的 render 方法重新渲染整个组件的 UI。

    React 主要的目标是提供一套不同的, 高效的方案来更新 DOM.不是通过直接把 DOM 变成可变的数据, 而是通过构建 “Virtual DOM”, 虚拟的 DOM, 随后 React 处理真实的 DOM 上的更新来进行模拟相应的更新。

    2.组件化的开发思路

    组件就是封装起来具有独立功能的UI控件。开发时,将UI上每一个功能相对独立的模块定义成组件,将小的组件通过组合或者嵌套的方式,最后构成一个大的组件,所以组件是高度可重用的。

    React的实例

    1.HTML模板

    使用React的网页源码,结构大致如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>demo01</title>
        <script src="../build/react.js"></script>
        <script src="../build/react-dom.js"></script>
        <script src="../build/browser.min.js"></script>
    </head>
    <body>
        <div id="example"></div>
        <script type="text/babel">
           /* our code*/
        </script>
    </body>
    </html>
    

    以上代码需要由两个地方注意:

    • body标签内的script标签的type属性值为text/babel,因为React独有的JSX语法与javascript不兼容,所有使用JSX语法的地方,都必须加上type="text/babel"
    • 以上代码一共使用三个库:react.jsreact-dom.jsbrowser.min.js,他们必须首先加载,其中,react.jsReact的核心库;react-dom.js是提供与DOM相关的功能;browser.min.js是将JSX语法转换为javascript语法,这一步比较耗时。

    2. 元素渲染

    什么是元素

    元素(Elements)是 React 应用中最小的构建部件(或者说构建块,building blocks)。

    一个元素用于描述你在将在屏幕上看到的内容:

    const element = <h1>Hello, world</h1>;
    

    不同于浏览器的 DOM 元素, React 元素是普通的对象,非常容易创建。React DOM 会负责更新 DOM ,以匹配React元素

    渲染一个元素到DOM

    要渲染一个 React 元素到一个 root DOM 节点,把它们传递给 ReactDOM.render() 方法:

    ReactDOM.render是React的最基本方法,用于将模板转换为HTML语言,并插入指定的DOM节点。

    ReactDOM.render(
            <h1>Hello World</h1>,
            document.getElementById("example")
     );
    

    以上代码将一个h1标题插入到example节点,在页面中渲染了一个 “Hello, world!” 标题。具体代码见 demo01

    更新已渲染的元素

    React 元素是 不可突变(immutable) 的. 一旦你创建了一个元素, 就不能再修改其子元素或任何属性。一个元素就像电影里的一帧: 它表示在某一特定时间点的 UI 。

    就我们所知, 更新 UI 的唯一方法是创建一个新的元素, 并将其传入 ReactDOM.render() 方法.

    注意:
    实际上,大多数 React 应用只会调用 ReactDOM.render() 一次。

    React 只更新必需要更新的部分

    React DOM 会将元素及其子元素与之前版本逐一对比, 并只对有必要更新的 DOM 进行更新, 以达到 DOM 所需的状态

    3.JSX语法

    上一节中直接将HTML语言写在javascript代码中,不加任何引号,这就是JSX语法。它允许 HTML 与 JavaScript 的混写。

    考虑一下这个变量的声明:
    const element = <h1>Hello, world!</h1>;
    这种有趣的标签语法既不是字符串也不是HTML。

    这就是 JSX ,他是 JavaScrip 的一种扩展语法。我们推荐在 React 中使用这种语法来描述 UI 信息。JSX 可能会让你想起某种模板语言,但是它具有 JavaScrip 的全部能力。JSX 可以生成 React “元素”。

    警告:
    比起 HTML , JSX 更接近于 JavaScript , 所以 React DOM 使用驼峰(camelCase)属性命名约定, 而不是HTML属性名称。
    例如,class 在JSX中变为classNametabindex 变为 tabIndex

    JSX语法例子1

        <div id="example"></div>
        <script type="text/babel">
          var names = ['Alice','Emily','Kate'];
          ReactDOM.render(
            <div>
              {
                names.map(function (name) {
                   return <div>Hello,{name}!</div>
                })
              }
            </div>,
            document.getElementById('example')
          );
        </script>
    

    以上代码体现了 JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。具体代码见demo02

    JSX语法例子2

    JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员

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

    上面代码的arr变量是一个数组,结果 JSX 会把它的所有成员,添加到模板。具体代码见demo03

    4.组件(Components) 和 属性(Props)

    组件使你可以将 UI 划分为一个一个独立,可复用的小部件,并可以对每个部件进行单独的设计。

    从定义上来说, 组件就像JavaScript的函数。组件可以接收任意输入(称为”props”), 并返回 React 元素,用以描述屏幕显示内容。

    函数式组件和类组件

    最简单的定义组件的方法是写一个 JavaScript 函数:

    function Welcome(props) {
         return <h1>Hello,{props.name}</h1>;
     }
    

    这个函数是一个有效的 React 组件,因为它接收一个 props 参数, 并返回一个 React 元素。 我们把此类组件称为”函数式(Functional)“组件, 因为从字面上看来它就是一个 JavaScript 函数。

    我们也可以用一个 ES6 的 class 来定义一个组件:

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

    上面两个组件从 React 的角度来看是等效的。类组件有一些额外的特性。

    渲染一个组件

    当 React 遇到一个代表用户定义组件的元素时,它将 JSX 属性以一个单独对象的形式传递给相应的组件。 我们将其称为 “props” 对象。

    function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }
    
    const element = <Welcome name="Sara" />;
    ReactDOM.render(
      element,
      document.getElementById('root')
    );
    

    我们简单扼要重述一下上面这个例子:

    1.我们调用了 ReactDOM.render() 方法并向其中传入了 <Welcome name="Sara" /> 元素。
    2.React 调用 Welcome 组件,并向其中传入了 {name: 'Sara'} 作为 props 对象。
    3.Welcome 组件返回 <h1>Hello, Sara</h1>。
    4.React DOM 迅速更新 DOM ,使其显示为 <h1>Hello, Sara</h1>。

    警告:
    组件名称总是以大写字母开始。
    举例来说, <div /> 代表一个 DOM 标签,而 <Welcome /> 则代表一个组件,并且需要在作用域中有一个 Welcome 组件。

    构造组件

    组件可以在它们的输出中引用其它组件。这使得我们可以使用同样的组件来抽象到任意层级。一个按钮,一个表单,一个对话框,一个屏幕:在 React 应用中,所有这些都通常描述为组件。

    例如,我们可以创建一个 App 组件,并在其内部多次渲染 Welcome:

    function Welcome(props) {
        return <h1>Hello,{props.name}</h1>;
      }
    function App() {
        return <div>
          <Welcome name="Andy"/>
          <Welcome name="Bob"/>
          <Welcome name="Cindy"/>
        </div>;
    }
    const element = <App />;
    ReactDOM.render(
        element,
        document.getElementById("example")
     );
    

    通常,新的 React apps 都有一个单独的顶层 App 组件。然而,如果你在已有的应用中整合 React,你可以需要由下至上地, 从类似于 Button 这样的小组件开始, 逐渐整合到视图层的顶层。

    警告:
    组件必须返回一个单独的根元素。这就是为什么我们添加一个 <div> 来包含所有 <Welcome /> 元素的原因。

    提取组件

    不要害怕把一个组件分为多个更小的组件。

    举个例子,思考下名 Comment 组件:

     function Comment(props) {
         return (
           <div className ="Comment">
             <div className = "UserInfo">
               <img className = "Avator" src="{props.author.avatarUrl}" alt="{props.author.name}"/>
               <div className = "UserInfo-name">{props.author.name}</div>
             </div>
             <div className = "Comment-text">{props.text}</div>
             <div className = "Comment-date">{formatDate(props.date)}</div>
           </div>
         );
    }
    

    它接受 author(一个对象),text(一个字符串)和 date(一个日期)作为 props,并用于在某社交网站中描述一条评论。

    这个组件修改起来很麻烦,因为它是被嵌套的,而且很难复用其中的某个部分。让我们从其中提取一些组件。

    首先,提取头像 Avatar:

    function Avator(props) {
         return (
           <img className = "Avator"
                src="{props.user.avatarUrl}"
                alt="{props.user.name}"
           />
         );
    }
    

    Avatar 组件不用关心它在 Comment 中是如何渲染的。这是为什么我们它的 prop 一个更通用的属性名: user, 而不是 author 的原因。

    我们建议从组件本身的角度来命名 props 而不是它被使用的上下文环境。

    接下来,我们提取用户信息 UserInfo 组件, 用于将 Avatar 显示在用户名旁边:

     function UserInfo(props) {
        return (
          <div className = "UserInfo">
            <Avator user = {props.user} />
            <div className = "UserInfo-name">{props.user.name}</div>
          </div>
        );
      }
    

    所以简化 Comment 组件如下:

     function Comment(props) {
         return (
           <div className ="Comment">
             <UserInfo user = {props.author}/>
             <div className = "Comment-text">{props.text}</div>
             <div className = "Comment-date">{formatDate(props.date)}</div>
           </div>
         );
       }
    

    注意:组件之间的传值,在以上代码中有两处传值的地方:一、user = {props.author},UserInfo 组件接收它的上级组件Comment的传值;二、user = {props.user} ,Avator 组件接收它的上级组件UserInfo的传值。

    提取组件可能看起来是一个繁琐的工作,但是在大型的 Apps 中可以回报给我们的是大量的可复用组件。一个好的经验准则是如果你 UI 的一部分需要用多次 (Button,Panel,Avatar),或者本身足够复杂(App,FeedStory,Comment),最好的做法是使其成为可复用组件。

    Props 是只读的

    无论你用函数或类的方法来声明组件, 它都无法修改其自身 props. 思考下列 sum (求和)函数:

    function sum(a, b) {
      return a + b;
    }
    

    这种函数称为 “纯函数” ,因为它们不会试图改变它们的输入,并且对于同样的输入,始终可以得到相同的结果。

    反之, 以下是非纯函数, 因为它改变了自身的输入值:

    function withdraw(account, amount) {
      account.total -= amount;
    }
    

    虽然 React 很灵活,但是它有一条严格的规则:
    所有 React 组件都必须是纯函数,并禁止修改其自身 props 。

    当然, 应用 UI 总是动态的,并且随时有可以改变。 所以在下一节, 我们会介绍一个新的概念 state(状态) 。state 允许 React 组件在不违反上述规则的情况下, 根据用户操作, 网络响应, 或者其他随便什么东西, 来动态地改变其输出。

    使用React.createClass()方法创建组件类

    React.createClass 方法就用于生成一个组件类,具体代码见demo04

      var HelloMessage = React.createClass({
        render:function () {
          return <h1>Hello {this.props.name}</h1>
        }
      });
    
      ReactDOM.render(
          <HelloMessage name="John" />,
          document.getElementById("example")
      );
    

    上面代码中,变量 HelloMessage 就是一个组件类。模板插入 <HelloMessage /> 时,会自动生成 HelloMessage 的一个实例(下文的"组件"都指组件类的实例)。所有组件类都必须有自己的 render 方法,用于输出组件。

    注意,组件类的第一个字母必须大写,否则会报错,比如HelloMessage不能写成helloMessage。另外,组件类只能包含一个顶层标签,否则也会报错。

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

    上面代码会报错,因为HelloMessage组件包含了两个顶层标签:h1和p。

    组件的用法与原生的 HTML 标签完全一致,可以任意加入属性,比如 <HelloMessage name="John"> ,就是 HelloMessage 组件加入一个 name 属性,值为 John。组件的属性可以在组件类的 this.props 对象上获取,比如 name 属性就可以通过 this.props.name 读取。

    添加组件属性,有一个地方需要注意,就是 class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。

    参考:

    相关文章

      网友评论

        本文标题:React.js的基础知识及一些demo(一)

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