1、父组件向子组件传值
想要在子组件中使用父组件的数据不能直接调用,但是可以使用组件传值的形式(父传子),使用属性绑定的形式,把子组件需要的数据传递到子组件内部,主要分为父传递和子组件接收两个步骤。
1.1、父组件传值给子组件
在父组件中使用子组件的时候,通过子组件的属性进行传递。通过:v-bind:自定义属性名="父组件数据的变量名(要传递的数据变量名)"
来给子组件传值。
自定义属性名:子组件内部用来接收父组件数据的变量名。
语法:
<子组件名称 v-bind:自定义属性名="父组件数据的变量名(要传递的数据变量名)"></子组件名称>
<!-- 简写,省略v-bind -->
<子组件名称 :自定义属性名="父组件数据的变量名(要传递的数据变量名)"></子组件名称>
1.2、子组件接收和使用父组件传递过来的值
props配置项用来接收父组件传递过来的值。props可以是数组、也可以是对象,如果是数组,那么里面就定义字符串类型的变量名,这个变量名要和接收父组件名称的数据一致。
语法:
props:['自定义属性名']
子组件中使用父组件传递过来的值:
<p>父组件中传递过来的数据:{{自定义属性名}}</p>
1.3、父子组件传值实例
<div id="app">
<h4>父组件</h4>
<p>父组件中的数据:{{msg}}</p>
<hr />
<sub-component v-bind:pmsg="msg"></sub-component>
</div>
<!-- 子组件模板 -->
<template id="subComponent">
<div>
<h4>子组件</h4>
<p>subComponent组件模板</p>
<p>子组件中的数据:{{name}}</p>
<p>父组件中传递过来的数据:{{pmsg}}</p>
</div>
</template>
<script src="../lib/vue.js"></script>
<script>
let subComponent = {
template: '#subComponent',
data(){
return {
name: '张三'
}
},
/**
* 接收父组件传递的值:
* props配置项接收父组件传递过来的值。
* props可以是数组、也可以是对象,如果是数组,那么里面就定义字符串类型的变量名,这个变量名
* 要和接收父组件名称的数据一致
**/
props:['pmsg']
};
Vue.component('subComponent', subComponent);
const vm = new Vue({
el: '#app',
data:{
msg: 'Hello Vue.'
}
});
</script>
运行结果:

1.4、父组件向子组件传值的特点
所有的prop都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
(1)、当父组件中的数据发生变化的时候,子组件中的值也相应改变。
(2)、当子组件的值发生改变的时候,不会影响到父组件中的数据。
实例:
<div id="app">
<h4>父组件</h4>
<p>父组件中的数据:{{msg}}</p>
<!-- <p>子组件中的数据:{{name}}</p> -->
<button type="button" @click="msg = 'Hello JavaScript.'">修改父组件中的msg</button>
<hr />
<sub-component v-bind:pmsg="msg"></sub-component>
</div>
<!-- 子组件模板 -->
<template id="subComponent">
<div>
<h4>子组件</h4>
<p>subComponent组件模板</p>
<p>子组件中的数据:{{name}}</p>
<p>父组件中传递过来的数据:{{pmsg}}</p>
<button type="button" @click="pmsg = 'Hello JavaScript.'">修改父组件传递过来的pmsg</button>
</div>
</template>
演示结果:

2、子组件向父组件传值
2.1、调用父组件函数来实现子向父传值
2.1.1、将父组件的函数传递给子组件
使用v-on
指令将父组件的函数与子组件绑定。就可以在子组件中使用父组件的函数(父组件向子组件传递函数(函数也是一种值))。
语法:
<子组件名 v-on:自定义名称 = "父组件中的函数名"></子组件名>
<!-- 简写 -->
<子组件名 @自定义名称 = "父组件中的函数名"></子组件名>
<!-- 可以传递多个 -->
<子组件名 @自定义名称 = "父组件中的函数名" @自定义名称1 = "父组件中的函数名2" @自定义名称2 = "父组件中的函数名2"></子组件名>
自定义的名称:在子组件中调用父组件函数的名称。只能是小写,或小写字母加下划线,不能使用驼峰命名。
例如:
<sub-component v-on:ptest="test"></sub-component>
或者简写为:
<sub-component @ptest="test"></sub-component>
<script>
const vm = new Vue({
el: '#app',
data:{
msg: 'Hello Vue.',
cname: ''
},
methods: {
//父组件中定义的方法
test( value ){
//value是子组件传递来的参数
this.cname = value;
}
},
});
</script>
将父组件的test函数与子组件进行绑定,在组件内部可以通过ptest名称来调用父组件的test方法。
2.1.2、在子组件中调用父组件的函数
Vue对象给我们提供了一个“触发函数”的对象$emit(父组件映射过来的名称,调用父组件函数的传递进去参数)
。
在子组件中定义一个方法,用来触发执行父组件传递过来的函数:
父组件映射过来的名称不能是驼峰命名的,必须是小写字母或小写字母加下划线的方式命名。
<template id="subComponent">
<div>
<h4>子组件</h4>
<p>subComponent组件模板</p>
<p>子组件中的数据:{{name}}</p>
<button type="button" @click="invokePtest">调用父组件传递过来的函数ptest</button>
</div>
</template>
<script>
let subComponent = {
template: '#subComponent',
data(){
return {
name: '张三'
}
},
methods:{
//在子组件中触发执行父组件的函数并传递参数
invokePtest(){
this.$emit('ptest',this.name);
}
}
};
Vue.component('subComponent', subComponent);
</script>
2.1.3、实例
<div id="app">
<p>子组件取巧的形式传递过来的name:{{cname}}</p>
<hr />
<sub-component @ptest="test"></sub-component>
</div>
<!-- 子组件模板 -->
<template id="subComponent">
<div>
<h4>子组件</h4>
<p>subComponent组件模板</p>
<button type="button" @click="invokePtest">调用父组件传递过来的函数ptest</button>
</div>
</template>
<script src="../lib/vue.js"></script>
<script>
let subComponent = {
template: '#subComponent',
data(){
return {
name: '张三'
}
},
methods:{
invokePtest(){
this.$emit('ptest',this.name);
}
}
};
Vue.component('subComponent', subComponent);
const vm = new Vue({
el: '#app',
data:{
cname: ''
},
methods: {
test( value ){
this.cname = value;
console.log(`子组件传递过来的值是:${value}`);
}
},
});
</script>
实例运行结果:

