jQuery === 面条式代码?

幸运
185
文章
0
评论
三月 12, 202012:17:31 评论 104 5558字阅读18分31秒

自打React/Vue等架构时兴以后,jquery挨打到了鲜面条式编码的标识,乃至变成“老鼠过街”,仿佛谁还要用jquery,谁就还沉迷在旧社会,许多人兴高采烈地相拥新架构,各大博客网站有很大一部分的博客都在介绍新的框架,争当时代的“弄潮儿”。新框架带来的新的理念,新的开发方式不可否认带来了生产效率,但是jquery等就应该被打上“旧时代”面条式代码的标签么?

我们从一篇文章说起:《React.js 的介绍 – 针对了解 jQuery 的工程师(译)》,英文原文是这个《React.js Introduction For People Who Know Just Enough jQuery To Get By》, 这篇文章我好久前就看过,现在再把它翻出来,里面对比了下jQuery和React分别实现一个发推的功能,作者用jQuery写着写着代码就乱套了,而用React不管需求多复杂,代码条理依旧很清晰。

我们一步步按照原文作者的思路来拆解。

(1)输入个数为0时,发送按钮不可点击

如下图所示,当输入框没有内容时,发推按钮置灰不可点,有内容点才能点。

jQuery === 面条式代码?

作者写的代码是这样的:

// 初始化状态

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

// 文本框的值发生变化时

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

// 只要超过一个字符,就

if ($(this).val().length > 0) {

// 按钮可以点击

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

} else {

//否则,按钮不能点击

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

}

});

这个代码本身写得很累赘,首先,既然一开始那个button是disabled的,那就直接在html上写个disabled属性就行了:

<form class="tweet-box">

<textarea name="textMsg"></textarea>

<input disabled type="submit" name="tweet" value="Tweet">

</form>

第二个要控制按钮的状态,其实核心只要一行代码就行了,不需要写那么长:

let form = $(".tweet-box")[0];

$(form.textMsg).on("input", function() {

form.tweet.disabled = this.value.length <= 0;

}).trigger("input");

这个代码应该够简洁了吧,而且代码在jQuery和原生之间来回切换,游刃有余。

(2)实现剩余字数功能

如下图所示:

jQuery === 面条式代码?

这个也好实现:

let form = $(".tweet-box")[0],

$leftWordCount = $("#left-word-count");

$(form.textMsg).on("input", function() {

// 已有字数

let wordsCount = this.value.length;

$leftWordCount.text(140 - wordsCount);

form.tweet.disabled = wordsCount <= 0;

});

(3)添加图片按钮

如下图所示,左下角多了一个选择照片的按钮:

jQuery === 面条式代码?

如果用户选择了照片,那么可输入字数将会减少23个字符,并且Add Photo文案要变成Photo Added。我们先来看下作者是怎么实现的,如下代码:

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);

}

如果代码像作者这样写的话确实是比较乱,而且比较面条式。但是我们可以优雅地实现。首先,选择照片一般会写一个input[type=file]的隐藏输入框盖在上传图标下面:

<div class="upload-container">

<img src="upload-icon.png" alt>

<span id="add-photo">Add Photo</span>

<input type="file" name="photoUpload">

</div>

然后监听它的change事件,在change事件里面给form套一个类:

$(form.photoUpload).on("change", function() {

// 如果选择了照片则添加一个photo-added的类

this.value.length ? $(form).addClass("photo-added")

// 否则去掉

: $(form).removeClass("photo-added");

});

然后就可以来实现文案改变的需求了,把上面#add-photo的span标签添加两个data属性,分别是照片添加和未添加的文案,如下代码所示:

<span id="add-photo" data-added-text="Photo Added"

data-notadded-text="Add Photo"></span>

通过form的类结合before/after伪类控制html上的文案,如下代码所示:

#add-photo:before {

content: attr(data-empty-text);

}

form.photo-added #add-photo:before {

content: attr("data-added-text);

}

这样就可以了,我们算是用了一个比较优雅的方式实现了一个文案变化的功能,其中css的attr可以兼容到IE9,并且这里html/css/js相配合,共同完成这个变化的功能,这应该也挺好玩的。

剩下一个要减掉23字符的需求,只需要在减掉的时候判断一下:

$(form.textMsg).on("input", function() {

// 已有字数

let wordsCount = this.value.length;

form.tweet.disabled = wordsCount <= 0;

$leftWordCount.text(140 - wordsCount -

//如果已经添加了图片再减掉23个字符

($(form).hasClass("photo-added") ? 23 : 0));

});

然后在选择图片之后trigger一下,让文字发生变化,如下代码倒数第二行:

/*

* @trigger 会触发文字输入框的input事件以更新剩余字数

*/

$(form.photoUpload).on("change", function() {

// 如果选择了照片则添加一个photo-added的类

this.value.length ? $(form).addClass("photo-added") :

// 否则去掉

$(form).removeClass("photo-added");

$(form.textMsg).trigger("input");

});

这里又使用了事件的机制,用reac应该基本上都是用状态state控制了。

再来看最后一个功能。

(4)没有文字但是有照片发推按钮要可点

上面是只要没有文字,那么发推按钮不可点,现在要求有图片就可点。这个也好办,因为如果有图片的话,form已经有了一个类,所以只要再加一个判断就可以了:

