引用官网的一句话:父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息
1.父组件向子组件传值
在子组件中定义props数组添加属性,父组件可以直接给props中的属性传值
父组件—传值—>子组件
1、子组件绑定父组件的数据
v-bind:post="post"
2、子组件用props接收
props: ['post'],父组件—监听—>子组件
1、监听(父)
v-on:enlarge-text123=“执行的事件"
2、发送(子)
v-on:click="$emit('enlarge-text123')"
具体代码实现
postDemo.js
import Vue from 'vue'
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
<div v-html="post.content"></div>
</div>
})
vue_global_api.vue
<template>
<div id="vue_global_api">
<div id="components-demo">
<!--
v-bind:key 不传有警告
v-bind:post post是组件内接收的参数名
-->
<!-- <blog-post v-for="post in posts" v-bind:post="post" v-bind:key="post.id" v-on:enlarge-text="onEnlargeText"></blog-post> -->
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post v-for="post in posts" v-bind:key="post.id" v-bind:post="post" v-on:enlarge-text="postFontSize += 0.1"></blog-post>
</div>
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post v-for="post in posts" v-bind:key="post.id" v-bind:post="post" v-on:enlarge-text="postFontSizeAction"></blog-post>
</div>
</div>
</div>
</template>
<article class="_2rhmJa" style="box-sizing: border-box; display: block; font-weight: 400; line-height: 1.8; margin-bottom: 20px;">
<script>
import {
postDemo
} from '../js/postDemo.js'
export default {
el: 'vue_global_api',
data() {
return {
posts: [{
id: 1,
title: 'My journey with Vue'
},
{
id: 2,
title: 'Blogging with Vue'
},
{
id: 3,
title: 'Why Vue is so fun'
}
],
data: {
title: "this.title",
message: "this.message"
},
postFontSize: 1
}
},
methods: {
postFontSizeAction() {
this.postFontSize += 0.1
}
}
}
</script>
<style>
</style>
2.子组件向父组件传值
子组件可以通过调用内建的
$emit
方法 并传入事件名称来触发一个事件
通过事件向父组件发送信息
- 子组件中EnFontsize.vue中$emit
<button @click="$emit('enlarge-text')">Enlarge text</button>
- 父组件中:
<template>
<div id="app">
<div :style="{ fontSize: postFontSize + 'em' }">
<div v-for="post in posts" v-bind:key="post.id" v-bind:post="post">
<span>{{post.id}}</span>
<span>{{post.title}}</span>
<EnFontsize v-on:enlarge-text="postFontSize += 0.1"></EnFontsize>
</div>
</div>
</div>
</template>
<script>
import EnFontsize from "./components/EnFontsize";
export default {
name: "App",
data: function() {
return {
posts: [
{ id: 1, title: "the title is..." },
{ id: 2, title: "the title is..." }
],
postFontSize: 1
};
},
components: {
EnFontsize
}
};
</script>
使用事件抛出一个值
- 子组件中使用 $emit 的第二个参数来提供这个值:
<button @click="$emit('enlarge-text123', 0.1)">Enlarge text</button>
- 父组件中可以通过 $event 访问到被抛出的这个值:
<EnFontsize v-on:enlarge-text123="postFontSize += $event"></EnFontsize>
或者,如果这个事件处理函数是一个方法:
<!-- <EnFontsize v-on:enlarge-text="postFontSize+=$event"></EnFon>-->
<EnFontsize v-on:enlarge-text="onEnlargeText"></EnFontsize>
那么这个值将会作为第一个参数传入这个方法:
methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}
注意:这里是自动接收这个值并传给函数作为第一个参数,虽然没有使用$event接收
3.非父子组件进行传值
非父子组件之间传值,需要定义个公共的公共实例文件bus.js,作为中间仓库来传值,不然路由组件之间达不到传值的效果。
- 公共bus.js
//bus.js
import Vue from 'vue'
export default new Vue()
- 组件A:
A组件:
<template>
<div>
<span>{{elementValue}}</span>
<input type="button" value="点击触发" @click="elementByValue">
</div>
</template>
<script>
// 引入公共的bug,来做为中间传达的工具
import Bus from './bus.js'
export default {
data () {
return {
elementValue: 4
}
},
methods: {
elementByValue: function () {
Bus.$emit('val', this.elementValue)
}
}
}
</script>
- 组件B:
<template>
<div>
B组件:
<input type="button" value="点击触发" @click="getData">
<span>{{name}}</span>
</div>
</template>
<script>
import Bus from './bus.js'
export default {
data () {
return {
name: 0
}
},
mounted: function () {
var vm = this
// 用$on事件来接收参数
Bus.$on('val', (data) => {
console.log(data)
vm.name = data
})
},
methods: {
getData: function () {
this.name++
}
}
}
</script>
非父子组之间的传值方式:1.创建中间仓库。2,缓存 3,vuex
单向数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
- 这里有两种常见的试图改变一个 prop 的情形:
1.这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
- 这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
props: ['size'],
computed: {
// 计算属性的 getter
normalizedSize: function () {
// `this` 指向 vm 实例
return this.size.trim().toLowerCase()
}
}
注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。