每个 knockoutjs 模板有一个单独的 VM class 违反了 OOP?
Having a separate VM class per knockoutjs template violates OOP?
我已经多次看到网页的特定区域有多个模板,根据场景加载其中一个模板。通常,相应的 VM 在该点实例化并绑定到模板。
这种设计模式是否不违反 OOP 原则,因为对象(在本例中为 VM)应该基于实际存在的功能实体,而不一定基于 UI 的特定区域。
让我用一个例子来证实这一点。假设我们有一个网页处理衣服、鞋子和家具的在线销售。一旦 selection 在页面的特定部分中的三个中创建,一个单独的模板将加载到页面的另一部分,这取决于 selection 所做的。根据 OOP 规则,我的对象模型应该是 ItemVM<-ShoeVM,ClothesVM,FurntitureVM,还是应该是包含 ItemSelectorVM(对于 UI 到 select 项目类型)、shoeAdverisementVM(绑定到结果加载了鞋子模板)、FurnitureAdvertisementVM 以及页面每个部分的更多 VM?
当你说 OOP 原则时,我假设你指的是 SOLID。
View Models 为 UI 建模,不必耦合到单个模板。您可以将视图模型与已创建的目标桌面模板一起使用,然后将视图模型与已创建的目标移动设备模板一起使用。
Should my object model be ItemVM<-ShoeVM,ClothesVM,FurntitureVM as per
OOP rules, or should it be ParentVM containing ItemSelectorVM (for the
UI to select the item type), shoeAdverisementVM (to bind to the shoe
template loaded as a result), FurnitureAdvertisementVM and many more
VMs for every part of the page?
这取决于应用程序和域的复杂性。
让我们假设您的 UI 不只是迭代 ObservableArray<T>
,其中 T
可能是 Shoe
或 Furniture
类型。我们还假设 ShoeAdvertisementVM
不是 ItemVM<T>
的 decorator。
现在,假设您有 FurnitureAdvertisementVM
和 ShoeAdverisementVM
,如下所示:
function FurnitureAdvertisementVM(furniture){
this.items = ko.observableArray(furniture);
this.doSomething = function(){
// doing something
}
}
function ShoeAdverisementVM(shoes){
this.items = ko.observableArray(shoes);
this.doSomething = function(){
// doing something
}
}
var shoeVM = new ShoeAdverisementVM(shoes);
var furnitureVM = new FurnitureAdverisementVM(furniture);
如果这两个视图模型几乎是一个复制和粘贴工作,唯一的区别是视图模型的名称和进入集合的项目的类型,那么可能值得将实现更改为通用的东西像这样:
function ItemsVM(items){
this.items = ko.observableArray(items);
this.doSomething = function(){
// doing something
}
}
var shoeVM = new ItemsM(shoes);
var furnitureVM = new ItemsVM(furniture);
但是如果每个视图模型都有一些非常具体的属性和功能,例如:
function FurnitureAdvertisementVM(furniture, someOtherDependency){
this.items = ko.observableArray(furniture);
this.doSomething = function(){
// doing something
}
this.propertyIsBoundToATextbox = ko.observable();
this.clickHandlerUsesDependency = function(ctx){
if(ctx.SomeCondition){
someOtherDependency.doSomething();
}
}
}
function ShoeAdverisementVM(shoes){
this.items = ko.observableArray(shoes);
this.doSomething = function(){
// doing something
}
this.propertyIsBoundToACheckbox = ko.observable();
}
然后它不像使两个视图模型通用那样清晰。
Roy J 评论:
your viewmodels are intended to model the view (the UI)
这是真的,所以如果视图有不同的要求,即一个有 3 个复选框,另一个有大量按钮等,那么您可能需要不同的视图模型。
如果您想将一些常用功能分解为单独的 类,那么您可以:
function ItemService(items){
this.items = ko.observableArray(items);
this.doSomething = function(){
// doing something
}
}
function FurnitureAdvertisementVM(itemService, someOtherDependency){
this.service = itemService;
this.propertyIsBoundToATextbox = ko.observable();
this.clickHandlerUsesDependency = function(ctx){
if(ctx.SomeCondition){
someOtherDependency.doSomething();
}
}
}
function ShoeAdverisementVM(itemService){
this.service = itemService;
this.propertyIsBoundToACheckbox = ko.observable();
}
我已经多次看到网页的特定区域有多个模板,根据场景加载其中一个模板。通常,相应的 VM 在该点实例化并绑定到模板。
这种设计模式是否不违反 OOP 原则,因为对象(在本例中为 VM)应该基于实际存在的功能实体,而不一定基于 UI 的特定区域。
让我用一个例子来证实这一点。假设我们有一个网页处理衣服、鞋子和家具的在线销售。一旦 selection 在页面的特定部分中的三个中创建,一个单独的模板将加载到页面的另一部分,这取决于 selection 所做的。根据 OOP 规则,我的对象模型应该是 ItemVM<-ShoeVM,ClothesVM,FurntitureVM,还是应该是包含 ItemSelectorVM(对于 UI 到 select 项目类型)、shoeAdverisementVM(绑定到结果加载了鞋子模板)、FurnitureAdvertisementVM 以及页面每个部分的更多 VM?
当你说 OOP 原则时,我假设你指的是 SOLID。
View Models 为 UI 建模,不必耦合到单个模板。您可以将视图模型与已创建的目标桌面模板一起使用,然后将视图模型与已创建的目标移动设备模板一起使用。
Should my object model be ItemVM<-ShoeVM,ClothesVM,FurntitureVM as per OOP rules, or should it be ParentVM containing ItemSelectorVM (for the UI to select the item type), shoeAdverisementVM (to bind to the shoe template loaded as a result), FurnitureAdvertisementVM and many more VMs for every part of the page?
这取决于应用程序和域的复杂性。
让我们假设您的 UI 不只是迭代 ObservableArray<T>
,其中 T
可能是 Shoe
或 Furniture
类型。我们还假设 ShoeAdvertisementVM
不是 ItemVM<T>
的 decorator。
现在,假设您有 FurnitureAdvertisementVM
和 ShoeAdverisementVM
,如下所示:
function FurnitureAdvertisementVM(furniture){
this.items = ko.observableArray(furniture);
this.doSomething = function(){
// doing something
}
}
function ShoeAdverisementVM(shoes){
this.items = ko.observableArray(shoes);
this.doSomething = function(){
// doing something
}
}
var shoeVM = new ShoeAdverisementVM(shoes);
var furnitureVM = new FurnitureAdverisementVM(furniture);
如果这两个视图模型几乎是一个复制和粘贴工作,唯一的区别是视图模型的名称和进入集合的项目的类型,那么可能值得将实现更改为通用的东西像这样:
function ItemsVM(items){
this.items = ko.observableArray(items);
this.doSomething = function(){
// doing something
}
}
var shoeVM = new ItemsM(shoes);
var furnitureVM = new ItemsVM(furniture);
但是如果每个视图模型都有一些非常具体的属性和功能,例如:
function FurnitureAdvertisementVM(furniture, someOtherDependency){
this.items = ko.observableArray(furniture);
this.doSomething = function(){
// doing something
}
this.propertyIsBoundToATextbox = ko.observable();
this.clickHandlerUsesDependency = function(ctx){
if(ctx.SomeCondition){
someOtherDependency.doSomething();
}
}
}
function ShoeAdverisementVM(shoes){
this.items = ko.observableArray(shoes);
this.doSomething = function(){
// doing something
}
this.propertyIsBoundToACheckbox = ko.observable();
}
然后它不像使两个视图模型通用那样清晰。
Roy J 评论:
your viewmodels are intended to model the view (the UI)
这是真的,所以如果视图有不同的要求,即一个有 3 个复选框,另一个有大量按钮等,那么您可能需要不同的视图模型。
如果您想将一些常用功能分解为单独的 类,那么您可以:
function ItemService(items){
this.items = ko.observableArray(items);
this.doSomething = function(){
// doing something
}
}
function FurnitureAdvertisementVM(itemService, someOtherDependency){
this.service = itemService;
this.propertyIsBoundToATextbox = ko.observable();
this.clickHandlerUsesDependency = function(ctx){
if(ctx.SomeCondition){
someOtherDependency.doSomething();
}
}
}
function ShoeAdverisementVM(itemService){
this.service = itemService;
this.propertyIsBoundToACheckbox = ko.observable();
}