接上篇《13.使用Axios、fetchJsonp请求数据》
上一篇我们主要讲解了如何使用使用Axios、fetchJsonp请求网络数据,本篇我们来讲解Vue中父组件如何将值、方法、实例传给子组件。
本系列博文使用的Vue版本:2.6.11
一、什么是父子组件?传值的意义
之前几篇博文中,有一篇是讲解如何使用Vue组件的,而且编写了一个根组件以及挂载的首页组件和新闻组件,结构如下:
这里的根组件,相对其下面挂载的组件,它就是父组件,而对于根组件,下面挂载的其它组件就是它的子组件,即父子组件就是挂载和被挂载的关系。
那么我们为什么要了解父子组件传值的机制呢?这是因为有很多场景是需要父子组件之间进行值的传递的。例如“首页组件”里面引入一个“头部组件”,同时“新闻组件”也引入一个“头部组件”,要求“头部组件”要按照页面类型的不同,分别显示“首页”和“新闻”,此时就需要父组件给子组件传值,来控制子组件的显示效果:
或者是页面中有一个购物车的组件,在主页面选择商品,就要更新购物车组件中的数量等等场景。
二、父子组件如何传值?
我们找到之前学习组件那一篇的代码,分别是“根组件”App.vue、“首页组件”HelloWorld.vue、“新闻组件”News.vue、“头部组件”Header.vue:
代码分别为:
App.vue:
<template>
<!-- vue的模板里面,所有的内容都需要被一个根节点包裹起来 -->
<div id="app">
<h2>{{msg}}</h2>
<v-hello></v-hello>
<br/><hr/>
<v-news></v-news>
</div>
</template>
<script>
/**1、import引入组件
* 2、在components中挂载组建
* 3、在template模板中使用组件
*
* 生命周期函数:组件挂载以及组件更新、销毁的时候触发的一系列的方法
*/
import Hello from './components/HelloWorld.vue'
import News from './components/News.vue'
export default {
name: 'app',
data () {
return {
msg: '你好,vue'
}
},
components:{
'v-hello':Hello,
'v-news':News
}
}
</script>
<style>
</style>
HelloWorld.vue:
<template>
<!-- 所有的内容要被根节点包含起来 -->
<div class="hello">
<v-header></v-header>
<h1>{{ msg }}</h1>
<button @click="run()">执行run方法</button>
</div>
</template>
<script>
import Header from './Header.vue';
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
methods:{
run(){
alert(this.msg);
}
},
components:{
'v-header':Header
}
}
</script>
<!-- 添加 "scoped" 属性来限制里面css样式只能被该组件引用 -->
<style scoped>
h1{
color:red;
}
</style>
News.vue:
<template>
<div class="News">
<v-header></v-header>
<h1>新闻组件</h1>
<ul>
<li>111111</li>
<li>222222</li>
<li>333333</li>
</ul>
</div>
</template>
<script>
import Header from './Header.vue';
export default {
name: 'News',
components:{
'v-header':Header
}
}
</script>
<style scoped>
</style>
Header.vue:
<template>
<!-- 所有的内容要被根节点包含起来 -->
<div class="header">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'header',
data () {
return {
msg: '头部组件'
}
}
}
</script>
<!-- 添加 "scoped" 属性来限制里面css样式只能被该组件引用 -->
<style scoped>
.header{
background-color: #000;
}
h1{
color:#fff;
}
</style>
启动项目之后,我们可以看到父页面的效果:
此时我们可以看到引入了头部组件的首页和新闻页,他们的区域都显示了“头部组件”的内容。我们下面用这个架构,分别实现父子组件传值、传方法和传实例的效果。
1、父组件传值给子组件
此时我们需要实现前面说的效果,即在首页和新闻页中的头部组件中分别显示不同的内容,即要首页和新闻页这两个父组件,向子组件头部组件传值。
父子组件传值分为两步:
(1)调用子组件时,为其绑定一个属性。
这里我们分别在HelloWorld.vue和News.vue组件中,调用<v-header>时,为其绑定名为titile的属性,并且在自己的data区域内声明这个属性值:
(2)在子组件中,在props参数中接收父组件传过来的数据。
然后我们在头部组件中,在script区域中,声明props参数,将父组件绑定的值的名称声明进来,然后在上面直接双花括号“{{title}}”取值即可:
然后我们就可以看到效果:
注意:如果子组件自己有个title属性,会被同名的父组件title覆盖,在开发中为了避免混淆,子组件的属性名称不要与父组件的名称相同。
2、父组件传方法给子组件
我们在父组件(Helloworld.vue)中定义一个run方法,将它传递到子组件。
父子组件传方法与传值基本一样,分为两步:
(1)调用子组件时,为其绑定一个属性,属性名为父组件的方法名。
我们将Helloworld.vue的run方法绑定到<v-header>上:
(2)在子组件中,在props参数中接收父组件传过来的方法名。
我们在props参数设置父组件的方法名,然后编写一个button调用它:
点击这个按钮,可以看到成功接收到父组件的方法:
3、父组件传实例给子组件
可以将父组件this作为一个实例,直接传递给子组件。方法也是一样的,分两步:
(1)调用子组件时,为其绑定一个属性,属性名为组件实例(this)。
我们将Helloworld.vue本身(this)方法绑定到<v-header>上:
<v-header :title="title" :run="run" :hello="this"></v-header>
(2)在子组件中,在props参数中接收父组件传过来的实例名。
我们在props参数设置父组件的实例名,然后直接可以调用这个实例的任何东西(参数或方法):
<template>
<!-- 所有的内容要被根节点包含起来 -->
<div class="header">
<h1>{{ title }}</h1>
<button @click="run()">执行父组件的方法</button>
<button @click="getParent()">使用父组件实例获取数据</button>
</div>
</template>
<script>
export default {
name: 'header',
data () {
return {
msg: '头部组件'
}
},
methods:{
getParent(){
alert("父组件msg的值:"+this.hello.msg);//获取父组件的值
this.hello.run();//调用父组件的方法
}
},
props:['title','run','hello']
}
</script>
<!-- 添加 "scoped" 属性来限制里面css样式只能被该组件引用 -->
<style scoped>
.header{
background-color: #000;
}
h1{
color:#fff;
}
</style>
效果:
4、验证父组件传给子组件的数据的合法性
我们为了区分父组件传递的值(不同的数据类型)、方法和实例,需要定义其数据类型,保证传递参数格式的正确性,做法就是制定props中所有参数的类型:
这里值可以定义基本数据类型(String、Number等),方法(Function )和实例(Object),如果相应的参数类型不一样,会在父组件加载时报错,声明类型错误:
props:{
'title':String,
'run':Function,
'hello':Object
}
也可以设置“默认值”和“是否强制需要该参数”,使用“default”和“required”指定即可:
props:{
'title':{
type:String,
default:'头部组件',
required:true
},
'run':Function,
'hello':Object
}
三、总结
父组件给子组件传值、方法和实例步骤:
(1)调用子组件时,为其绑定一个属性,属性名为值、方法和实例名。
(2)在子组件中,在props参数中接收父组件传过来的值、方法和实例名。
参考:
《IT营:itying.com-2018年Vue2.x 5小时入门视频教程》