VueJs Ajax数据映射

In a Vue page, I have a call to get data using Ajax when the mounted() event is fired. The code recreates the existing Pager using a new Pager object where it has to pass in all the parameters in the constructor to reconstruct it.

If I don't do this, vm.Pager is just an Object and does not have some needed methods, and fails the prop type check that it gets passed to.

        axios.post("/Home/GetList", vm.Pager)
        .then(function (result)
        {
           var p = result.data.Pager;
           vm.Pager = new Pager(p.PageSize, p.CurrentRecord, p.TotalCount);
           // etc. (Pager has additional fields...)
           vm.ItemList = result.data.ListItems;        
        })
        .catch(function (error)
        {
            alert(error); 
        });

In the knockoutjs, there was a mapping function and you could what tell it what types to map without having to recreate the object. This was convenient, particularly for more complicated or nested Ajax data.

Is there a better way to do this in Vue (or javascript) where it maps the type from the Ajax without having to recreate it?

You could make your own mapper function.

methods: {
  mapTypesToData (responseData, map) {
     responseData.forEach((item, key) => {
       let mapperVal = map[key]
       if (typeof mapperVal === 'string') {
         this.$set(this, map[key], item)
       } else if (typeof mapperVal === 'function') {
         this.$set(this, key, map[key](item))
       }
     })
  }
}

then in your ajax request

        axios.post("/Home/GetList", vm.Pager)
        .then(function (result)
        {
          this.mapTypesToData(result.data, {
            ItemList: 'ListItems',
            Pager: (p) => new Pager(p.PageSize, p.CurrentRecord, p.TotalCount)
          })      
        })

I found I can use either:

Object.assign(vm.Pager, result.data.Pager);

Or

// import _ from 'lodash'
_.merge(vm.Pager, result.data.Pager);

...and both seem to update the viewmodel correctly. Unfortunately, when I use either of these methods, the watch method in the nested ListPager control (which receives the Pager object) does not fire.

To get that to work, I found the solution below, after looking at this documentation VueJs: Reactivity in Depth - Change Detection Caveats.

 vm.Pager = Object.assign(new Pager(), vm.Pager, result.data.Pager);

This actually creates a new Pager but seems to populate it correctly and retains the Vue reactivity. Hopefully this will scale out to more elaborate solutions, if needed.