Loading “knockout.mapping” plugin using require.js

2020-05-28 02:31发布

问题:

I am creating an MVC3 application, with requireJS. In my views I need to convert the Model object into a knockout viewmodel object. So I need to use knockout and knockout.mapping libraries.

My application is designed in the following way,

1). All the script files are categorized into folders

  • Scripts/app/home/ - contains the scripts for the views in Home controller.
  • Scripts/lib/ - contains the scripts like jQuery, knockout,knockout.mapping, requirejs etc

2). In the "_Layout.cshtml" I am referencing "require.js" like this.

<script src="@Url.Content("~/Scripts/lib/require.js")" type="text/javascript"></script>

3). To configure the require.js settings I am using a different script file called "common.js" (Scripts/lib/common.js)

require.config(
{
    baseUrl: "/Scripts/",
    paths:{
            jquery: "lib/jquery-2.0.3",
            ko: "lib/knockout-2.3.0",
            komapping: "lib/knockout.mapping"
        }
});

4). This is my index.js file which is in 'Scripts/app/home/"

define(['ko', 'komapping'], function (ko, komapping) {

var person = function () {
    var self = this;
    self.getPersonViewModel = function (data) {
        return ko.mapping.fromJS(data); ;
    };

};
return { Person: person };

});

5). This is my "Index" action method in the "Home" controller

public ActionResult Index()
    {
        var person = new Person
        {
            Id = 1,
            Name = "John",
            Addresses = new List<Address>(new[]{new Address{Country = "Country 1", City = "City 1"}})
        };

        return View(person);
    }

6). Finally this is my "Index" view

@model MMS.Web.Models.Person

<script type="text/javascript">

require(["/Scripts/common/common.js"], function () {

            require(["app/home/index"], function (indexJS) {
                var person = new indexJS.Person();
                var vm = person.getPersonViewModel(@Html.Raw(Json.Encode(Model)));
            });
});
</script>

The problem which I am facing is when loading the index.js file, I get a script error that the knockout.js cannot be loaded.

Failed to load resource: the server responded with a status of 404 (Not Found) - http:///Scripts/knockout.js

But if I remove the dependency of "komapping" inside the "index.js" file it loads correctly, but then I cannot use the mapping functionality.

I had a look inside these links, but couldn't find a solution, Knockout.js mapping plugin with require.js and https://github.com/SteveSanderson/knockout.mapping/issues/57

Your help, suggestions are much appreciated. Thanks!

回答1:

I had the same issue. The problem is that the knockout.mapping defines a knockout dependency, so you need to satisfy this one when you load the script.

Here is how you should load your mapping stuff

require.config(
{
    baseUrl: "/Scripts/",
    paths:{
        jquery: "lib/jquery-2.0.3",
        knockout: "lib/knockout-2.3.0",
        komapping: "lib/knockout.mapping"
    },
    shim: {
        komapping: {
            deps: ['knockout'],
            exports: 'komapping'
        }
    }
});

Then in my case, I use an index.js file with a requirejs call like the following

requirejs(['jquery', 'knockout', 'komapping'], function($, ko, komapping){
    ko.mapping = komapping;
    //Do other stuff here
});