比如这样的一个页面,里面有很多点击事件、对dom动态操作,我将js用对象封装,但发现越写越乱,有些功能和事件揉和在一起,当要修改维护时,修改的地方出现几处。请问怎么组织好?
var public = {
init: function() {
this.showEdit();
this.showSubnav();
this.musicHighLight();
this.preview();
},
//编辑菜单切换
showEdit: function() {
var $panel = $(".m-panel li");
$panel.click(function() {
$panel.removeClass("active noborder");
$(this).addClass("active noborder").prev().addClass("noborder");
var tempClass = $(this).data("tempclass");
$("." + tempClass).fadeIn().siblings().fadeOut();
});
},
//主导航条
showSubnav: function() {
var $mainNav = $(".mainnav");
var $mainLi = $mainNav.children("li");
var $subNav = $mainNav.find(".subnav");
var $subLi = $subNav.children("li");
var $bgMusic = $(".g-bgmusic");
$mainLi.on("click", function() {
$(this).siblings().removeClass("active");
$(this).toggleClass("active");
var index = $(this).index();
//高亮导航,显示隐藏模块
if(index === 1) {
$bgMusic.slideUp();
if($bgMusic.css("display") == "block") {
$subNav.stop().delay(1000).slideToggle();
} else {
$subNav.stop().toggle();
}
} else if(index === 2) {
$(this).addClass("active");
//复制当前页
$(".page").each(function() {
if($(this).hasClass("active")) {
if($(this).index() !== $(".page").length - 1) {
$(this).nextAll().each(function(index, value) {
$(value).find(".wrap-num").get(0).innerHTML = parseInt($(value).find(".wrap-num").get(0).innerHTML) + 1;
})
}
var num = $(this).find(".wrap-num").html();
$(this).after($(this).clone(true)).removeClass("active");
$(this).next().find(".wrap-num").html(++num);
}
})
} else if(index === 3) {
$subNav.slideUp();
if($subNav.css("display") == "block") {
$bgMusic.stop().delay(400).slideToggle();
} else {
$bgMusic.stop().slideToggle();
}
} else {
$subNav.slideUp();
$bgMusic.slideUp();
}
});
//点击提交按钮
$(".wrap-submit").find("a").click(function() {
$(".g-submit").css("height", $("body").height());
$(".g-submit").fadeToggle();
$(".g-submit").not(".m-submit").click(function() {
$(".g-submit").fadeOut();
})
$(".m-submit").click(function(event) {
event.stopPropagation();
})
})
//10个模板点击事件
$subLi.on("click", function() {
//切换模板
var temp = $(this).data("tempclass")
$("." + temp).fadeIn().siblings().fadeOut();
$subLi.removeClass("active");
$(this).addClass("active");
});
},
musicHighLight: function() {
//歌曲种类高亮
$(".m-bgmusic").find(".subnav").find("li").click(function() {
$(this).addClass("active").siblings().removeClass("active");
})
//选择歌曲高亮
$(".bgmusic li").click(function() {
if($(this).index() == 0) {
$(".bgmusic li").removeClass("active")
} else {
$(this).addClass("active").siblings().removeClass("active");
}
})
},
//预览区
preview: function() {
//预览区自适应高度
var height = $(window).height() - $(".g-header").height() - 52;
$(".m-preview").css("height", height);
//高亮
$(".m-preview").find(".page").find("img").click(function() {
$(this).parent().parent().addClass("active").siblings().removeClass("active");
})
//删除模板
$(".m-preview").find(".btn-delete").click(function() {
var $activeView = $(this).parent().parent()
var index = $activeView.index();
if(index == $(".m-preview").find(".page").length - 1) {
$activeView.prev().addClass("active")
} else {
$activeView.next().addClass("active");
$activeView.nextAll().each(function(index, value) {
$(value).find(".wrap-num").get(0).innerHTML = parseInt($(value).find(".wrap-num").get(0).innerHTML) - 1;
})
}
$(this).parent().parent().fadeOut().remove();
})
},
}
public.init();
//颜色色板模块
var color = {
init: function() {
this.initColorBar();
this.render();
},
initColorBar: function() {
var color = ["fff", "000", "595959", "f14646", "e95731", "f6bb43", "8cc051", "3baeda", "36bc9b", "3baeda", "967bdc", "f22874", "abda3b", "7bdcab", "6a37ee", "3bda5d", "36bc9b", "40535a", "503b87", "7cd0f0", "da3bb3"];
$.each(color.reverse(), function(index, value) {
var $li = $("<li></li>");
$li.css({
"background-color": "#" + value,
}).prependTo(".square ul")
});
},
render: function() {
$(".wrap-color").each(function() {
var self = this;
var $square = $(self).find(".square");
var $squareLi = $square.find("li");
var $coloroption = $(self).find(".coloroption");
//初始化透明度
$(self).find("#opacity")[0].value = 0;
$(self).find("#transparency").html("0%");
//初始化颜色值
$(self).find(".red")[0].value = 255;
$(self).find(".green")[0].value = 255;
$(self).find(".blue")[0].value = 255;
//初始化所选颜色
$(self).find(".bgcolorbar").css("background-color", "#fff");
$squareLi.click(function() {
//获取颜色
var color = $(this).css("backgroundColor");
var opacity = Math.round((100 - $(self).find("#opacity")[0].value) / 10) / 10;
var rgba = color.slice(0, 3) + "a" + color.slice(3, -1) + ", " + opacity + ")"
var rgb = rgba.replace(/[rgba()\s]/g, '').split(",");
//设置滑块位置
$(self).find(".red")[0].value = rgb[0];
$(self).find(".green")[0].value = rgb[1];
$(self).find(".blue")[0].value = rgb[2];
//设置长条颜色
$(this).addClass("active").siblings().removeClass("active");
$(self).find(".coloroption").each(function() {
if($(this).hasClass("active")) {
$(this).next().css("background-color", color);
return;
}
})
})
//背景色、文字色、高亮色选项
$coloroption.click(function() {
$coloroption.removeClass("active");
$(this).addClass("active");
})
//滑块滑动变色
$(self).find("input[type=range]").change(function() {
//获取变化后颜色
var red = $(self).find(".red")[0].value;
var green = $(self).find(".green")[0].value;
var blue = $(self).find(".blue")[0].value;
var transparency = $(self).find("#opacity")[0].value;
var opacity = Math.round((100 - transparency) / 10) / 10;
var rgba = "rgba(" + red + "," + green + "," + blue + "," + opacity + ")";
//设置颜色和值
$(self).find("#transparency").html(transparency + "%")
$(self).find(".coloroption").each(function() {
if($(this).hasClass("active")) {
$(this).next().css("background-color", rgba);
return;
}
})
})
//输入色值
$(self).find("#color").change(function() {
var color = $(this).val();
$(self).find(".coloroption").each(function() {
if($(this).hasClass("active")) {
$(this).next().css("background-color", color);
return;
}
})
$(document).keypress(function(e) {
// 回车键事件
if(e.which == 13) {
$(self).find(".coloroption").each(function() {
if($(this).hasClass("active")) {
$(this).next().css("background-color", color);
return;
}
})
}
});
})
});
}
}
color.init();
//上传
var upload = {
init: function() {
this.render();
},
render: function() {
var self = this;
$(".btn-imgupload").find("input").each(function(index, ele) {
var imgview = $(".imgview").eq(index).get(0);
$(ele).change(function(e) {
self.uploadImg(e.target, imgview);
})
})
},
//上传图片
uploadImg: function(inputEle, imgDom) {
if(inputEle.files && inputEle.files[0]) {
if(inputEle.files[0].type.match(/^image/) == null) {
alert("请选择图片文件")
} else {
var reader = new FileReader();
reader.onload = function(e) {
$(imgDom).attr('src', e.target.result);
}
reader.readAsDataURL(inputEle.files[0]);
}
}
},
//图片裁剪
imgClip: function() {
},
//上传语音
uploadAudio: function() {
},
}
upload.init();
var time = {
init: function() {
this.render();
},
render: function() {
//切换纯文字和时间点
var $inputEle = $("input[name='font']");
var nowTemp = "";
var targetTemp = "";
$.each($inputEle, function(index, ele) {
if($(ele).prop("checked") == true) {
nowTemp = $(ele).data("tempclass");
return;
}
});
$inputEle.change(function() {
$inputEle.removeAttr("checked");
$(this).prop("checked", "true").attr("checked", "true");
targetTemp = $(this).data("tempclass");
$('.' + nowTemp).fadeOut();
$('.' + targetTemp).fadeIn();
})
//编辑 备注切换
$(".temp-timelinefont .btn-edit").click(function() {
var html = $(this).html();
if(html === "编辑") {
$(this).html("备注");
$(this).parent().addClass("active");
}
if(html === "备注") {
alert("待制作的备注添加框")
}
return false;
})
//删除一个时间点
if($(".temp-timelinefont .btn-delete")) {
$(".temp-timelinefont .btn-delete").click(function() {
$(this).parent().remove();
})
}
},
}
time.init();
高洛峰2017-04-11 11:41:51
谢邀,好问题
我的看法是:组件化、语义化
你现在所有的功能都由一个公共对象管理,当然显得凌乱了。然而事实上只要仔细分析,你会发现一个页面可以拆分成若干个毫不相干或是低耦合的模块。把不同的模块用类封装起来:对内 自行管理自身状态,自行进行事件绑定等操作;对外暴露一个简单的接口,用于传递数据等。
第二点是语义化,方法是拆分函数。好的代码应该是不怎么需要注释的,因为代码必须可以自解释。保证只将一个简单完整逻辑作为一个函数。一个好的函数应该控制在 5 ~ 10 条语句——当然视具体情况而定。太长的函数有大可能会有嵌套的子逻辑。给函数取一个合理的名字并置换到原来冗长代码的地方,代码会更有条理。拆分函数还有另一个好处是:可以复用代码,这可以解决“牵一发而动全身”的问题。
一点小建议
PHP中文网2017-04-11 11:41:51
兄弟,你和我有一样的困扰。目前我是这么解决的,个人能力问题,我只把自己的方案写出来不一定是最佳方案。
你这里的showsubnav方法名很奇怪,并不是显示子菜单,而是绑定子菜单的事件。名字应该改成bindSubnav比较贴切。
还有就是你的这个方法代码太多,可以做成子菜单类SubNav然后
sub=new SubNav();
sub.bindEvent();
还有你里面有太多if else,可以用自定义事件emit出来,在外面用合适的对象去捕获它,做到指责单一,而且这样每个方法看起来都很短,很赞( •̀∀•́ )
ringa_lee2017-04-11 11:41:51
谢邀。
感觉题主现在有点执着于表面化的对象和this了,其实可以试试把功能拆分出来。
个人见解,最开始不必一定要用一个公共的对象把所有的功能包含进去。
其实只要足够细致就可以了。这里有个不错的类似问题:
https://segmentfault.com/q/1010000000633373