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》这篇文章让我印象深刻。
只需一些基本的 JS 和 JQuery 的知识,通过重构推特网发推特的页面,上衫向我们展示了一个完整的 React 世界。
这篇文章,对我这类从实践中学习的人而言是很有帮助的。每当一个新的框架出来后,我都会用它重新把东西实现一遍。因此,我也仿照这篇文章,带你重温我最近学习 Vue 的过程。
我强烈建议在读我接下来写的内容之前,先读一下上衫写的那篇文章。因为他在文章中介绍了实现这些效果的 JQuery 代码,尽管其中的一些代码比较简单。所以我这里就不多说了,直接进入 Vue 的主题。
我们要做什么
推特很多人都用,下面这个界面大家都很熟悉。
这个界面是一个很好的例子,像我们展示了如何用 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-if,v-show,v-else等)来有条件地显示和隐藏内容。当传递给该指令的 JavaScript 表达式求值为 true 时,元素将被渲染,反之隐藏。
在我们的例子中,我们添加了一个v-if语句来用计算属性photoHasBeenUploaded来控制是否渲染图片。
photoHasBeenUploaded: function() {
return this.photo !== null;
}
当该函数返回值为真时(当data的photo键不等于null时)整个div被渲染。
而在div里面,我们渲染了两个元素:
1. 通过将data的photo键的内容传递给 Vue 的v-bind:src指令来加载图像
2. 一个删除按钮,其中利用了@click来处理点击事件,绑定了一个函数,通过将data的photo键的内容设置为null来「删除」照片
removePhoto: function() {
this.photo = null;
}
我们就快完成任务了。
步骤六:修正,用户可以上传多张「照片」
我们现在可以有效地处理一个用户上传一张照片到推特,但如果 Ta 想上传更多照片怎么办?
到目前为止,你应该考虑一下:「之前我们已经绑定了我们的事件处理函数,我想这里唯一重大的变化就是能够在textarea下有条件的显示出多个图像...」你想的很正确!我们来看看我们需要遵循的步骤:
1. 我们需要通过将data的photo键更改为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元素,我们现在将有N个figure元素对应于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-if或v-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:enter和v-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 的指南的主要内容,如果未能解决你的问题,请参考以下文章