Vue Mixins for Component

Vue Mixins for Component demo by http://qcode.in

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
 <foo></foo>
 <bar></bar>
</div>

JavaScript

// Mixins
let dateRangeFormat1 = {
  computed: {
    dateRangeFormat() {
      return `[1: ${this.start}-${this.end}]`;
    }
  }
}
let dateRangeFormat2 = {
  computed: {
    dateRangeFormat() {
      return `[2: ${this.start}-${this.end}]`;
    }
  }
}
let dateRangeFormat3 = {
  computed: {
    dateRangeFormat() {
      return `[3: ${this.start}-${this.end}]`;
    }
  }
}

function mergeComputed(parentVal, childVal) {
  if(typeof parentVal !== 'function' || typeof childVal !== 'function') 
    throw new Error('Не умею работатать со сложным computed, допили меня!');

  return function() {
    return parentVal.call(this) + ' | '  + childVal.call(this)
  }
}

Vue.config.optionMergeStrategies.computed = function(parentVal, childVal) {
  if (!parentVal) return childVal;
  if (!childVal) return parentVal;

  const mergedVal = Object.create(null);
  
  for(const key in childVal) if(key in parentVal) {
    mergedVal[key] = mergeComputed(parentVal[key], childVal[key]) 
  }
  
  return {
    ...parentVal,
    ...childVal,
    ...mergedVal
  };
};


Vue.component('foo', {
  template: '<div>foo: {{dateRangeFormat}}</div>',
  data() {
    return {
      start: 1,
      end: 2,
    }
  },
  mixins: [
    dateRangeFormat1,
    dateRangeFormat2,
    dateRangeFormat3, 
  ]
});

Vue.component('bar', {
  template: '<div>bar: {{dateRangeFormat}}</div>',
  data() {
    return {
      start: 3,
      end: 4,
    }
  },
  mixins: [    
    dateRangeFormat3,
    dateRangeFormat2,
    dateRangeFormat1,
  ]
});

new Vue({
  el: '#app'
})