$(form.textMsg).on("input", function() {

// 已有字数

let wordsCount = this.value.length;

form.tweet.disabled = wordsCount <= 0

//disabled再添加一个与判断

&& !$(form).hasClass("photo-added");

$leftWordCount.text(140 - wordsCount -

//如果已经添加了图片再减掉23个字符

($(form).hasClass("photo-added") ? 23 : 0));

});

最后看一下,汇总的JS代码,加上空行和注释总共只有23行:

let form = $(".tweet-box")[0],

$leftWordCount = $("#left-word-count");

$(form.textMsg).on("input", function() {

// 已有字数

let wordsCount = this.value.length;

form.tweet.disabled = wordsCount <= 0

//disabled再添加一个与判断

&& !$(form).hasClass("photo-added");

$leftWordCount.text(140 - wordsCount -

//如果已经添加了图片再减掉23个字符

($(form).hasClass("photo-added") ? 23 : 0));

});

/*

* @trigger 会触发文字输入框的input事件以更新剩余字数

*/

$(form.photoUpload).on("change", function() {

// 如果选择了照片则添加一个photo-added的类

this.value.length ? $(form).addClass("photo-added") :

// 否则去掉

$(form).removeClass("photo-added");

$(form.textMsg).trigger("input");

});

html大概有10行,还有6行核心CSS,不过这两个比较易读。再来看一下React的完整版本,作者的实现:

var TweetBox = React.createClass({

getInitialState: function() {

return {

text: "",

photoAdded: false

};

},

handleChange: function(event) {

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

},

togglePhoto: function(event) {

this.setState({ photoAdded: !this.state.photoAdded });

},

remainingCharacters: function() {

if (this.state.photoAdded) {

return 140 - 23 - this.state.text.length;

} else {

return 140 - this.state.text.length;

}

},

render: function() {

return (

<div className="well clearfix">

<textarea className="form-control"

onChange={this.handleChange}></textarea>

<br/>

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

<button className="btn btn-primary pull-right"

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

<button className="btn btn-default pull-right"

onClick={this.togglePhoto}>

{this.state.photoAdded ? "✓ Photo Added" : "Add Photo" }

</button>

</div>

);

}

});

React.render(

<TweetBox />,

document.body

);

React的套路是监听事件然后改变state,在jsx的模板里,使用这些state展示,而jQuery的套路是监听事件,然后自己去控制DOM展示。React帮你操作DOM,jQuery要自己去操作DOM,前者提供了便利但同时也失去了灵活性,后者增加了灵活性但同时增加了复杂度。

使用jQuery不少人容易写出面条式的代码,但是写代码的风格我觉得和框架没关系,关键还在于你的编码素质,就像你用了React写class,你就可以说你就是面向对象了?不见得,我在《JS与面向对象》这篇文章提到,写class并不代表你就是面向对象,面向对象是一种思想而不是你代码的组织形式。一旦你离开了React的框架,是不是又要回到面条式代码的风格了?如果是的话那就说明你并没有没有掌握面向对象的思想。不过,React等框架能够方便地组件化,这点是不可否认的。

还有一个需要注意的是,框架会帮你屏蔽掉很多原生的细节,让你专心于业务逻辑,但往往也让你丧失了原生的能力不管是html还是js,而这才是最重要的功底。例如说对于事件,由于所有的事件都是直接绑在目标元素,然后通过state或者其它第三方的框架进行传递,这样其实就没什么事件的概念了。所以需要警惕使用了框架但是丧失了基本的前端能力,再如ajax分页改变url,或者说单页面路由的实现方式,还有前后退的控制,基本上能够完整回答地比较少。很多人都会用框架做页面,但是不懂JS.

本文来源于:jQuery === 面条式代码?-幸运草博客
特别声明:以上文章内容仅代表作者本人观点,不代表幸运草博客观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与幸运草联系。

  • 本站QQ群
  • weinxin
  • 捐赠本站
  • weinxin
jquery中cookie用法介绍 jQuery

jquery中cookie用法介绍

cookie在jquery中有指定的cookie操作类,下面我先来介绍我们在使用cookie操作类时的一些问题,然后介绍正确的使用方法。 使用JQuery操作cookie时 发生取的值不正确的问题: ...
jQuery事件:bind、delegate、on的区别 jQuery

jQuery事件:bind、delegate、on的区别

「内容简介」本文详解各种jQuery事件绑定方法:on,bind,delegate,live,unbind,trigger。 同时总结一下常用的jQuery事件技术:如何阻止事件冒泡、阻止浏览器默认行...
jQuery入门讲解-jQuery样式操作 jQuery

jQuery入门讲解-jQuery样式操作

css 操作 通过css()的方法设置或者获取样式,无论样式属性是从外部导入的,还是直接写在HTML标签里面的,css()方法都可以获取到。。 1、设置单个样式: 2、设置多个样式: 操作多个样式的时...
Jquery Notes jQuery

Jquery Notes

1.什么是jQuery 2.如何使用jQuery 3.查找元素 1.什么是jQuery jQuery是第三方开发的执行DOM操作的极简化的函数库 第三方:下载 执行DOM操作:jQuery还是执行DO...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: