(点选下方社会公众号,可加速高度关注)
fed.renren.com/2017/09/03/jquery-not-noodle-code/
好景不长React/Vue等架构盛行后,jQuery被打上了饺子式标识符的条码,即使成了“傻子”,好似谁还在用jQuery,谁就还活在博戈达,许多人都兴高采烈地亲吻新架构,数十家网志中文网站有非常大一小部分的网志都在如是说捷伊架构,争做黄金时代的“先行者”。新架构增添的捷伊经营理念,捷伊Attichy不容否认增添了制造工作效率,但jQuery等就如果被打上“博戈达”饺子式标识符的条码么?
他们从一则该文讲起:《React.js 的如是说 – 特别针对介绍 jQuery 的技师(译)》,英语书名是那个《React.js Introduction For People Who Know Just Enough jQuery To Get By》, 这篇该文我很久前就看完,那时再把它挑出来,里头对照了下jQuery和React依次同时实现两个罗亚尼的机能,译者用jQuery写着写着标识符就述补了,而用React无论市场需求多繁杂,标识符章法依然很明晰。
我们一点一点依照书名译者的路子来回收。
(1)输出特征值为0时,推送按键不容点选
如下表所示图右图,当快捷方式没文本时,罗亚尼按键置灰不容点,有文本点就可以点。
译者写的标识符是这种的:
// 调用状况
$(“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”>
<textareaname=“textMsg”></textarea>
<input disabledtype=“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)同时实现剩余字数机能
如下表所示图右图:
那个也好同时实现:
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)添加图片按键
如下表所示图右图,左下角多了两个选择照片的按键:
如果用户选择了照片,那么可输出字数将会减少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的完整版本,译者的同时实现:
varTweetBox = 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){
return140 – 23 – this.state.text.length;
}else{
return140 – 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.
觉得本文对你有帮助?请分享给更多人
高度关注「前端大全」,提升前端技能