Vue中父子间传参(props,$emit)

组件是Vue核心功能之一,合理的组件化,可以减少我们代码的冗余,提高项目的可维护性。下面,我将由浅入深的讲Vue的组件
在讲之前,首先我们先了解一下组件的命名。


HTML是对特征名不敏感的语言,他会将所有的字符全部转换成小写。我们命名了一个组件的名称为 nameTest ,然后再其他组件里面引用 <nameTest> </nameTest> ,那么我们将找不到这个组件,因为这个组件一已经将名字转换为nametest

 

props : 父组件 向 子组件 传参

基本使用

Parent.vue

 1 <template>
 2 <div>
 3     parent:下面是我的子组件
 4     <childSon :userName='name'></childSon>
 5 </div>
 6 </template>
 7 <script>
 8 import childSon from './Childs'
 9 export default {
10     name:'Parent',
11     components:{
12         childSon
13     },
14     data(){
15         return{ 
16             name:'啊哈'
17         }
18     }
19 }
20 </script>

Childs.vue

 1 <template>
 2 <div>
 3     child:这是父组件给我传的数据——{{userName}}
 4 </div>
 5 </template>
 6 <script>
 7 export default {
 8     name:'Childs',
 9     props:['userName'],
10     data(){
11         return{
12 
13         }
14     }
15 }
16 </script>

 

 

 我们在 Parent.vue 组件里面引用子组件 Childs.vue 然后传入 userName 参数给子组件,Childs props里面接收父组件传传来的数据。

上面的例子我们传入的是一个字符串,其实,props可以传入StringNumberObjectBoolenArray等数据类型。那么我们在接受参数的时候就会有一个问题,我们怎么知道接收的应该是字符串'12'还是数字12呢?
所以 Vue有一个 Prop验证 的功能。

Prop 验证

子组件在接受数据的时候,可以指定接收具体类型的数据、是否不能为空,是否有默认值等。
Parent.vue

 1 <template>
 2 <div>
 3     parent:下面是我的子组件
 4     <childSon :name='name' :firstName='firstName' :age='18' ></childSon>
 5 </div>
 6 </template>
 7 <script>
 8 import childSon from './Childs'
 9 export default {
10     name:'Parent',
11     components:{
12         childSon
13     },
14     data(){
15         return{ 
16             name:'大卫',
17             firstName:'大华'
18         }
19     }
20 }
21 </script>

Child.vue

 1 <template>
 2 <div>
 3      child:这是父组件给我传的数据——name:{{name}}——firstName:{{firstName}}——lastName:{{lastName}}——age:{{age}}
 4 </template>
 5 <script>
 6 export default {
 7     name:'Childs',
 8     props:{
 9         name: String,
10         firstName: {
11             type: String,//规定值的类型
12             required: true //必须传值,否则报错
13         },
14         lastName: {
15             type: String,
16             default: 'lastNameDefault' //如果不传值,则为default的值
17         },
18         age: {
19             type: [String,Number], //类型可以是多种
20             validator: function(value) { //自定义验证
21 
22                 let num = parseInt(value)
23                 if (num > 0 && num <100) {
24                     return true;
25                 } else {
26                     return false;
27                 }
28             }
29         }
30     },
31     data(){
32         return{
33 
34         }
35     }
36 }
37 </script>

运行结果如下图:

 

 

 

如果我们将条件改变的时候,name 传入一个数组,firstName 不传值,age 传入一个不能转换为数字的值。

<childSon :name=[11]  age='ss' ></childSon>

 

 

 

 

 

 

 

 

 

 

 根据我们的验证规则,name 必须为一个String 类型,所以控制台报错:希望得到一个String,得到了一个数组;firstName 为一个必填的值,但是我们没有传值,所以报错;age要为一个可以转换成数字的值,但是我们穿了"ss",会经过我们自定义的验证,然后抛错。

Prop传入对象

如果我们要将一个 对象 的所有属性全部传给子组件,我们不需要将属性一个个的作为Prop传递,只需要将整个对象传递过去就可以。

 

Parent.vue

 1 <template>
 2 <div>
 3     parent:下面是我的子组件
 4     <childSon v-bind='obj' ></childSon>
 5 </div>
 6 </template>
 7 <script>
 8 import childSon from './Childs'
 9 export default {
10     name:'Parent',
11     components:{
12         childSon
13     },
14     data(){
15         return{ 
16             obj: {
17                 name: 'lily',
18                 age: '16'
19             }
20         }
21     }
22 }
23 </script>

 

