Vue.js 组件通信一 父组件向子组件传值——通过props
Prop 是你可以在组件上注册的一些自定义 attribute。这是官方给出的定义。简单点说,就是父组件给子组件传值的时候,把值直接传给子组件自己定义的属性。这些属性(property)是在子组件里面定义的,没错,prop就是property的缩写。相当于给父组件带名字的盒子,叫父组件往里面放数据就行。还是举个例子说明更清楚。我们定义一个子组件的模板,因为子组件是提供给父组件(通常就是顶层组件)用
组件通信概述
组件之间虽然有父子关系,但还是互相独立的。互相之间并不能直接操作对方的数据。这是出于安全性考虑的。组件之间是有通信需求的,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本身的含义就是属性。就是给子组件定义属性用的。子组件有了属性,父组件就可以直接给这些属性赋值。
更多推荐
所有评论(0)