3

Given a component:

Vue.component('my-comp', {
  props: ['input'],
  watch: { input: function(){...} },
});

What is the programmatic method for the following?

<my-comp :input="map[key]"></my-comp> map[key] change triggers watch

I have tried:

new (Vue.component('my-comp'))({
  propsData: { input:map[key] }, // map[key] change doesn't trigger watch
});

The context for this is inserting zero-to-many components into markdown-generated HTML. I call .$mount() for each component, and move its node with a native DOM replaceChild() call when markdown is re-rendered. See also Vue components in user-defined markdown

Liam
  • 495
  • 6
  • 21
  • Possible duplicate of [Vue propsData not updating dynamically](https://stackoverflow.com/questions/48662160/vue-propsdata-not-updating-dynamically) – Roy J Mar 14 '18 at 14:20
  • The answer to that Q didn't appear to solve my issue. – Liam Mar 14 '18 at 18:49

2 Answers2

1

A render function is the programmatic means of creating and inserting a component. Using new with propsData is primarily for unit testing, where the component will not necessarily have a Vue instance as a parent.

$mount doesn't establish a parent-child relationship, it just mounts the component free-standing to the DOM. You will need to set up the parent-child props management.

Vue.component('my-comp', {
  template: '<div>{{ input }}</div>',
  props: ['input']
});

new Vue({
  el: '#app',
  data: {
    thingy: 5,
    child: null
  },
  created() {
    this.child = new(Vue.component('my-comp'))({
      propsData: {
        input: this.thingy
      }
    });
    this.$watch('thingy', (newValue) => this.child.$props.input = newValue);
    setInterval(() => ++this.thingy, 2000);
  },
  mounted() {
    this.child.$mount(this.$el);
  }
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <div>
tony19
  • 125,647
  • 18
  • 229
  • 307
Roy J
  • 42,522
  • 10
  • 78
  • 102
1

If prop input is a primitive value, we have to manipulate the component with child.$props.input = x as Roy J suggests, but in this case we need input = map[key]. Hence this solution:

Vue.component('my-comp', {
  props: ['map','key'],
  computed: { input: function() { return this.map[this.key] } },
  watch: { input: function(a, b) {...} }, // triggered on map[key] change
});

new (Vue.component('my-comp'))({
  propsData: { map:theMap, key:theKey }, // theMap must be reactive
});
Liam
  • 495
  • 6
  • 21