【Vue学习总结】14.Vue父子组件数据传递

接上篇《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小时入门视频教程》

转载请注明出处:https://blog.csdn.net/acmman/article/details/109277210

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光仔December

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值