细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

我也听说过React.js很好,最近花了一些时间玩它。既然我对React非常满意,我决定写一个关于这个主题的教程。

 

目标受众群:足够了解jQuery的人

在开始之前,我想澄清一下我的目标受众是谁。

在从未尝试过React的人们中,有些人对Backbone,Ember或Angular之类的前端JS框架感到满意,有些人非常了解JavaScript,有些人知道足够的jQuery可以解决。

对其中一些人有效的教程,对他一些可能就不是最佳的。

 

在本教程中,我针对的是我提到的第三组:了解jQuery的人。可能适合该类别的人员包括:

  • 可以在HTML / CSS / jQuery中进行基本编码的设计师。
  • 知道如何使用jQuery插件的WordPress开发人员。
  • 刚完成在线基本HTML / CSS / JS教程的开发人员。
  • 依靠Bootstrap和基本jQuery满足其前端需求的后端开发人员。
  • 在JavaScript方面,任何喜欢复制粘贴代码的人。

 

如果您对JavaScript或Backbone / Ember / Angular之类的任何前端框架感到满意,那么本教程不适合您,并且我的写作风格会让您感到沮丧。您可以从中学习很多很棒的教程,包括官方的React教程。另外,如果您已经知道React,那么您也会对我感到不高兴,因为我主要谈论的是状态而不是不变性或组合化。但是,我发现首先讲状态是jQuery开发人员了解React优越性的最好方法。

无论如何,让我们开始吧!

 

预计时间:1〜2小时

如果您走得很快(并且复制粘贴示例代码而不是键入内容),那么本教程将花费一个多小时。如果您走慢,则需要2个小时以上。

 

概述:我们将构建一个“ Tweet Box”

许多React.js教程都是从解释React的工作方式或为什么React很棒的开始。我的教程没有。

取而代之的是,我们将正确构建一个简单的UI,在jQuery实现和React.js实现之间进行交替,并解释其中的差异。我相信您会以更多的方式思考,而不是仅输入示例。

我们将构建的UI类似于您在Twitter上找到的Tweet框。它不会完全像真正的Tweet框,但会非常相似。希望您会发现这个例子很实际。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

步骤1:JSBin简介(5至10分钟)

我们将使用JSBin,一个在线HTML / CSS / JS编辑器,它同时支持jQuery和React.js代码。您可能熟悉诸如CodePenJSFiddle之类的类似服务-它们非常相似,因此我决定使用JSBin。

这是一个JSBin示例:

jsbin.com上的JS Bin 无法加载吗?请点击这里

尝试修改左侧的 HTML-即更改按钮的文本。您会在右侧看到更改。这就是JSBin的工作方式。

 

创建一个JSBin帐户

除非您已经有一个JSBin帐户,否则请转到jsbin.com创建一个帐户。单击菜单上的登录或注册以创建帐户。

创建帐户后,您可以公共JSBins 克隆到您的帐户中,就像克隆公共GitHub存储库一样。

让我们尝试一下。在下面的JSBin菜单上单击“保存”

jsbin.com上的JS Bin 无法加载吗?请点击这里

进入JSBin网站后,可以从菜单中选择“添加库”以导入流行的CSS / JS库。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

尝试执行以下操作

  • 点击“添加库”并添加最新的Bootstrap
  • btn btn-primary在上添加课程<button>

输出变得更漂亮:

jsbin.com上的JS Bin 无法加载吗?请点击这里

 

创建一个推文框

您现在似乎对JSBin非常满意。好吧,让我们建立一个Tweet框。仍与以前使用同一JSBin,像这样更改HTML里面的内容<body>

<div class="well clearfix">
  <textarea class="form-control"></textarea><br/>
  <button class="btn btn-primary pull-right">Tweet</button>
</div>

我们使用自举类像form-controlwellclearfix等等,但这些都只是对外观和不相干的教程。结果如下:


这就是步骤!还不错吧?

 

步骤2:实现第一个功能 – 禁用 Tweet 按钮(5分钟)

现在,该花点时间学习一些JS。我们将首先实现以下功能:

功能1:首先应禁用“ Tweet”按钮。如果文本字段中至少有一个字符,则应启用“ Tweet”按钮。

这是演示。如您所见,该按钮最初被禁用。如果在文本框中键入内容,该按钮将变为启用状态。

要使其正常工作,请从上一个JSBin继续,打开JavaScript选项卡,并添加以下jQuery代码。您不需要添加jQuery,因为我们在上一步中添加的Bootstrap包括jQuery。

// Initially disable the button
$("button").prop("disabled", true);

