[Vuejs]-Vue component communication

0👍

I’ve written up a snippet with four examples: your original, a simple Vue app (no components) that does the same thing, and two apps with two components that are coordinated by the parent.

The simple Vue app is actually more concise than the pure JavaScript app, and I think it shows off the reason for having a framework: your view doesn’t act as a store for your program data, from which you have to pull it out.

In the final example, the parent still owns pageText, but passes it down to the my-textarea component. I like to hide the emitting behind the abstraction of a settable computed, so that the element can use v-model. Any changes are emitted up to the parent, which changes pageText, which propagates back down to the component.

I think your performance concerns fall into the realm of premature optimization, but it is possible not to use the text content as data at all, and only be concerned with the length. The fourth example does that. emitLength could have used event.target.value.length, but I wanted to use it in the mounted to initialize the length properly, so I used a ref.

function characterCount() {
  var characters = document.myForm.pagetext.value.length;
  document.getElementById('charcounter').innerHTML = characters + "";
}
new Vue({
  el: '#app',
  data: {
    pageText: 'Type here'
  }
});

new Vue({
  el: '#app2',
  data: {
    pageText: 'Type here'
  },
  components: {
    myTextarea: {
      props: ['value'],
      template: '<textarea name="pagetext" v-model="proxyValue"></textarea>',
      computed: {
        proxyValue: {
          get() {
            return this.value;
          },
          set(newValue) {
            this.$emit('input', newValue);
          }
        }
      }
    },
    textLength: {
      props: ['value'],
      template: '<div>{{value}}</div>'
    }
  }
});

new Vue({
  el: '#app3',
  data: {
    textLength: null
  },
  components: {
    myTextarea: {
      template: '<textarea ref="ta" name="pagetext" @input="emitLength">Type here</textarea>',
      methods: {
        emitLength() {
          this.$emit('change', this.$refs.ta.value.length);
        }
      },
      mounted() {
        this.emitLength();
      }
    },
    textLength: {
      props: ['value'],
      template: '<div>{{value}}</div>'
    }
  }
});
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<form name="myForm">
  <textarea id="pagetext" name="pagetext" onChange="characterCount();" onKeyup="characterCount();">Type here</textarea>
</form>
<div id="charcounter"></div>

<div id="app">
  <h1>Vue (simple)</h1>
  <form>
    <textarea name="pagetext" v-model="pageText"></textarea>
  </form>
  <div>{{pageText.length}}</div>
</div>

<div id="app2">
  <h1>Vue (with components)</h1>
  <form>
    <my-textarea v-model="pageText"></my-textarea>
  </form>
  <text-length :value="pageText.length"></text-length>
</div>

<div id="app3">
  <h1>Vue emitting stats</h1>
  <form>
    <my-textarea @change="(v) => textLength=v"></my-textarea>
  </form>
  <text-length :value="textLength"></text-length>
</div>

0👍

You can create a "Model" for value of textarea and provide this model to second component by using following way https://v2.vuejs.org/v2/guide/components-props.html

Leave a comment