vue.js
vue.js2

Vue.js 2系で親コンポーネントから子コンポーネントにデータを受け渡す。

※Vue.js初心者です。あしからず。
こんな記事をゆっくり更新しています。
Vue.js初心者の僕がつまづいたところメモ
いつか誰かのお役にたてるようにがんばっていきます。

親コンポーネントから子コンポーネントにdataを渡す。

こんな構成でブログの新規投稿画面(Editor)を作成しました。
Githubっぽいマークダウンで入力して、RailsAPIにテキストを送信します。
それにあたり、コンポーネント分割の練習をしてみました。

実装物

component_vue.png

結論:こんなコードになりました。

※コードは重要なところ以外は省略しています!

親コンポーネント

親コンポーネントEditorから子コンポーネントSubmitButtonを呼び出しています。

Editor.vue
<template>
  <!-- 省略 -->
  <SubmitButton :input="input"></SubmitButton>
</template>

<script>

import SubmitButton from "@components/parts/buttons/SubmitButton"

export default {
  name: "Editor"
  data () {
    return {
      input: ""
    }
  }
}

</script>

SubmitButton.vue
<template>
  <div id="submit" v-on:click="addFeed">Submit</div>
</template>

<script>
  import axios from "axios"

    export default {
      name: 'SubmitButton',
      props: ['input'],
      methods: {
        addFeed(e) {
          let _this = this;

          axios.post("http://localhost:3000/feeds",
            {
              feed: {
                text: this.input
              }
            }
          ).then(function(res) {
            _this.$router.push({ path: "/"})
          })
          e.preventDefault();
        }
      }
    }
</script>

ポイント

親側でv-bind, 子側でprops、そしたらthisでとれる。

Feed.vue
 <SubmitButton :input="input"></SubmitButton>

親コンポーネントで子コンポーネントを呼び出しているところで
v-bindして親コンポーネントとdataであるinputを渡してあげる。
(:input="input"の部分)

SubmitButton
export default {
  name: 'SubmitButton',
  props: ['input'],
  methods: {
    addFeed(e) {
      this.input //this.inputでアクセスできる!ワッショイヽ(゚∀゚)ノワッショイ

    }
  }
}

子コンポーネントでpropsを記述すると、
this.inputで親のdataにアクセスできるようになってる!

あとがき

データバインディングがどうとか、v-bindの挙動だとか細かい話しは正直わかっていません。また随時お勉強次第書き足していきます!

おまけ: 全コード(2コンポーネント分)

マークダウンエディタでブログ投稿画面を作成しています。

Vueのことはまだまだわかっていませんが、コンポーネント化という思想はとても好きです。JSが圧倒的に追いやすい。

Feed.vue
<template>
  <div id="feed">
    <div id="markdown-display" v-html="compiledMarkdown"></div>
  </div>
</template>

<script>
;(function() {
  var renderer = new marked.Renderer()
  renderer.code = function(code, language) {
    return '<pre'+'><code class="hljs">' + hljs.highlightAuto(code).value + '</code></pre>';
    // 参考サイト: http://phiary.me/marked-js-highlight-js, https://qiita.com/59naga/items/7d46155715416561aa60
   };

  marked.setOptions({
    renderer: renderer,
  });
})();

import axios from 'axios'
export default {
  name: 'Markdown',
  data () {
    return {
      feed: ""
    }
  },
  created() {
    axios.get('http://localhost:3000/feeds/' + this.$route.params.id)
    .then(response => {
      this.feed = response.data.text
    })
    .catch(e => {
      this.errors.push(e)
    })
  },
  computed: {
    compiledMarkdown: function() {
      return marked(this.feed, { sanitize: true })
    }
  }
}
</script>

<style scoped>
#feed {
  padding: 20px 80px;
  text-align: left;
}
</style>
SubmitButton.vue
<template>
  <div id="submit" v-on:click="addFeed">Submit</div>
</template>

<script>

import axios from "axios"

export default {
  name: 'SubmitButton',
  props: ['input'],
  computed: {
    compiledMarkdown: function() {
      return marked(this.input, { sanitize: true })
    }
  },
  methods: {
    addFeed(e) {
      let _this = this;
      console.log(this);

      axios.post("http://localhost:3000/feeds",
        {
          feed: {
            text: this.input
          }
        }
      ).then(function(res) {
        _this.$router.push({ path: "/"})
      })
      e.preventDefault();
    }
  }
}
</script>


<style scoped>
  #submit {
    position: fixed;
    bottom: 20px;
    right: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100px;
    text-align: center;
    box-shadow: 0 2px 5px rgba(0,0,0,0.26);
    height: 40px;
    cursor: pointer;
    color: #fff;
    background: #706D7F;
    border: 1px solid transparent;
    transition: all .3s;
  }

  #submit:hover {
    background: #fff;
    color: #706D7F;
    border: 1px solid #D1D9E5;
  }
</style>