Store pattern without Vuex

by bc_rikko

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.0/css/bulma.min.css">
<div id="parent">
  <div class="panel parent">
    <label class="label">Parent</label>
    <p v-text="state.message"></p>
  </div>
  
  <child></child>
  <grand-child></grand-child>
</div>

<script type="text/x-template" id="grand-child">
  <div class="panel grand-child">
    <label class="label">GrandChild</label>
    <input class="input" type="input" v-model="text">
    <button class="button" type="button" @click="setMessage">Set</button>
    <button class="button" type="button" @click="clearMessage">Clear</button>
  </div>
</script>

<script type="text/x-template" id="child">
  <div class="panel child">
    <label class="label">Child</label>
    <p v-text="state.message"></p>
  </div>
</script>

CSS

.panel {
  border: 4px dashed rgba(0,0,0,.5);
  padding: 10px;
  margin: 10px;
}

p {
  padding: 5px 10px;
}

JavaScript

// import [email protected] [email protected]
// x-templateはデモや極小アプリ以外は非推奨

const store = {
  state: {
    message: ''
  },
  setMessage (msg) {
    this.state.message = msg;
  },
  clearMessage (msg) {
    this.state.message = '';
  }
};

const GrandChild = Vue.component('grand-child', {
  template: '#grand-child',
  data () {
    return {
      text: '',
      state: store.state
    }
  },
  methods: {
    setMessage () {
      store.setMessage(this.text);
    },
    clearMessage () {
      store.clearMessage();
    }
  }
});

const Child = Vue.component('child', {
  template: '#child',
  data () {
    return {
      state: store.state
    }
  }
});

const Parent = new Vue({
  el: "#parent",
  components: {
    Child,
    GrandChild
  },
  data () {
    return {
      state: store.state
    }
  }
});