跳转到主要内容

主页内容

Vue组件(三)Vue组件间传值和Props

由 webadmin 发布于 阅读 23 次

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、对象写法