JQuery 重度用户学习 Vue.js 的指南

Posted 奇舞周刊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JQuery 重度用户学习 Vue.js 的指南相关的知识,希望对你有一定的参考价值。

(图片来自网络)

编者按:本文由smartsrh在众成翻译平台上翻译。jQuery应该是每个前端初学者第一个学习的js库,当你熟练掌握jQuery之后,学习使用一个框架,比如说Vue.js的话,你会碰到什么问题呢?下面让我们来看看吧~

这几年学习 javascript 我是痛并快乐着。

我最开始学 JavaScript 是设计和编程圈子里最喜欢折腾的 jQuery。 作为一个「会编程的设计师」, jQuery 对我来说是一个神奇的存在。 我可以轻松实现淡入淡出的效果。 在第三方库的支持下, 只调用一个函数我就可以实现视差滚动。 这小小 100kb 文件中几乎包含了所有我能想到的效果。

Angular 出来以后,我不得不用它把我的作品重新实现一遍。React 出来以后,我又不得不基于它重新实现一遍。Vue.js 出来以后,我又不得不基于它重新再来。

玩笑归玩笑,我非常享受用这些框架来学习 JS 的过程。学习过程中我读了无数篇文章和教程,但只有上杉周作的《为 JQuery 重度用户介绍 React.js》这篇文章让我印象深刻。

JQuery 重度用户学习 Vue.js 的指南

只需一些基本的 JS 和 JQuery 的知识,通过重构推特网发推特的页面,上衫向我们展示了一个完整的 React 世界。

这篇文章,对我这类从实践中学习的人而言是很有帮助的。每当一个新的框架出来后,我都会用它重新把东西实现一遍。因此,我也仿照这篇文章,带你重温我最近学习 Vue 的过程。

我强烈建议在读我接下来写的内容之前,先读一下上衫写的那篇文章。因为他在文章中介绍了实现这些效果的 JQuery 代码,尽管其中的一些代码比较简单。所以我这里就不多说了,直接进入 Vue 的主题。

我们要做什么

推特很多人都用,下面这个界面大家都很熟悉。

JQuery 重度用户学习 Vue.js 的指南

这个界面是一个很好的例子,像我们展示了如何用 Vue (或者上衫说的 React)来提升 JS 编程的舒适度。这个界面由以下几个部分构成:

  • 用来输入推文的 <textarea>

  • 发推文的 <button>,如果推文超过指定长度按钮就 disabled

  • 一个剩余可输入字数的计数器,小到某个阈值就变色提示用户快到规定字数了

  • 一个相机图表,点击可以上传图片

  • 一个列表显示已经上传的图片

  • 每个照片上有一个按钮,点击就可以删除照片

欢迎向我咨询

如果你感觉文章中什么地方很困惑,我没有解释清楚,可以立马在推特上找我 @mattrothenberg。一定要记住,这篇文章是我的感受,可能和你的不完全一样。

那么我们开始吧。

写代码的过程

我用 CodePen 来完成这个例子。CodePen 就不过多介绍了。

步骤一: 搭好框架

在写 JS 之前,需要先写一个静态的发推特页面。用 Tachyons 可以快速搭建好看的前端页面,Tachyons 让我们少写很多 CSS,专注于 JS 和静态页面的搭建。

我不会详细说 Tachyons 怎么用,假设你已经会用了。

我已经提前把 Vue 通过 CDN 加载好了,Vue 的一大优点就是精简,可以融入其它代码库。

万事俱备,就开动吧。

步骤二: 第一个功能——发推特的按钮开始应该是禁用的

To Disable or Not To Disable, that is the question

功能描述: 当用户向 textarea 输入至少一个字符才能移除禁用。

首先,用以下创建一个 Vue 实例。可见 Vue 以其简单易用的特性受广大开发者的喜爱。

new Vue({

  el: '#twitterVue',

  data: {

    tweet: ''

  },

  computed: {

    tweetIsEmpty: function() {

      return this.tweet.length === 0;

    }

  }

})

