Edited at

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

More than 1 year has passed since last update.

※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>