// When the value of the text area changes...
$("textarea").on("input", function() {
  // If there's at least one character...
  if ($(this).val().length > 0) {
    // Enable the button.
    $("button").prop("disabled", false);
  } else {
    // Else, disable the button.
    $("button").prop("disabled", true);
  }
});

 

说明

  • 我使用了标签名buttontextarea作为选择器-对于这个简单的示例,无需添加ID /类。
  • 要启用/禁用按钮,请使用$(...).prop(disabled, ...)
  • 要监听中的更改textarea,请使用input在现代浏览器上有效的事件。

 

通过在“推文”框中键入一些文本并查看按钮的启用/禁用状态更改进行尝试

如果这个例子让您感到困惑,请不要继续-您可能需要学习更多jQuery才能使用React。

现在,该功能已经完成,我们将尝试使用React重新实现相同的功能。这将需要几个步骤。

 

步骤3:使用React.js的Tweet框(5-10分钟)

在React中您会注意到的第一件事是,您将使用JS而不是HTML编写标记

让我告诉你我的意思。这是显示相同Tweet框的React.js代码。

 

警告!您不需要继续学习-只需阅读代码。

 

一些观察:

  • 里面return (...)是HTML代码,而不是JavaScript。在React中,您将使用称为JSX的特殊语法编写代码,该语法可将类似HTML的代码放入JavaScript中。
  • 我说HTML-“ like”是因为它与HTML不同。请注意,它使用className代替class-,但是它们非常相似,因此您将快速学习它们。
  • 您的浏览器不了解JSX,因此当React处理您的JSX代码时,它将自动将JSX中的HTML部分转换为有效的JavaScript代码,以便浏览器可以理解它。
  • 其中return (...)的HTML代码与步骤1中的HTML代码几乎相同。
  • 尝试单击上述JSBin上的“ HTML”,您会发现HTML中除了之外没有其他标记<body><div id="container"></div></body>。这就是我在React中说的意思,您将使用JavaScript(JSX)而不是HTML编写标记

 

常见问题与解答

问题:做什么React.createClassReactDOM.render做什么?我现在需要了解它们吗?
:暂时不要担心。基本上,React.createClass创建一个带有名称的UI(在本例中为TweetBox)。然后通过ReactDOM.render(<TweetBox />, document.getElementById("container"))– 将其附加到DOM,这意味着此UI已添加到<div id="container">标记内。这就是您现在需要知道的。

 

问题:在本地计算机上编写JSX时,我需要做些特殊的事情吗?
:是的,但这不在本教程的讨论范围之内-简而言之,您需要导入称为JSX转换器的东西(方法如下)。不过,在JSBin上不必执行此步骤。在JSBin上编写JSX所需要做的就是(1)从下拉列表中添加一个React库(一个没有插件的库),以及(2)从JS视图的下拉菜单中选择“ JSX(React)”。

 

问题:在同一位置编写标记(HTML)和行为(JS)是否不好?
:对于简单的网页来说这可能是一种不好的风格,但对于大型的Web应用程序却不一定是这样。在大型Web应用程序中,将有数百个UI,每个UI包含自己的标记和行为。如果将每个UI的那些标记和行为放在一起,而不是将“所有标记”放在一起和“所有行为”放在一起,则代码将更易于管理。React是为开发大型Web应用程序而设计的。实际上,React实际上是由Facebook创建和使用的,Facebook是有史以来最大的Web应用程序之一。

接下来,我将向您展示如何逐步编写上述React代码。

 

第4步:编写您的第一个React.js代码(5至10分钟)

我为您创建了一个入门HTML文件。使用“添加库”,我导入了Bootstrap(删除了bootstrap.js和jquery)和React(没有附加组件)。

请尝试跟随。首先,单击“保存”以将其复制到您的JSBin中。

保存到您的JSBin后,打开JavaScript选项卡,然后选择“ JSX(反应)”

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

现在您可以编写一些React了。尝试遵循并在您的JSBin上键入以下JS代码段

var TweetBox = React.createClass({
  render: function() {
  }
});

这是使用React(在本例中为Tweet框)创建UI的模板。$(function() { ... })与jQuery 一样重要。

 

要实际构建UI,我们必须填写该render()方法。现在,让我们仅用一个div标签就可以使其简单。

var TweetBox = React.createClass({
  render: function() {
    return (
      <div>
        Hello World!
      </div>
    );
  }
});

像上述例子中,把一对括号的(...)return,并写入标记的内部。

 

JSX陷阱

启用JSX时render(),您需要记住一件事,里面必须恰好有一个最外面的标签return (...)

因此以下操作无效,因为最外面的标签为零:

return (
  Hello World!
);

 

这也不起作用,因为里面有两个最外面的(span)标签return (...)

