将介绍 Vue.js 中,父组件和子组件之间 Prop 之间数据流向关系,以及一些注意事项。涉及知识点:
父组件和子组件之间 Prop 的关系
什么是单向下行绑定
子组件试图修改 Prop 的情况
在 Vue.js 中,所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
前面介绍子组件修改 Prop 不会影响父组件的 Prop,因此不建议这么做。但是,也有例外,下面列举了两种常见的试图变更一个 prop 的情形:
(1)这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值,例如:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}(2)这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性,例如:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}注意:在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。
该示例定义了一个子组件,且在根组件和子组件均定义了按钮,该按钮用来对 count 加一操作。例如:
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue</title>
<!-- 使用 CDN 引入 Vue 库 -->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.9/vue.js"></script>
</head>
<body>
<div id="app">
<h1>
count: {{ count }}
<button v-on:click="incrParent">count++</button>
</h1>
<my-component my-title="Hello Vue.js"
v-bind:my-count="count"></my-component>
</div>
<script type="text/javascript">
Vue.component("my-component", {
props: {
myTitle: String,
myCount: Number
},
template: `
<div style="background:red;">
<h2>{{myTitle}}</h2>
<p>Count: {{myCount}}</p>
<p>
<button v-on:click="incr">myCount++</button>
</p>
</div>
`,
methods: {
incr: function(){
this.myCount += 1;
}
}
});
var app = new Vue({
el: "#app",
data: {
count: 1024
},
methods: {
incrParent: function(){
this.count += 1;
}
}
});
</script>
</body>
</html>运行效果图:

上图中,当我们点击组件外的按钮增加 count 会影响子组件,而点击子组件内部的按钮增加 count,并不会影响父组件。