Tôi sẽ điểm qua một số điều đơn giản có thể giúp bạn hoặc có thể không. Một số có thể rõ ràng, một số có thể cực kỳ phức tạp.
Bước 1: Chia nhỏ mã của bạn
Tách mã của bạn thành nhiều đơn vị mô-đun là bước đầu tiên rất tốt. Làm tròn những gì hoạt động "cùng nhau" và đặt chúng trong đơn vị nhỏ được bọc của riêng chúng. đừng lo lắng về định dạng ngay bây giờ, hãy giữ nó nội tuyến. Cấu trúc là một điểm sau.
Vì vậy, giả sử bạn có một trang như thế này:
Sẽ rất hợp lý khi phân chia ngăn để tất cả các trình xử lý / liên kết sự kiện liên quan đến tiêu đề đều ở trong đó, để dễ bảo trì (và không phải sàng lọc qua 1000 dòng).
Sau đó, bạn có thể sử dụng một công cụ như Grunt để xây dựng lại JS của bạn trở lại thành một đơn vị duy nhất.
Bước 1a: Quản lý sự phụ thuộc
Sử dụng thư viện như RequestJS hoặc CommonJS để triển khai một thứ gọi là AMD . Tải mô-đun không đồng bộ cho phép bạn trình bày rõ ràng mã của bạn phụ thuộc vào điều gì, sau đó cho phép bạn giảm tải việc gọi thư viện tới mã. Bạn chỉ có thể nói "Cái này cần jQuery" theo nghĩa đen và AMD sẽ tải nó và thực thi mã của bạn khi có jQuery .
Điều này cũng có một viên ngọc ẩn: việc tải thư viện sẽ được thực hiện vào lần thứ hai DOM đã sẵn sàng, không phải trước đó. Điều này không còn tạm dừng tải trang của bạn nữa!
Bước 2: Modularize
Xem khung dây? Tôi có hai đơn vị quảng cáo. Rất có thể họ sẽ có những người nghe sự kiện được chia sẻ.
Nhiệm vụ của bạn trong bước này là xác định các điểm lặp lại trong mã của bạn và cố gắng tổng hợp tất cả những điều này thành các mô-đun . Các mô-đun, ngay bây giờ, sẽ bao gồm mọi thứ. Chúng tôi sẽ chia nhỏ mọi thứ khi chúng tôi tiếp tục.
Toàn bộ ý tưởng của bước này là đi từ bước 1 và xóa tất cả các copy-pasta, để thay thế chúng bằng các đơn vị được ghép nối lỏng lẻo. Vì vậy, thay vì có:
ad_unit1.js
$("#au1").click(function() { ... });
ad_unit2.js
$("#au2").click(function() { ... });
Tôi sẽ có:
ad_unit.js
:
var AdUnit = function(elem) {
this.element = elem || new jQuery();
}
AdUnit.prototype.bindEvents = function() {
... Events go here
}
page.js
:
var AUs = new AdUnit($("#au1,#au2"));
AUs.bindEvents();
Điều này cho phép bạn phân chia giữa các sự kiện và đánh dấu của bạn ngoài việc loại bỏ sự lặp lại. Đây là một bước khá tốt và chúng tôi sẽ mở rộng thêm về sau.
Bước 3: Chọn một khuôn khổ!
Nếu bạn muốn mô-đun hóa và giảm số lần lặp lại hơn nữa, có một loạt các khuôn khổ tuyệt vời xung quanh việc triển khai các phương pháp tiếp cận MVC (Model - View - Controller). Tôi thích nhất là Backbone / Spine, tuy nhiên, cũng có Angular, Yii, ... Danh sách vẫn tiếp tục.
Một mẫu đại diện cho dữ liệu của bạn.
Một Xem đại diện mark-up của bạn và tất cả các sự kiện liên quan đến nó
Một điều khiển đại diện cho logic kinh doanh của bạn - nói cách khác, bộ điều khiển nói với trang gì xem để tải và những gì mô hình để sử dụng.
Đây sẽ là một bước học tập quan trọng, nhưng giải thưởng rất đáng giá: nó ủng hộ mã mô-đun sạch sẽ hơn mì spaghetti.
Có rất nhiều thứ khác bạn có thể làm, đó chỉ là những hướng dẫn và ý tưởng.
Các thay đổi dành riêng cho mã
Dưới đây là một số cải tiến cụ thể cho mã của bạn:
$('.new_layer').click(function(){
dialog("Create new layer","Enter your layer name","_input", {
'OK' : function(){
var reply = $('.dialog_input').val();
if( reply != null && reply != "" ){
var name = "ln_"+reply.split(' ').join('_');
var parent = "";
if(selected_folder != "" ){
parent = selected_folder+" .content";
}
$R.find(".layer").clone()
.addClass(name).html(reply)
.appendTo("#layer_groups "+parent);
$R.find(".layers_group").clone()
.addClass(name).appendTo('#canvas '+selected_folder);
}
}
});
});
Điều này được viết tốt hơn là:
$("body").on("click",".new_layer", function() {
dialog("Create new layer", "Enter your layer name", "_input", {
OK: function() {
// There must be a way to get the input from here using this, if it is a standard library. If you wrote your own, make the value retrievable using something other than a class selector (horrible performance + scoping +multiple instance issues)
// This is where the view comes into play. Instead of cloning, bind the rendering into a JS prototype, and instantiate it. It means that you only have to modify stuff in one place, you don't risk cloning events with it, and you can test your Layer stand-alone
var newLayer = new Layer();
newLayer
.setName(name)
.bindToGroup(parent);
}
});
});
Trước đó trong mã của bạn:
window.Layer = function() {
this.instance = $("<div>");
// Markup generated here
};
window.Layer.prototype = {
setName: function(newName) {
},
bindToGroup: function(parentNode) {
}
}
Đột nhiên, bạn có một cách để tạo một lớp tiêu chuẩn từ bất kỳ đâu trong mã của mình mà không cần sao chép dán. Bạn đang làm điều này ở năm nơi khác nhau. Tôi vừa lưu cho bạn năm bản sao chép.
Một lần nữa:
// Trình bao bọc bộ quy tắc cho các hành động
var PageElements = function(ruleSet) {
ruleSet = ruleSet || [];
this.rules = [];
for (var i = 0; i < ruleSet.length; i++) {
if (ruleSet[i].target && ruleSet[i].action) {
this.rules.push(ruleSet[i]);
}
}
}
PageElements.prototype.run = function(elem) {
for (var i = 0; i < this.rules.length; i++) {
this.rules[i].action.apply(elem.find(this.rules.target));
}
}
var GlobalRules = new PageElements([
{
"target": ".draggable",
"action": function() { this.draggable({
cancel: "div#scrolling, .content",
containment: "document"
});
}
},
{
"target" :".resizable",
"action": function() {
this.resizable({
handles: "all",
zIndex: 0,
containment: "document"
});
}
}
]);
GlobalRules.run($("body"));
// If you need to add elements later on, you can just call GlobalRules.run(yourNewElement);
Đây là một cách rất hiệu quả để đăng ký các quy tắc nếu bạn có các sự kiện không chuẩn hoặc các sự kiện tạo. Điều này cũng thực sự nghiêm túc khi được kết hợp với hệ thống thông báo pub / sub và khi bị ràng buộc với một sự kiện, bạn sẽ kích hoạt bất cứ khi nào bạn tạo các phần tử. Fire'n'forget sự kiện mô-đun ràng buộc!