Thế nào là MVC Framework ? Điểm khác biệt của nó so với React
Bài đăng này đã không được cập nhật trong 9 năm
MVC Framework
MVC Framework trong javascript là một framework cho JS sử dụng mô hình MVC. Vậy mô hình MVC là gì
Như bạn đã biết, tên của mô hình MVC được dựa trên từng thành phần chính của nó: Model: chứa các model của dữ liệu ứng dụng, View sẽ render Model cho một đại diện thích hợp, và Controller sẽ cập nhật cho Model
Chúng ta định nghĩa kiến trúc đặc trưng của mô hình MVC như sau
- Model: Các đại diện cụ thể của các thông tin mà trên đó các ứng dụng hoạt động. Nó sẽ định nghĩa thêm ý nghĩa cho các dữ liệu thô (ví dụ như tính toán nếu ngày hôm nay là sinh nhật của user, hoặc tính toán t, phí shipping của một đơn hàng vv...)
- View: Render các model thành một hình thức thích hợp cho sự tương tác, thường là một yếu tố giao diện người dùng. MVC là thường thấy trong các ứng dụng web, nơi mà view là các trang HTML và code sẽ đưa các dữ liệu động cho trang
- Controller: Xử lý và đáp ứng các sự kiện, như là các hành động của users, gọi những thay đổi của model và view
Trên đây là những lý thuyết tôi cóp nhặt từ trên mạng, bạn chả hiểu gì đúng không.
Bây giờ chúng ta sẽ thử áp dụng mô hình MVC trong khi phát triển một component của JS
Chúng ta có một List box HTML (select tag) có thể chỉnh sửa danh sách các item. Người sử dụng có thể lựa chọn, loại bỏ và thêm các mục mới vào danh sách
Model của dữ liệu sẽ như sau: là một mảng các item, có thể chọn và xóa
function ListModel(items) {
this._items = items;
this._selectedIndex = -1;
// Các item sẽ có event thêm/xóa và selected
this.itemAdded = new Event(this);
this.itemRemoved = new Event(this);
this.selectedIndexChanged = new Event(this);
}
//Định nghĩa các function của model
ListModel.prototype = {
getItems : function () {
return [].concat(this._items);
},
addItem : function (item) {
this._items.push(item);
this.itemAdded.notify({ item : item });
},
removeItemAt : function (index) {
var item;
item = this._items[index];
this._items.splice(index, 1);
this.itemRemoved.notify({ item : item });
if (index === this._selectedIndex) {
this.setSelectedIndex(-1);
}
},
getSelectedIndex : function () {
return this._selectedIndex;
},
setSelectedIndex : function (index) {
var previousIndex;
previousIndex = this._selectedIndex;
this._selectedIndex = index;
this.selectedIndexChanged.notify({ previous : previousIndex });
}
};
Event là một class để quan sát việc thay đổi danh sách items
function Event(sender) {
this._sender = sender;
this._listeners = [];
}
Event.prototype = {
attach : function (listener) {
this._listeners.push(listener);
},
notify : function (args) {
var index;
for (index = 0; index < this._listeners.length; index += 1) {
this._listeners[index](this._sender, args);
}
}
};
Class của View cần định nghĩa dạng tương tác với form. Chúng ta sẽ làm một list item (select tag), bên cạnh có 2 nút "+" và "-" để điều khiển việc thêm (xóa) item
View Class:
function ListView(model, elements) {
this._model = model;
this._elements = elements;
this.listModified = new Event(this);
this.addButtonClicked = new Event(this);
this.delButtonClicked = new Event(this);
var _this = this;
// Gắn sự kiện vào model
this._model.itemAdded.attach(function () {
_this.rebuildList();
});
this._model.itemRemoved.attach(function () {
_this.rebuildList();
});
// Gắn listeners vào HTML control
this._elements.list.change(function (e) {
_this.listModified.notify({ index : e.target.selectedIndex });
});
this._elements.addButton.click(function () {
_this.addButtonClicked.notify();
});
this._elements.delButton.click(function () {
_this.delButtonClicked.notify();
});
}
ListView.prototype = {
show : function () {
this.rebuildList();
},
rebuildList : function () {
var list, items, key;
list = this._elements.list;
list.html('');
items = this._model.getItems();
for (key in items) {
if (items.hasOwnProperty(key)) {
list.append($('<option>' + items[key] + '</option>'));
}
}
this._model.setSelectedIndex(-1);
}
};
Controller sẽ thực hiện việc thêm/xóa và cập nhật danh sách. Chúng ta cũng sẽ có 3 function tương ứng
function ListController(model, view) {
this._model = model;
this._view = view;
var _this = this;
this._view.listModified.attach(function (sender, args) {
// thực hiện việc cập nhật list items
_this.updateSelected(args.index);
});
this._view.addButtonClicked.attach(function () {
// thực hiện việc thêm item
_this.addItem();
});
this._view.delButtonClicked.attach(function () {
// xóa item
_this.delItem();
});
}
ListController.prototype = {
addItem : function () {
var item = window.prompt('Add item:', '');
if (item) {
this._model.addItem(item);
}
},
delItem : function () {
var index;
index = this._model.getSelectedIndex();
if (index !== -1) {
this._model.removeItemAt(this._model.getSelectedIndex());
}
},
updateSelected : function (index) {
this._model.setSelectedIndex(index);
}
};
Vậy là chúng ta đã xây dựng xong 3 thành phần của MVC. Dĩ nhiên chúng phải được kết hợp với nhau để code hoàn chỉnh
- Khởi tạo giá trị ban đầu cho Model
- Tạo View
- Tạo Controller
$(function () {
var model = new ListModel(['Ruby', 'JavaScript']),
view = new ListView(model, {
'list' : $('#list'),
'addButton' : $('#plusBtn'),
'delButton' : $('#minusBtn')
}),
controller = new ListController(model, view);
view.show();
});
Việc còn lại chỉ là tạo HTML page
<select id="list" size="10"></select>
<button id="plusBtn"> + </button>
<button id="minusBtn"> - </button>
Trên đây chúng ta đã thử làm JS với mô hình MVC, trên thực tế có rất nhiều các Framework hỗ trợ chúng ta làm những việc trên đây như
- AngularJS
- EmberJS
- MeteorJS
- BackboneJS
- KnockOutJS
Điểm khác biệt của MVC Framework và React
Như tôi đã trình bày, các MVC Framework cung cấp cả 3 phần của mô hình MVC: Model-View-Controller.
Còn React chỉ là một thư viện phát triển UI của Facebook để tạo ra các components tương tác, bạn có thể coi nó cung cấp phần "V" trong mô hình MVC
Như vậy bạn có thể sử dụng React bên trong các MVC framework một cách thoải mái. Ví dụ bạn có thể dùng React như các Directive bên trong AngularJS, Components trong Ember ...
Sau đây chúng ta thử dùng React để làm lại Demo bên trên
Chúng ta chỉ phải tạo class SelectBox, nó được khởi tạo các giá trị ban đầu, có 3 function là "thêm", "xóa" item và render lại view
var SelectBox = React.createClass({
getInitialState: function() {
return {
Options: [
{
value: "",
text: "Ruby"
},
{
value: "",
text: "JavaScript"
}
]
};
},
_onClickAddButtonHandler: function() {
var itemName = prompt("Enter item name", ""),
Options = this.state.Options;
if (itemName.trim()) {
Options.push({value: '', text: itemName});
this.setState({
Options: Options
});
}
},
_onClickRemoveButtonHandler: function() {
var selectedIndex = this.refs.select_box.getDOMNode().selectedIndex,
Options = this.state.Options;
if (selectedIndex >= 0) {
Options.splice(selectedIndex, 1);
this.setState({
Options: Options
});
}
},
render: function() {
var Options = this.state.Options;
var OptionElements = Options.map(function(item, idx) {
return (
<option value={item.value}>{item.text}</option>
);
});
return (
<div>
<select size="20" ref="select_box">
{OptionElements}
</select>
<button onClick={this._onClickAddButtonHandler}>+</button>
<button onClick={this._onClickRemoveButtonHandler}>-</button>
</div>
);
}
});
Và việc cuối cùng chỉ cần làm là render cái SelectBox đó ra view
React.render(<SelectBox />, document.body);
Rất gọn gàng và đơn giản phải không nào.
Còn bạn đã biết AngularJS, bạn hãy thử kết hợp nó và React xem sao
All rights reserved