return (
  <span>
    Hello
  </span>
  <span>
    World
  </span>
);

 

对于上面的示例,解决方法是创建一个包装两个span标签的额外标签。我只是div在这里用过。使用React时这是必不可少的。

return (
  <div>
    <span>
      Hello
    </span>
    <span>
      World
    </span>
  </div>
);

 

将UI附加到DOM

现在,我们需要将该UI“附加”到DOM才能看到Hello World。为此,在我们刚刚编写的代码下面添加ReactDOM.render()

var TweetBox = React.createClass({
  ...
});

ReactDOM.render(
  <TweetBox />,
  document.getElementById("container")
);

请注意...代码段中的省略号()表示为清楚起见已省略了代码。换句话说,请勿触摸代码的这一部分并保持原样。)

 

ReactDOM.render有两个参数。第一个参数是UI对象,即<VariableName />。第二个参数是DOM对象(在本例中为document.getElementById("container"))。放在一起,上面的代码将TweetBoxUI 呈现在内部<div id="container">

现在,您应该看到Hello World出现在您的JSBin上。恭喜,您编写了第一个React UI!

 

 

编写推文框的实际HTML

现在,代替Hello World,我们将为Tweet Box实现HTML。交换内部代码render()

return (
  <div className="well clearfix">
    <textarea className="form-control"></textarea>
    <br/>
    <button className="btn btn-primary pull-right">Tweet</button>
  </div>
);

 

您需要注意两件事:

  • 不要使用class。而是使用className。这是因为JSX被翻译成JS,并且class是JS最新版本中的关键字。
  • 如果您使用<br>代替<br/>,它将无法正常工作。确保贴上/自动关闭标签。

其他所有内容都应与之前的jQuery示例相同。

 

如果输入正确,则应该在JSBin上看到Tweet框。如果输出中没有任何内容,请非常仔细地检查代码,以确保没有错别字。

这就是步骤!这是到目前为止的JSBin:

 

第5步:重新实现第一个功能-应在React中最初禁用Tweet按钮-5至10分钟

我们将在React中重新实现我们使用jQuery实现的第一个功能:

 

功能1:首先应禁用“ Tweet”按钮。如果文本字段中至少有一个字符,则应启用“ Tweet”按钮。

这是我们编写的jQuery代码:

<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <div class="well clearfix">
    <textarea class="form-control"></textarea><br>
    <button class="btn btn-primary pull-right">Tweet</button>
  </div>
</body>
</html>
// Initially disable the button
$("button").prop("disabled", true);

// When the value of the text area changes...
$("textarea").on("input", function() {
  // If there's at least one character...
  if ($(this).val().length > 0) {
    // Enable the button.
    $("button").prop("disabled", false);
  } else {
    // Else, disable the button.
    $("button").prop("disabled", true);
  }
});

让我们看看如何在React中做到这一点。

从上一步的JSBin开始。提示:由于您不会在React中触摸HTML,因此可以关闭JSBin上的HTML选项卡,以便获得更多的屏幕空间。)

 

首先,让我们通过添加禁用按钮disabled

render: function() {
  return (
    ...
    <button className="..." disabled>Tweet</button>
    ...
  );
}

 

然后,该按钮现在应该被禁用。注意,在我们的jQuery实现中,我们编写了:

$("button").prop("disabled", true);

最初禁用该按钮,但我们可以button像上面那样修改标记。

现在,当文本字段中至少有一个字符时,我们需要启用该按钮。

 

处理变更事件

首先,我们需要等待用户输入文本。在我们的jQuery实现中,我们写道:

