Javascript 如何消除不同视图模型模块之间的代码重复?
我的JS被组织成viewmodels和services。这些服务主要与AJAX调用有关,而我的viewModels描述了它们在其中使用的视图 我现在有两个视图模型-StoreViewModel和MyStoreViewModel。在每一项中,我都有以下内容:Javascript 如何消除不同视图模型模块之间的代码重复?,javascript,mvvm,knockout.js,Javascript,Mvvm,Knockout.js,我的JS被组织成viewmodels和services。这些服务主要与AJAX调用有关,而我的viewModels描述了它们在其中使用的视图 我现在有两个视图模型-StoreViewModel和MyStoreViewModel。在每一项中,我都有以下内容: function MyStoreVm(model) { var self = this; self.doThis = function(){ // do stuff self.doThat(
function MyStoreVm(model) {
var self = this;
self.doThis = function(){
// do stuff
self.doThat();
};
}
然后:
我来自C#背景——通常我只会在这种情况下使用继承。我如何通过让它们从第三个共享模块继承来消除两个不同模块/视图模型之间的代码重复
更多详细信息:在MVC视图中使用了这些选项,根据存储是否为MyStore,我在MVC视图中使用了淘汰绑定:
@if (!Model.IsMyStore) {
<script type="text/javascript">
$(document).ready(ko.applyBindings(new StoreVm(@Html.Raw(JsonConvert.SerializeObject(Model, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() })))));
</script>
} else if (Model.IsMyStore) {
<script type="text/javascript">
$(document).ready(ko.applyBindings(new MyStoreVm(@Html.Raw(JsonConvert.SerializeObject(Model, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() }).Sanitize()))));
</script>
}
这种方法有什么问题吗?如果有两个子类型需要从同一父级继承,可以执行以下操作:
function Parent( foo ) {
this.foo = foo;
}
Parent.prototype.method = function() {
console.log( this.foo );
};
function Child1() {
Parent.call( this, "bar" );
}
Child1.prototype = Object.create( Parent.prototype );
Child1.prototype.constructor = Child1;
function Child2() {
Parent.call( this, "qux" );
}
Child2.prototype = Object.create( Parent.prototype );
Child2.prototype.constructor = Child2;
var parent = new Parent("blah");
var child1 = new Child1();
var child2 = new Child2();
parent.method(); // => "blah"
child1.method(); // => "bar"
child2.method(); // => "qux"
首先,您应该了解
JavaScript
如何实现继承JavaScript
是一种基于原型的语言,它不包含class语句,如C
中的语句。相反,它使用函数作为类(没有类,只有对象)。因此,我们这里有对象继承自其他对象(现在您可能需要喝点咖啡) 因此,
JavaScript
并没有赋予您在C#
中获得的继承和多态性的全部功能如果您想知道如何在JS中实现继承: 回到您的问题,我认为您可能需要实施。因此,您的js代码可能是这样的:
function MyStoreVm(model) {
var self = this;
self.doThis = function() {
// do stuff
self.doThat();
};
}
function StoreVm(model) {
var self = this;
self.doThis = function() {
// do stuff
self.doThat();
};
}
// Define factory object that create your proper store object
// StoreFactory takes the model as input.
// You can change it to accept seconf parameter that define class type
function StoreFactory() {
this.classType == "MyStoreVm"; // default value
this.createStore = function(model) {
if (model.IsMyStore === true)
this.classType = MyStoreVm;
else
this.classType = StoreVm;
return new this.classType(model);
}
}
然后在MVC视图中:
$(document).ready(function() {
var mystoreFactory = new StoreFactory();
ko.applyBindings(mystoreFactory.createStore((@Html.Raw(JsonConvert.SerializeObject(Model, new JsonSerializerSettings() {
ContractResolver = new CamelCasePropertyNamesContractResolver()
})))));
});
退房。虽然这与创建自己的原型和继承方法基本相同,但使用起来很好。这也是AMD意识到的
// base class
var Store = klass(function() {
var self = this;
// add properties here
}).methods({
doThis: function () {
// do this
},
doThat: function () {
// do that
}
});
return Store;
// create the first constructor
var myStoreVm = Store.extend(function () {
// super class is called
}).methods({
doThis: function(){
this.supr(); // call Store.doThis
// some other code
}
});
return myStoreVm;
// create the second constructor
var storeVm = Store.extend(function () {
// super class is called
}).methods({
doThis: function(){
// override Store.doThis with my own code
}
});
return storeVm;
抱歉-它们都应该从一个单独的其他函数继承。谢谢。我试过你的建议,但把所有的东西都放在一起时弄糊涂了。我能够通过更新中的代码使其工作-您对这种方法有何想法?有点可笑,您提到JavaScript是一种基于原型的语言,然后生成了完全没有使用它的示例代码。@HMR您说得对。。我只是想弄清楚如何解决这个问题,而不是详细解释继承。尽管我很困惑——这是如何消除代码重复的?我试图通过将共享代码从两个模块中推到一个共享模块中来变得更简单、更干练。我认为JS并没有提供您想要的灵活性。最后,您必须声明希望对象不是基类的子类类型(JS中没有多态性)
$(document).ready(function() {
var mystoreFactory = new StoreFactory();
ko.applyBindings(mystoreFactory.createStore((@Html.Raw(JsonConvert.SerializeObject(Model, new JsonSerializerSettings() {
ContractResolver = new CamelCasePropertyNamesContractResolver()
})))));
});
// base class
var Store = klass(function() {
var self = this;
// add properties here
}).methods({
doThis: function () {
// do this
},
doThat: function () {
// do that
}
});
return Store;
// create the first constructor
var myStoreVm = Store.extend(function () {
// super class is called
}).methods({
doThis: function(){
this.supr(); // call Store.doThis
// some other code
}
});
return myStoreVm;
// create the second constructor
var storeVm = Store.extend(function () {
// super class is called
}).methods({
doThis: function(){
// override Store.doThis with my own code
}
});
return storeVm;