我来解释一下刚刚的代码是干嘛的:

  • el 是 Vue 实例所绑定的一个 DOM 元素,和 jQuery 的属性选择器一个意思。

  • data 是连接 Vue 实例和 DOM 元素的属性。可以在 html 中用{{tweet}}来获取其中的数据,也可以在 Vue 实例中用 tweet 访问这个数据(注意 tweetIsEmpty函数就使用了这个属性)。

  • computed 顾名思义,是用 Vue 实例中已有的属性计算出来的属性。推荐在 computed 中定义逻辑方法来得到这类需要计算的值(状态),可以避免在 HTML 中引入繁琐的逻辑。

现在请注意我们的 HTML 相比之前也有一些小小的三个变化:

1.  给最外层的 div 加上了 twitterVue 的 id,这样就完成了我们的 Vue 实例创建。

<div id="twitterVue">...</div>

2. v-model 指令在用户输入和 Vue 实例的 data 之间创建了双向绑定data 属性里tweet的值会随着用户在textarea输入的改变而自动改变。

<textarea v-model="tweet"></textarea>

3. 添加了 :disabled属性到按钮中。disabled前的冒号将引号内的语句当成 JavaScript 表达式运行。如果我们忽略冒号,内容将被视为一个字符串。 我还添加了几行 CSS,使禁用按钮具有独特的视觉样式。

<button :disabled="tweetIsEmpty">Tweet</button>

button[disabled] {

cursor: not-allowed;

opacity: .5;

}

4. 在实例上添加了一个计算属性tweetIsEmpty。该属性实际上是基于tweet属性的长度返回一个布尔值的函数。 Vue 使得在 HTML 和实例本身中访问数据模型变得简单。由于双向数据绑定的魔力,当 tweet 的值更新时,tweetIsEmpty也会重新运行,求值为true时,按钮被禁用。

tweetIsEmpty: function() {

return this.tweet.length === 0;

}

不得不说,当我第一次使用Vue时,感觉非常魔幻。当然真正了解这些函数和指令是如何操纵实例和 HTML 后 Vue 对我帮助更大。简而言之可以通过前面提到的大括号语法轻松访问 HTML中的数据模型,构建一个快速、可视化的反馈循环,这就够了。

<p>The value of <strong>tweet </strong>is: **{{tweet}}** </p>

<p>The value of <strong>tweetIsEmpty</strong>is: **{{ tweetIsEmpty}}**</p>


演示demo请点击底部阅读原文


可以随意重复这些步骤,如果有什么地方感到困惑(我的写作或代码可能有问题,或是 Vue 本身的问题),可以发送推文或发表评论。

步骤三: 第二个功能 - 显示剩余的字符数

功能描述:当用户输入时,显示推文中剩余可键入的字符数(最多 140 个)。如果用户输入的字符超过 140 个字符,就禁用蓝色的按钮。

现在我们已经学会了双向数据绑定和计算属性,它们是 Vue 的核心概念。因此可以利用这些概念来构建我们的下一个功能:显示用户剩下多少个字符(140个),当没有剩余时就禁用该按钮。

下面是实现此功能所需的 JavaScript 和 HTML 的一些改动。

首先更改 JS :

1. 首先定义一个常量 MAX_TWEET_LENGTH 表示允许输入的最大字符数

const MAX_TWEET_LENGTH = 140;

2. 然后添加另一个计算属性charactersRemaining,动态返回 140 和用户输入的tweet的长度之差

charactersRemaining: function() {

  return MAX_TWEET_LENGTH - this.tweet.length;

}

3. 最后将旧的 tweetIsEmpty 属性重命名为 tweetIsOutOfRange 并更新函数逻辑。注意如何使用计算属性charactersRemaining来计算该值。 为这里的代码复用喝彩!

tweetIsOutOfRange: function() {

  return this.charactersRemaining == MAX_TWEET_LENGTH

      || this.charactersRemaining < 0;

 }

HTML方面,得益于Vue的双向数据绑定功能,只需要做一些小修改就行了。

<div class="flex items-center">

  <span class="mr3 black-70">**{{ charactersRemaining }}**</span>

  <button **:disabled="tweetIsOutOfRange"** class="button-reset bg-blue bn white f6 fw5 pv2 ph3 br2 dim">Tweet</button>