2.1.4、子组件修改父组件的数据
也是通过函数传递的形式调用。即:子组件触发执行一个父组件的方法,通过父组件的方法来修改父组件的数据。
<div id="app">
<h4>父组件</h4>
<p>子组件取巧的形式传递过来的name:{{cname}}</p>
<p>父组件的msg的值:{{msg}}</p>
<hr />
<sub-component @ptest="test" @change_value="changeValue"></sub-component>
</div>
<!-- 子组件模板 -->
<template id="subComponent">
<div>
<h4>子组件</h4>
<p>subComponent组件模板</p>
<button type="button" @click="invokePtest">调用父组件传递过来的函数ptest</button>
<button type="button" @click="changeParentMsg">修改父组件的msg的值</button>
</div>
</template>
<script src="../lib/vue.js"></script>
<script>
let subComponent = {
template: '#subComponent',
data(){
return {
name: '张三'
}
},
props:['pmsg'],
methods:{
invokePtest(){
this.$emit('ptest',this.name);
},
changeParentMsg(){
//在这里传递一个值,用来替换父组件属性的旧值
this.$emit('change_value',"Hello world!");
}
}
};
Vue.component('subComponent', subComponent);
const vm = new Vue({
el: '#app',
data:{
msg: 'Hello Vue.',
cname: ''
},
methods: {
test( value ){
this.cname = value;
console.log(`子组件传递过来的值是:${value}`);
},
//在这里修改父组件的数据
changeValue(value){
this.msg = value;
console.log(`父组件的msg值是:${value}`);
}
},
});
</script>
测试子组件修改父组件的值:

2.2、通过属性绑定的形式向子组件传递数据
2.2.1、添加属性修饰符.sync
子组件中的props数据发生改变,同步到父组件。
属性绑定的时候,添加同步修饰符:.sync
。加上这个修饰符以后,就可以实现子组件和父组件间的“双向绑定”。
语法:
<子组件名称 :自定义属性名称.sync="数据的变量名(要传递的数据变量名)"></子组件名称>
2.2.2、通过Vue的$emit对象来修改props里面的值
语法:
$emit('update:props里面的数据的名称')
在子组件中定义方法:
let subComponent = {
template: '#subComponent',
data(){
return {
name: '张三'
}
},
props:['pmsg'],
methods:{
changeMsg(){
//$emit('update:props里面的数据的名称')
this.$emit('update:pmsg','Hello JavaScript.');
}
}
};
2.2.3、实例
实现在子组件中修改父组件传递过来的值,并同步修改父组件中相应的属性。
<div id="app">
<h4>父组件</h4>
<p>父组件的msg的值:{{msg}}</p>
<button type="button" @click="msg = 'Hello JavaScript.'">修改msg的数据</button>
<hr />
<sub-component :pmsg.sync="msg"></sub-component>
</div>
<!-- 子组件模板 -->
<template id="subComponent">
<div>
<h4>子组件</h4>
<p>subComponent组件模板</p>
<p>父组件传过来的值:{{pmsg}}</p>
<button type="button" @click="changeMsg">修改父组件传递过来的pmsg(sync修饰符实现)</button>
</div>
</template>
<script src="../lib/vue.js"></script>
<script>
let subComponent = {
template: '#subComponent',
data(){
return {
name: '张三'
}
},
props:['pmsg'],
methods:{
changeMsg(){
this.$emit('update:pmsg','Hello JavaScript.');
}
}
};
Vue.component('subComponent', subComponent);
const vm = new Vue({
el: '#app',
data:{
msg: 'Hello Vue.',
},
methods: {
},
});
</script>
运行结果:

3、Props
Props是你可以在组件上注册的一些自定义特性。当一个值传递给一个 props 特性的时候,它就变成了那个组件实例的一个属性。
3.1、Props 的大小写
HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用DOM 中的模板时,camelCase(驼峰命名法)的 prop 名需要使用其等价的kebab-case(短横线分隔命名)命名:
在父组件给子组件传值的时候使用了“-”:
<sub-component :real-name="realname"></sub-component>
在子组件中接收值:
props:['realName'],//使用驼峰写法
在子组件模板中调用:
<p>父组件传过来的prealname值:{{realName}}</p>
3.2、Props类型
3.2.1、数组写法
props: ['name', 'age', 'isLogin', 'hobby', 'address']
3.2.2、对象写法