组件通信概述

组件之间虽然有父子关系,但还是互相独立的。互相之间并不能直接操作对方的数据。这是出于安全性考虑的。组件之间是有通信需求的,vue为我们提供了两者方式来实现父子组件之间的通信。分别是props(父传子)和emit(子传父)。 后面会详细讲解。

组件通信是非常重要的一个内容,也是相对比较难的一个内容,所以需要多练习,熟练掌握。

笔者打算写两篇文章来分别介绍props(父传子)和emit(子传父)。这篇文章先介绍props(父传子)的使用。

对于官方文档的吐槽(可直接跳过看下一小节)

题外话,可直接跳过看下一小节。

如果你看过官方文档,props是单独作为一个节点说明的,然后你发现根本看不懂,不知道他在说什么东西。而且一上来就讲props的驼峰命名。这并不是你的问题,而是文档的问题。
在文档的最开始,有一段提示,告诉你要先阅读组件基础。确实在组件基础这小节,居然给出了props的定义。
在这里插入图片描述

这是我最不能理解的文档结构,把定义放在别的地方,然后把不重要的东西又写在单独节点的开头。
在这里插入图片描述
我给的建议是先阅读 组件基础里面 关于props定义的部分,然后再阅读props这节。

什么是props

组件通信中要实现父传子的功能是通过props实现的。那么什么是props呢?

Prop 是你可以在组件上注册的一些自定义 attribute。这是官方给出的定义。简单点说,就是父组件给子组件传值的时候,把值直接传给子组件自己定义的属性。这些属性(property)是在子组件里面定义的,没错,prop就是property的缩写。相当于给父组件带名字的盒子,叫父组件往里面放数据就行。

还是举个例子说明更清楚。
我们定义一个子组件的模板,因为子组件是提供给父组件(通常就是顶层组件)用的。所以子组件定义的变量不能写死,而是需要父组件传入。

<!--1.定义子组件模板-->
<template id="studentInfo">
    <div>
        <p>{{msg}}</p>
        <p>姓名:{{name}}</p>
        <p>年龄:{{age}}</p>
        <p>性别:{{gender}}</p>
    </div>
</template>

我们希望父组件在使用子组件的时候是类似这种效果的。
如果你运行代码肯定报错,因为我们根本就没有定义name,age和gender属性。
这里就是最关键的地方。没有怎么办?当然是在子组件定义啊。

<div id="box">
       <student name="张三" age="age" gender="男"></student>
       <hr>
       <student name="李四" age="18" gender="女"></student>
</div>

我们可以通过在子组件里面写props来定义子组件的属性。
这是关键点。
props的本质就是给组件定义属性的名字。
props的本质就是给组件定义属性的名字。
props的本质就是给组件定义属性的名字。

给props写上值,就相当于子组件的模板标签可以使用下面的显示来使用了。这时候就不会报错了,因为name,age,gender已经定义好了。

 <student name="xxx" age="xxx" gender="xxx"></student>

这里还定义了data,里面返回了msg的值。也就是msg是用的子组件自己的值,没有对父组件暴露。

<!--2.注册子组件-->
  Vue.component("student",{
      template:`#studentInfo`,
      data(){
          return{
             msg: "我是一个好学生"
          }
       },
      //3.定义属性
      props:["name","age","gender"]
  })

运行代码神奇的事情发生了,原本不存在的name,age,gender属性居然可以用了。

<student name="李四" age="18" gender="女"></student>

在这里插入图片描述

props的多种定义方式

第一种方式:
这是最简单的方式。

props:["name","age","gender"]

第二种方式:
相对规范一点。

      props:{
          name:String,
          age:Number,
          gender:String
      }

第三种方式:
最完整的用法。

      props:{
          name:{
              type:String,
              required:true
          },
          age:{
              type:Number,
              required: false,
              default:99
          },
          gender: {
              type:String
          }
      }

props和数据绑定

前面其实props的基本概念已经讲完了。接下来看使用中会遇到的问题。

现在我希望age传过来的值自动加1。可能会写下面的代码,但这样是错误的。结果如下,会变成两个字符串的相加。

<!--1.定义子组件模板-->
<template id="studentInfo">
    <div>
        //some code
        <p>年龄:{{age+1}}</p>
        //some code
    </div>
</template>

在这里插入图片描述
其实非常的简单,我们只需要给age设为数据绑定就行了。这里涉及到数据绑定的一个小技巧。数据绑定后," "里面的内容变成了表达式而不是字符串,这样age内容在传输的时候就变成的Number类型。

 <student name="张三" :age="18" gender="男"></student>

一般情况下,传值的时候,我们是不会直接写的,而是通过data来传值。我们定义两个值。

    var app = new Vue({
        el: "#box",
        data: {
            message:"你叫什么名字",
            age:25
        },
        methods: {}
    })

将这两个值通过数据绑定绑定上。

<student :msg="message" name="张三" :age="18" gender="男"></student>

我们没有定义msg属性,所以一定会报错,这时候还需要在props里面定义msg属性。

 props:["name","age","gender","msg"]

这样,我们的msg也传过来了。
在这里插入图片描述
如果你打开控制台,会发现报错了。虽然界面还是正常的。会告诉你下面的错误。因为现在是父组件传值,直接把下面的代码注释,写到props里面,并且赋默认值就行了。
在这里插入图片描述
data可以注释了。

      data(){
          return{
             // msg: "我是一个好学生"
          }
      }

给msg设默认值。

          msg:{
              type:String,
              default: "我是一个好学生"
          }

修改父组件传过来的值

现在添加两个按钮,对年龄++和–

<template id="studentInfo">
    <div>
        <p>{{msg}}</p>
        <p>姓名:{{name}}</p>
        <p>年龄:{{age}}</p>
        <p>性别:{{gender}}</p>
        <button @click="age++">+</button>
        <button @click="age--">-</button>
    </div>

</template>

功能是可以用的,但有下面的警告。大概意思就是避免修改父组件传过来的值,因为可能父子组件同时修改,会造成一些问题。
在这里插入图片描述
但我就需要实现这样的功能怎么办?可以考虑用一个中间变量缓冲一下。

     data(){
          return{
              myAge:this.age
          }
      }

然后对我们的中间变量进行操作就可以了。

        <p>年龄:{{myAge}}</p>
        <button @click="myAge++">+</button>
        <button @click="myAge--">-</button>

总结

props本身的含义就是属性。就是给子组件定义属性用的。子组件有了属性,父组件就可以直接给这些属性赋值。

Logo

前往低代码交流专区

更多推荐