</div>

演示demo请点击底部阅读原文

步骤四:实现第三个功能,「剩余字符」的条件样式

功能说明:撰写推特仅剩 20 个字符时,「剩余字符」的颜色应变为深红色,剩下十个或更少时变为浅红色。

使用 jQuery 操作元素的样式或 class 可能很麻烦,Vue 提供了一种更简洁的方法。Vue 的方法感觉更具声明性,只需描述想要改变某种样式的方式(比如基于某个给定的属性),把其它繁重的任务交给 Vue 完成。

本例中,字符剩余有两种状态,每个都需要一个相应的 class。

1. 当剩余字符数是十到二十个时应该添加 dark-red 的 class

2. 当剩余字符数小于十个时应该添加 light-red 的 class

现在你在潜意识里应该大喊「计算属性!」所以,让我们听从这个想法,并把这些属性用computed方法关联起来。

underTwentyMark: function() {

  return this.charactersRemaining <= 20

    && this.charactersRemaining > 10;

  },

underTenMark: function() {

  return this.charactersRemaining <= 10;

}

根据我们的逻辑,让我们来看看 Vue 处理条件样式的方法之一:v-bind:class指令。此伪指令的参数是一个键为 CSS class 的对象,键对应的值是计算属性。

{ 'dark-red': underTwentyMark, 'light-red': underTenMark }

在包含「剩余字符」指标的span标签中添加以上指令,我们就完成了所需要的功能。

<span v-bind:class="{ 'dark-red': underTwentyMark, 'light-red': underTenMark }">

  {{ charactersRemaining }}

</span>

在这些钩子函数和双向数据绑定的作用下,Vue 将根据指定的计算属性来添加和删除这些类。

演示demo请点击底部阅读原文


步骤五:实现第四个功能:上传照片

功能说明:允许用户通过文件选择器对话框将一张照片附加到他们的推文。上传照片后,将其显示在textarea下方,并允许用户通过单击图像删除附件。

请注意:本节内容比较多。尽管看起来本步骤增加了相当多的功能,但我们不必编写太多的代码。现在让我们将交互逻辑分解为小步骤来分析。

1. 用户点击「添加照片」按钮

2. 用户看到一个文件选择器对话框,可以选择一个要上传的照片

3. 选择照片后,将在文本区域下方显示一个框,其中包含所选的照片

4. 用户点击圆形 X 按钮删除照片

5. 用户回到步骤 1

到目前为止,我们还没有完成任何事件处理(监听按钮的点击和输入的更改等)。Vue 可以通过v-on指令(简称@)来监听事件。通过传递方法作为此指令的值,我们可以有效地监听 DOM 事件,并在事件触发时运行指定的 JavaScript。

在编写我们需要的功能之前,我们先来一个简单的练习

事件处理非常简单,将@click指令添加到给定按钮就可以了,并将相应的方法添加到 Vue 实例的method里。

<button @click"="logNameToConsole">Log User's Name</button>


methods: {

  logNameToConsole: function() {

    if( this.name !== 'Donald Trump' ) {

      console.log(this.name);

    } else {

      console.warn('Sorry, I do not understand');

    }

  },

}

现在来编写我们需要的功能 ... 我们的 HTML 和 JavaScript 需要做如下变化:

我们添加了一个带有@click指令的按钮。当用户单击此按钮时,将会调用triggerFileUpload方法。

<button [@click](http://twitter.com/click "Twitter profile for @click")="triggerFileUpload">...</button>

所以,在我们的 JavaScript 中,为我们的Vue实例添加一个method方法和新的data属性如下:

data: {

 photo: null

},

computed: {},

methods: {

  triggerFileUpload: function() {

    this.$refs.photoUpload.click(); // 这是什么鬼?

  },

}

自定义 HTML5 文件输入样式非常困难。 一个解决方法是将一个<input>元素放在 DOM 中并用 CSS 隐藏它。为了让浏览器打开本地文件选择器,又必须单击这个隐藏的<input>元素。不管怎样,如何点击<input>元素和客户端怎样处理用户上传的内容是没有关系的。

在我们的 HTML 中,我们添加了一个这样的<input>元素并用一个特殊的 hide class 隐藏它。 我们还添加了一些其他属性:

<input ref="photoUpload" @change="handlePhotoUpload" type="file" class="hide">

  • ref属性用于注册给定 DOM 元素的引用,在 JavaScript 代码中可以使用$refs.photoUpload来访问我们的 DOM 元素。这意味着我们可以通过编程方式触发此元素上的click事件,从而规避了上述难题。

  • 点击<input>元素是一个难题; 处理用户上传的文件是另一个难题。幸运的是,Vue 允许我们通过@change指令将处理程序绑定到<input>元素的更新事件上。在用户从文件选择器中选择文件后,我们绑定在该指令的方法将被调用。 该方法handlePhotoUpload是相当简单的

handlePhotoUpload: function(e) {

  var self = this;

  var reader = new FileReader();


  reader.onload = function(e) {

    // Set that base 64 string to our data model's 'photo' key

    self.photo = (e.target.result);

  }

  // Read upload file as base 64 string

  reader.readAsDataURL(e.target.files[0]);

 }


演示demo请点击底部阅读原文


深吸一口气,因为我们几乎快完成这个功能了!

用户上传照片后,我们需要在textarea下方显示一个包含所选照片的框。正如元素的条件样式用 Vue 能轻松实现一样,条件渲染也是小菜一碟。注意我们在textarea下面添加了以下 HTML:

<div v-if="photoHasBeenUploaded">

  <figure>

    <button @click="removePhoto">

      ...

    </button>

    <img v-bind:src="photo">

  </figure>

</div>

Vue 提供了一些模板助手(v-ifv-showv-else等)来有条件地显示和隐藏内容。当传递给该指令的 JavaScript 表达式求值为 true 时,元素将被渲染,反之隐藏。

在我们的例子中,我们添加了一个v-if语句来用计算属性photoHasBeenUploaded来控制是否渲染图片。

photoHasBeenUploaded: function() {

  return this.photo !== null;

}

当该函数返回值为真时(当dataphoto键不等于null时)整个div被渲染。

而在div里面,我们渲染了两个元素:

1. 通过将dataphoto键的内容传递给 Vue 的v-bind:src指令来加载图像

2. 一个删除按钮,其中利用了@click来处理点击事件,绑定了一个函数,通过将dataphoto键的内容设置为null来「删除」照片

removePhoto: function() {

  this.photo = null;

}

我们就快完成任务了。

步骤六:修正,用户可以上传多张「照片」

我们现在可以有效地处理一个用户上传一张照片到推特,但如果 Ta 想上传更多照片怎么办?

到目前为止,你应该考虑一下:「之前我们已经绑定了我们的事件处理函数,我想这里唯一重大的变化就是能够在textarea下有条件的显示出多个图像...」你想的很正确!我们来看看我们需要遵循的步骤:

1. 我们需要通过将dataphoto键更改为photos来更新我们的数据模型,新的键是一个 base64 字符串的数组(不是一个 base64 字符串)

data: {

  photos: []

},

2. 我们需要更新我们的计算属性photoHasBeenUploaded来检查我们的photos数组的长度

photoHasBeenUploaded: function() {

  return this.photos.length > 0;

}

3. 我们需要更新我们输入监听@change绑定的处理函数,循环上传的文件并将其推送到我们的photos数组里。

handlePhotoUpload: function(e) {

  var self = this;

  var files = e.target.files;


  for(let i = 0; i < files.length; i++) {

    let reader = new FileReader();


    reader.onloadend = function(evt) {

 self.photos.push(evt.target.result);

    }


 reader.readAsDataURL(files[i]);

  }

},

但是,在HTML方面,我们必须用新的方法,因为用 jQuery 来迭代数据和渲染内容可能很麻烦。

var array = [1, 2, 3, 4, 5];

var newHTML = [];

for (var i = 0; i < array.length; i++) {

 console.log('UGHHHHHH');

    newHTML.push('<span>' + array[i] + '</span>');

}

$(".element").html(newHTML.join(""));

幸运的是,Vue 通过v-for指令提供了对该过程的抽象。这个指令的参数是(thing,index)的一个集合形式,这种集合一般是是源数组,thing指代数组中的元素,而index是该元素的索引。

一个典型的例子可能如这个 Codepen

之前我们为用户上传的照片提供了一个单一的figure元素,我们现在将有Nfigure元素对应于photos数组的长度。

幸运的是,由于设计的整体结构仍然相同,因此我们的 HTML 不必变化太大。

<figure v-for="(photo, index) in photos">

  <button @click="removePhoto(index)">

    ...

  </button>

  <img v-bind:src="photo" class="h3 w3">

</figure>

我们需要做的一个改变是removePhoto这个方法,之前,这个方法将将data的单个photo键的内容设置为null。 现在,由于我们有N张照片,我们必须将元素的索引传递给removePhoto方法,并将该元素从数组中删除。

removePhoto: function(index) {

  this.photos.splice(index, 1);

}

步骤七:动画 + 额外修改

在推特的用户界面中,编写推特的组件是以模态弹窗的形式打开。我们的最后一个任务就是实现这个弹窗,我想要应用我们迄今为止学到的所有 Vue 技术,再加一个新的 Vue 技术 —— 过渡。

实际上,过渡是 Vue 的一个重要的内容,我们现在实现的动效仅仅是其中的冰山一角,我们用第三方动画库 Velocity.js 与 Vue 集成。

简而言之, Vue 提供了一个过渡组件,可以为包含的元素添加进入/离开的动画,前提是该元素通过例如v-ifv-show指令有条件地显示。

<transition

  name="modal-transition"

  v-on:enter="modalEnter"

  v-on:leave="modalLeave">

    <div v-if="modalShowing">

      <!-- Our modal contents goes here ! -->

    </div>

</transition>

在我们的示例中,我们附加了两个对应于过渡生命周期中的两个事件方法:v-on:enterv-on:leave。将这些方法添加到 Vue 实例中,让 Velocity.js 来淡入淡出我们的弹窗。

methods: {

  modalEnter: function(el, done) {

    Velocity(el, 'fadeIn', { duration: 300, complete: done, display: 'flex' })

  },

  modalLeave: function(el, done) {

    Velocity(el, 'fadeOut', { duration: 300, complete: done })

  }

}

如上所述,当包含的元素被有条件地设置为显示时,过渡动效将触发。因此,在我们的过渡组件的内部div上,我们添加了一个v-if声明,其值为一个布尔的modalShowing,让我们及时更新我们的实例的数据模型。

data: {

  modalShowing: false

}

现在,当我们要显示弹窗时,我们所要做的就是将布尔值设置为true

<button @click="showModal">Compose Tweet</button>

并写一个函数来改变布尔值。

hideModal: function() {

  this.modalShowing = false;

},

showModal: function() {

  this.modalShowing = true;

},

这里用了一些 CSS 奇技淫巧,我们还将一个点击事件处理函数绑定到页面背景,因此用户可以隐藏弹窗。厉害吧!

<div

    @click="hideModal" class="backdrop">

</div>

总结

我希望以上过程不是太痛苦(并且你一路上也学到了一些东西)。 我们只接触了一下 Vue 的冰山一角,但是这些概念对于解锁 Vue 大师级成就至关重要。

我承认,将 Vue 与 jQuery 进行比较是不公平的,因为它们是不同时代的产品,有各不相同的用例。 然而,对于那些通过 jQuery 学习 DOM 操作和事件处理的你来说,我希望这些概念能够让你耳目一新,你可以将其应用于你之后的工作中。


奇舞周刊

——————————————————

领略前端技术 阅读奇舞周刊


长按二维码,关注奇舞周刊


以上是关于JQuery 重度用户学习 Vue.js 的指南的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js入门指南

Vue.js新手入门指南

Vue2.0基础学习--- 一个简单的实例学习

Vue.js 简介与入门指南

vue2.0仿今日头条开源项目

用vscode开发vue应用[转]