$("textarea").on("input", function() {
  ...
}

 

在React领域,我们将事件处理程序编写为method让我们称之为handleChange

React.createClass({
  handleChange: function(event) {
  },
  render: function() {
    ...
  }
});

 

接下来,我们在输入文本时调用此处理程序。为此,请像这样修改textarea标记render()

<textarea className="form-control"
          onChange={this.handleChange}></textarea>
  • 我们将input事件用于jQuery,但是在React中我们将使用onChange-您将从React文档中了解事件在React的JSX中的不同之处,所以现在不必太担心。
  • 更重要的是,我们使用{...}语法在JSX的HTML语法部分内包含所有JavaScript代码。在这种情况下,我们要传递处理程序handleChange,并为其加上前缀,this.因为它是此UI对象上的方法。
  • 如果您习惯使用jQuery,这似乎是一种不好的做法,但是请不要担心。同样,在大型应用程序中,如果对于每个用户界面,这些标记和行为都保持在一起,则代码将更易于管理。

 

为了确保确实调用了该处理程序,让我们在console.log里面添加handleChange

handleChange: function(event) {
  console.log(event.target.value);
},

所述event对象包含target,这是textarea。我们用.value它来输出的当前值textarea

 

在您的JSBin中,打开console选项卡以检查输出。然后在“推文”框中键入内容。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

您可以在这里尝试:

注意:完成后,关闭JSBin上的控制台选项卡。我们不再需要它。

 

步骤6:执行中的状态(10到15分钟)

现在,我将解释jQuery风格的代码和React.js风格的代码之间的最大区别之一。

在jQuery中,当发生某些事件时,通常会更改DOM(就像我们之前所做的那样):

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

在React中,您不会直接修改DOM。相反,在事件处理程序中,您可以修改称为“状态”的内容。这是通过调用来完成的this.setState

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

然后,每次状态更新时,render()都会再次调用。而且在render()里面你可以访问状态

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

这是您响应事件来更新UI的方式。是的,这很令人困惑,所以让我解释一下代码。

 

编写事件处理程序

从上一步的JSBin开始。首先,我们需要初始化状态对象 -如果没有此对象,则将无法执行任何操作。

为此,我们需要编写一个称为的特殊方法getInitialState,并使其返回一个JS对象,该对象成为初始状态。

对象中有什么?让我们创建一个名为的密钥,text并将其存储在Tweet框中的任何内容。

var TweetBox = React.createClass({
  getInitialState: function() {
    return {
      text: ""
    };
  },
  handleChange: ...
  render: ...
});

 

接下来,我们将修改事件处理程序,以将状态text字段设置为当前文本框中的内容。为此,我们使用一种特殊的内置方法,称为,setState并传递更新的键值对。

handleChange: function(event) {
  this.setState({ text: event.target.value });
},

现在,我们通过在中编写一些仅调试的代码来检查状态是否已正确设置render()

 

为此,只需this.state.text在的末尾添加render(),然后使用该{ ... }语法在JSX的HTML语法部分内调用JS代码。

render: function() {
  return (
    <div ...>
      ...
      <button ...>Tweet</button>

      <br/>
      {this.state.text}
    </div>
  )
}

 

现在,尝试在推文框中输入一些文本。同一组文本应显示在按钮下方。

您也可以在下面的JSBin上尝试一下:

现在,上一张图可能对您更有意义。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

删除调试代码

确认正确设置了状态后,请删除我们刚刚添加的调试代码:

<br/>
{this.state.text}

 

启用/禁用按钮

现在我们可以监视文本的更改,剩下的就是根据是否输入文本来启用/禁用按钮。

使用状态,我们可以使用以下逻辑:

  • 如果为this.state.text.length === 0,则应禁用该按钮。

 

要在React中执行此操作,请添加disabled属性,并将其设置为返回值this.state.text.length === 0。由于这是JS代码,因此需要使用进行包装{}

<button className="btn btn-primary pull-right"
        disabled={this.state.text.length === 0}>Tweet</button>

 

如果您使用原始HTML 编写disabled="true"disabled="false"使用原始HTML,则无法使用-在原始HTML中,您需要删除disabled属性以启用按钮。但是React 不是原始的HTML-它在幕后做了以下魔术:

  • 如果disabled={true}使用JSX,它将转换为仅<button ... disabled>HTML。
  • 如果您disabled={false}使用JSX,disabled则会从buttonHTML 的标记中删除该属性。

这适用于其他布尔属性,例如checked。撰写本文时尚未正式记录,但应尽快将其包括在内。

 

生成的JSBin在这里:

 

感言

同样,在继续下一步之前,请记住jQuery和React之间的区别:

  • 在jQuery中,您编写了修改DOM的事件处理程序。
  • 在React.js中,您编写了可修改state的事件处理程序。然后您写render()以反映当前状态。

 

步骤7:jQuery中的剩余字符数(5分钟)

我们将实现的下一个功能是剩余字符数。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

规格如下:

  • 将显示字符数140 - the number of characters entered

 

我们将首先在jQuery中实现,然后在React中实现。

我们将从先前的jQuery实现开始。我们将保留我们的React.js代码。从现在开始,随着我们在jQuery和React之间交替,我将在每章的开头为您提供新的代码。这意味着在完成每个步骤之后,您可以先处理代码,然后再进行下一步。

 

首先,使用来添加HTML中的字符数span。让我们将其设置为span

<textarea ...></textarea><br>
<span>140</span>
<button ...>Tweet</button>

 

input里面的JS处理程序,添加以下代码来更新字符数

$("textarea").on("input", function() {
  $("span").text(140 - $(this).val().length);
  ...
});

 

而已!尝试在“推文”框中键入内容,您会看到字符计数更新。这是JSBin:

 

步骤8:React.js中的剩余字符数(5分钟)

在React中怎么样?您应该尝试自己执行此操作。从我们之前的React实现开始。

  • 无需更改getInitialState()handleChange()
  • this.state.text.length在中使用render()

 

回答:

render()中<br/>以下添加

<span>{140 - this.state.text.length}</span>


太容易了?不知道为什么React.js比jQuery好得多吗?好了,下一步变得更加复杂了,这就是React.js真正发挥作用的时候。

 

第9步:“添加照片”按钮(5分钟)

对于我们的下一个功能,我们将向用户界面添加“添加照片”按钮。这是事情变得棘手的时候。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

但是,我们实际上不会允许用户上传照片。相反,这是我们要做的。

当您在Twitter上上传照片时,它会计入您可以使用的字符数。我尝试将剩余字符数从140个减少到117个:

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

这就是我们要做的。规格如下:

  • 创建一个“添加照片”按钮。
  • 单击此按钮可切换开/关状态。如果打开,按钮将显示✓ Photo Added
  • 如果此按钮为开,则可用字符数减少23。
  • 同样,如果此按钮为ON,即使没有输入任何文本,“ Tweet”按钮仍保持启用状态。

 

这是演示JSBin。尝试单击“添加照片”按钮,查看字符数和“tweet”按钮会发生什么。

让我们实现它。我们将首先尝试使用jQuery。

 

步骤10:使用jQuery的“添加照片”按钮(15-20分钟)

从我们先前的jQuery实现开始。

我们将同时修改HTML和JS。之前,我们在上附加了一个处理程序$("button"),但是如果有两个按钮,则此方法将无效。因此,让我们像这样修改HTML

...
<button class="js-tweet-button btn btn-primary pull-right" disabled>Tweet</button>
<button class="js-add-photo-button btn btn-default pull-right">Add Photo</button>
...

 

更改如下:

  • 添加了第二个按钮 “添加照片”。
  • 添加了类js-tweet-buttonjs-add-photo-button每个按钮。之所以加上前缀,js-是因为它们仅在JS中使用,而不在CSS中使用。
  • disabled属性添加到“推文”按钮,因此我不必在JS中执行此操作。

 

接下来,像这样重写整个JS文件:

$("textarea").on("input", function() {
  $("span").text(140 - $(this).val().length);

  if ($(this).val().length > 0) {
    $(".js-tweet-button").prop("disabled", false);
  } else {
    $(".js-tweet-button").prop("disabled", true);
  }
});

 

更改如下:

  • (重要)$("button").prop("disabled", true);已从第一行删除,因为我disabled在“推特”按钮中添加了属性,
  • 替换为$("button")$(".js-tweet-button")因此可以与区别.js-add-photo-button

 

添加按钮

接下来,我们将实现以下功能之一:

  • 单击“添加照片”按钮切换ON / OFF状态。如果打开,按钮将显示✓ Photo Added

 

为此,我们添加以下代码

$("textarea").on("input", function() {
  ...
});

$(".js-add-photo-button").on("click", function() {
  if ($(this).hasClass("is-on")) {
    $(this)
      .removeClass("is-on")
      .text("Add Photo");
  } else {
    $(this)
      .addClass("is-on")
      .text("✓ Photo Added");
  }
});

我们使用该类is-on来跟踪状态。多次单击“添加照片”按钮,然后交替查看文本,以检查是否有效

 

减字符数

接下来,我们将实现此功能:

  • 如果“添加照片”按钮为开,则可用字符数减少23。

 

为此,请像这样修改刚刚添加的点击处理程序

if ($(this).hasClass("is-on")) {
  $(this)
    .removeClass("is-on")
    .text("Add Photo");
  $("span").text(140 - $("textarea").val().length);
} else {
  $(this)
    .addClass("is-on")
    .text("✓ Photo Added");
  $("span").text(140 - 23 - $("textarea").val().length);
}

span每次点击都会更改的文本。如果按钮变为ON,则需要从117中减去文本长度,即140 - 23140 - 23现在我们为了清楚起见使用-最终我们应该使用常量。

单击“添加照片”按钮,以检查是否可以使用

 

修复输入处理程序

但是,这还不完整- 如果您打开了“添加照片”按钮并开始在文本区域中键入内容,则剩余字符数将不同步。

要解决此问题,我们还需要更新以下输入处理程序textarea

$("textarea").on("input", function() {
  if ($(".js-add-photo-button").hasClass("is-on")) {
    $("span").text(140 - 23 - $(this).val().length);
  } else {
    $("span").text(140 - $(this).val().length);
  }

  if (...) {
    ...
});

请检查该作品点击“上传照片”按钮,并输入一些文字。

 

我知道这需要一些时间…

但是坚持下去!此处的jQuery代码应该令人困惑,所以不用担心!

 

实施最终功能

我们需要实现的最后一个功能是:

  • 如果“添加照片”按钮为开,则即使没有输入文字,“推文”按钮仍保持启用状态。

 

为此,我们需要修改“添加照片”按钮的点击处理程序:

$(".js-add-photo-button").on("click", function() {
  if ($(this).hasClass("is-on")) {
    ...
    if ($("textarea").val().length === 0) {
      $(".js-tweet-button").prop("disabled", true);
    }
  } else {
    ...
    $(".js-tweet-button").prop("disabled", false);
  }
});

 

解释如下:

  • 如果“添加照片”按钮从“开”变为“关”(if子句),我们需要检查是否未输入文本,如果是,请禁用“推文”按钮。
  • 如果“添加照片”按钮从“关闭”变为“开启”(else子句),我们将始终启用“推文”按钮。

 

但是,这又被打破了

我们还没有完成。以下步骤将破坏代码。自己尝试一下

  • 打开“添加照片”按钮。
  • 输入一些文字。
  • 删除所有文本。
  • 由于“添加照片”按钮处于打开状态,因此应该仍启用“推特”按钮,但实际情况并非如此。

 

这意味着我们的输入处理程序textarea缺少一些逻辑。为了解决这个问题,我们需要if在输入处理程序的语句中添加另一个条件

$("textarea").on("input", function() {
  ...
  if ($(this).val().length > 0 || $(".js-add-photo-button").hasClass("is-on")) {
    ...
  } else {
    ...
  }
});

 

我们对是否应禁用按钮添加了以下检查:

  • 文本更改时,如果“添加照片”按钮为开,则不要禁用该按钮。

 

再次尝试上述步骤,这次不会中断。

 

第11步:对jQuery代码的思考-为什么如此令人困惑?(5分钟)

这是上一步的最终HTML和JS代码:

 

再次看一下jQuery代码。这非常令人困惑。如果您将代码保持原样,则可能需要一些注释,以便您记住所做的事情。有明显的重复迹象,但是您必须对如何重构进行一些思考。

 

问题是:为什么它变得如此丑陋如此之快?

答案与我们之前讨论的“ jQuery样式”有关。回想一下这个图:

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

当只有1个事件处理程序和1个DOM时,这很简单。但是,就像我们刚刚看到的那样,如果多个事件处理程序正在修改DOM的多个部分,则代码将变得难看。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

想象添加了一些可能影响字符数限制和“ Tweet”按钮状态的功能。上图将有更多箭头。而且代码将变得难以管理。

 

从理论上讲,您可以通过重构为可重用的函数来减轻这种情况。但是,每次添加新内容时,您仍然都必须认真考虑一下。(更新:Hacker News的某人向我发送了重构的jQuery代码。非常干净,但是又需要一些思考。)

现在,让我们看看在React中做同样的事情的感觉。提示:它将变得更加简单。

 

步骤12:React中的“添加照片”按钮(10-20分钟)

从我们之前的React实现开始。

 

添加按钮

首先,让我们添加“添加照片”按钮。修改JSX

<button ...>Tweet</button>
<button className="btn btn-default pull-right">Add Photo</button>

 

现在,让我们向该按钮添加一个点击处理程序,以使文本从Add Photo变为✓ Photo Added。回想一下React的编写代码风格:

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

我们会:

  1. 创建一个状态变量,以跟踪“添加照片”按钮是打开还是关闭。
  2. 使用状态render(),以决定是否显示Add Photo✓ Photo Added
  3. 修改点击处理程序上的状态

 

对于(1),我们将getInitialState在状态下修改并添加一个键值对,以跟踪是否添加了照片:

getInitialState: function() {
  return {
    text: "",
    photoAdded: false
  };
},

 

对于(2),我们将为 “添加照片”按钮修改JSX标记。如果this.state.photoAdded为true,我们将显示“添加照片”按钮。我们可以在这里使用三元表达式。

<button className="btn btn-default pull-right">
  {this.state.photoAdded ? "✓ Photo Added" : "Add Photo" }
</button>

 

最后,对于(3),我们将在JSX上附加一个点击处理程序,就像对以下操作一样textarea

<button className="btn btn-default pull-right"
  onClick={this.togglePhoto}>
  {this.state.photoAdded ? "✓ Photo Added" : "Add Photo" }
</button>

 

添加一个与之相反的处理程序方法this.state.photoAdded

togglePhoto: function(event) {
  this.setState({ photoAdded: !this.state.photoAdded });
},

现在,单击Add Photo将切换文本。自己尝试一下

 

减字符数

现在,我们将实现下一个功能:

  • 如果“添加照片”按钮为开,则可用字符数减少23。

 

当前,可用字符数显示如下render()

<span>{140 - this.state.text.length}</span>

现在这也将取决于this.state.photoAdded,因此我们需要ifand else在这里。

但是,在JSX中,您不能编写ifelseinside{ ... }。您可以a ? b : c像以前一样使用三元表达式(),但是在这种情况下会很长。

 

通常,在这种情况下,最简单的方法是将条件重构为方法。让我们尝试一下。

首先,修改上面的代码以使用如下方法

<span>{ this.remainingCharacters() }</span>

 

并定义如下方法:

remainingCharacters: function() {
  if (this.state.photoAdded) {
    return 140 - 23 - this.state.text.length;
  } else {
    return 140 - this.state.text.length;
  }
},

现在,当切换“添加照片”按钮时,剩余字符数应相应更新。

 

:在render(),为什么{ this.remainingCharacters() }(),但{ this.handleChange }{ this.togglePhoto }没有?

好问题。让我们render()再看一看:

render: function() {
  return (
    ...
      <textarea className="..."
                onChange={ this.handleChange }></textarea>
      ...
      <span>{ this.remainingCharacters() }</span>
      ...
      <button className="..."
        onClick={ this.togglePhoto }>
        ...
      </button>
    </div>
  );

 

  • 我们已经编写remainingCharacters()返回数字的方法。我们需要获取此数字并将其放在中间<span></span>,因此我们需要使用来调用 remainingCharacters() method ()。这就是为什么有()remainingCharacters()
  • 另一方面,handleChangetogglePhoto事件处理程序。我们希望仅在用户与UI交互(更改文本或单击按钮)时才调用这些方法。为此,在中render(),我们需要编写不带它们的代码,()并将它们分配给诸如onChange和的属性onClick

 

“ Tweet”按钮的状态

我们还有另一个功能要实现:

  • 如果“添加照片”按钮为开,则即使没有输入文字,“推文”按钮仍保持启用状态。

 

这实际上很容易做到。以前,“tweet”按钮的disabled选项设置为:

<button ... disabled={this.state.text.length === 0}>...</button>

 

换句话说,以前如果文本的长度为0 ,则“ Tweet”按钮被禁用。现在,如果满足以下条件,则“ Tweet”按钮被禁用

  • 文字的长度为0,
  • “添加照片”按钮处于关闭状态。

 

因此逻辑变为:

<button ... disabled={this.state.text.length === 0 && !this.state.photoAdded}>...</button>

 

或者,您可以利用简化上述代码remainingCharacters()。如果剩余140个字符,则表示不输入任何文本,并且“添加照片”按钮为OFF,因此应禁用“ Tweet”按钮。

<button ... disabled={this.remainingCharacters() === 140}>...</button>

而已!尝试切换“添加照片”按钮,并检查“ Tweet按钮”是否已正确启用/禁用。

 

我们做完了!

那很简单。这是生成的JSBin:

 

步骤13:对React代码的反思-为什么这么简单?(5分钟)

使用React时,为适应“添加照片”按钮所做的更改很小。无需重构。为什么会这样呢?

同样,它与React编写UI代码的风格有关。在React中,事件处理程序会修改“状态”,并且每当修改状态时,React都会自动render()再次调用以更新UI。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

在此特定示例中,该图现在看起来像这样:

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

状态变成介于事件处理程序和render()以下事件之间的中间事物:

  • 事件处理程序不必担心DOM的哪一部分会更改。他们只需要设置状态。
  • 同样,在编写时render(),您只需担心当前state是什么。

 

与jQuery比较

您可以想象,随着UI获得更多功能,将会发生什么。没有中介“状态”,我们将很难处理复杂性。这就是为什么您要针对复杂的UI使用React over jQuery的原因。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

同样,可以编写看起来不像意大利面条的干净的jQuery代码。但是您必须自己弄清楚代码结构,并在每次添加新功能时考虑如何重构。React为您提供了这种结构并减轻了您的认知负担。

 

步骤14:最终功能-突出显示溢出字符(5分钟)

我们要实现的最后一个功能是突出显示超出限制的字符

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

不幸的是,我们不会在Tweet框内突出显示实际文本,因为这将需要我们更改textareacontenteditable,并且contenteditable出于说明目的太复杂了。

相反,我们将在顶部显示一个警告框,并指出需要删除的字符,如下所示:

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

要试用,请复制史蒂夫·乔布斯的以下报价:

如果尚未找到它,请继续寻找。别解决 与内心所有事情一样,当您找到它时就会知道。而且,就像任何伟大的关系一样,随着岁月的流逝,这种关系会越来越好。

 

并将其粘贴到下面的“ Tweet”框中:

  • 它应该显示一个警告框,其中溢出的字符以红色突出显示
  • 它也应该在截止点之前显示10个字符,并且不突出显示。

 

如果我们要在jQuery中实现这一点,我们的代码将更加混乱。请注意,在图中,我们将为一项新功能添加另外两个箭头。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

所以我们不会在jQuery中实现它。我们将在React中进行,并称之为一天。在React中做起来非常简单-图表上只有一个额外的箭头:

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

第15步:突出显示React中的溢出字符(10-15分钟)

从我们之前的React实现开始。

我们将逐步进行此操作。首先,当您超出限制时我们将显示一个简单的警报。该警报将包含一些静态文本。

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

由于这将需要条件,因此我们将其编写为单独的方法。在文本框前面添加{ this.overflowAlert() }

{ this.overflowAlert() }
<textarea className="form-control"
          onChange={this.handleChange}></textarea>

 

现在,此方法应返回:

  • 如果没有更多的字符,则为警报框的div标签
  • 否则没有其他内容(即空文本)。

 

事实证明,在React中,您可以从一个方法返回JSX标记,并在其他方法中使用它,一切都将正常工作。换句话说,您可以执行以下操作:

someMethod: function() {
  return (
    <a href="#">Hello World</a>
  );
},
someMethod2: function() {
  return (
    <h1>
      { this.someMethod() }
    </h1>
  );
},

 

在我们的情况下,我们可以( <div> ... </div> )在一种情况下返回,而在另一种情况下什么也不能返回。因此,我们的overflowAlert方法将如下所示:

overflowAlert: function() {
  if (this.remainingCharacters() < 0) {
    return (
      <div className="alert alert-warning">
        <strong>Oops! Too Long:</strong>
      </div>
    );
  } else {
    return "";
  }
},

注意,我们正在检查this.remainingCharacters()是否应该显示警报。

 

通过键入140+个字符(或在“添加照片”按钮为ON的情况下输入117+个字符)来尝试一下。它应该显示警报。

 

显示溢出字符

这是警报消息中内容的细分:

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

  • 在“糟糕!太长:”和实际文本之间,有一个空的单个空格,后跟三个点。我&nbsp;在这里使用它是因为在React中编写标记时,标签之间的空白会被删除。
  • 然后是的第131〜140个字符(共10个)this.state.text
  • 然后,其余字符以红色突出显示。

 

让我们用JSX编写它。在的if子句中overflowAlert,我们将创建两个变量:beforeOverflowTextoverflowText。我们将.substring()在上使用method this.state.text

if (this.remainingCharacters() < 0) {
  var beforeOverflowText = this.state.text.substring(140 - 10, 140);
  var overflowText = this.state.text.substring(140);

  return (
    <div className="alert alert-warning">
      <strong>Oops! Too Long:</strong>
      &nbsp;...{beforeOverflowText}
      <strong className="bg-danger">{overflowText}</strong>
    </div>
  );
}
  • 如果这样做.substring(a, b),它将从字符串中返回a + 1bth个字符。
  • 如果这样做.substring(a),它将返回a + 1字符串中的最后一个字符。
  • 我们使用Bootstrap的bg-danger类以红色突出显示文本。

 

复制后再次粘贴此文本,然后查看正确的文本。我们快完成了!

如果尚未找到它,请继续寻找。别解决 与内心所有事情一样,当您找到它时就会知道。而且,就像任何伟大的关系一样,随着岁月的流逝,这种关系会越来越好。

 

如果“添加照片”按钮处于打开状态怎么办?

如果“添加照片”按钮为ON,则字符限制由23降低所以我们beforeOverflowTextoverflowText需要考虑到这一点:

if (this.state.photoAdded) {
  var beforeOverflowText = this.state.text.substring(140 - 23 - 10, 140 - 23);
  var overflowText = this.state.text.substring(140 - 23);
} else {
  var beforeOverflowText = this.state.text.substring(140 - 10, 140);
  var overflowText = this.state.text.substring(140);
}

 

现在,尝试在输入任何超出限制的文本时切换“添加照片”按钮。它应该可以正常工作。这是JSBin:

而已!同样,您可以看到代码更改很简单:

细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

步骤16:下一步是什么?(5分钟)

我的教程到此结束。希望你学到了:

  • jQuery代码与React代码之间的区别,以及
  • 如何在JSX中编写一些基本的React代码。
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比
细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

 

 

 

本文:细数jQuery和React用法差别, jQuery转React, jQuery和React的区别, jQuery和React实例对比

Leave a Reply