Childs.vue

 1 <template>
 2 <div>
 3     child:这是父组件给我传的数据——name:{{name}}——age:{{age}}
 4 </div>
 5 </template>
 6 <script>
 7 export default {    
 8     name:'Childs',
 9     props:{
10         name: String,
11         age: {
12             type: [String,Number], //类型可以是多种
13             validator: function(value) { //自定义验证
14 
15                 let num = parseInt(value)
16                 if (num > 0 && num <100) {
17                     return true;
18                 } else {
19                     return false;
20                 }
21             }
22         }
23     }
24 }
25 </script>

运行结果如下图:

 

 

 

我们传入一个 obj 对象,然后在子组件里面可以拿到对象

的所有属性。

Prop的单向数据传递

直接作为一个本地变量

Parent.vue

 1 <template>
 2 <div>
 3     parent:<input type='text' v-model="content">下面是我的子组件 
 4     <childSon :content='content' ></childSon>
 5 </div>
 6 </template>
 7 <script>
 8 import childSon from './Childs'
 9 export default {
10     name:'Parent',
11     components:{
12         childSon
13     },
14    data() {
15     return {
16       content:'er'
17     };
18   },
19 }
20 </script>

Childs.vue

 1 <template>
 2 <div>
 3     child:这是父组件给我传的数据——{{con}}
 4 </div>
 5 </template>
 6 <script>
 7 export default {    
 8     name:'Childs',
 9     props:['content'],
10     data(){
11         return{
12            con:this.content
13         }
14     }
15 }
16 </script>

运行结果如下图:

 

 

emit :子组件 向 父组件 传递数据

基本使用

子组件父组件传递数据,不能像上面一样实时的传递数据,必须通过 事件 触发。我们通过 $emit 方法来向父子间传递数据,第一个参数为事件的 名称 ,第二个为传递的 数据 ,是一个可选的参数。父组件必须监听同样的事件名称才能监听到我们的这个事件,事件抛出的值必须通过 $event或者通过一个方法来访问。

**Parent.vue

 1 <template>
 2 <div>
 3     parent:这是我的子组件传给我的值:{{num}}
 4     <childSon :content='content' @getNum='getMsg'></childSon>
 5 </div>
 6 </template>
 7 <script>
 8 import childSon from './Childs'
 9 export default {
10     name:'Parent',
11     components:{
12         childSon
13     },
14    data() {
15     return {
16       content:'er',
17       num:''
18     }
19   },
20   methods:  {
21       getMsg(num){
22           this.num = num;
23       }
24   }
25 }
26 </script

Childs.vue

 1 <template>
 2 <div>
 3     child:这是父组件给我传的数据——{{content}} <br />
 4     <button @click="sendMsgtoParent">点击我可以向父子间传递参数哦</button>
 5 </div>
 6 </template>
 7 <script>
 8 export default {    
 9     name:'Childs',
10     props:['content'],
11     data(){
12         return{
13             num: 0
14         }
15     },
16     methods: {
17         sendMsgtoParent(){
18             this.$emit('getNum',this.num ++ );
19         }
20     }
21 }
22 </script>

运行结果如下图:

 

 

子组件定义了一个num变量,然后点击按钮触发method,通过 $emit向父组件发送事件的名称(getNum)和一个参数(this.num),然后 父组件 监听事件getNum,然后将传递值赋值给父组件的一个属性上,这样就可以是实现子组件点击一次按钮,就向父组件发送一次数据。更多实例可以参考官网

组件间的数据双向绑定

我们知道我们可以使用v-model来实现数据的双向绑定。但是如果这个数据是跨组件的话,我们要怎样实现绑定吗?

首先我们先要明白v-model的原理。v-model其实是分为两个方面,一方面数据层的改变引起视图层的变化,我们可以使用v-bind来实现,另一方面视图层的变化引起数据层的变化我们可以监听事件来实现。所以我们想要双向绑定一个数据,只需要这两步操作。具体实现参考官网

弹框嵌套表格组件化使用

 

posted @ 2022-05-11 19:16  Adinsclay  阅读(2158)  评论(0)    收藏  举报