Vue.js学习笔记——11.组件化开发(二)

目录

  • 六、父子组件的通信
    • 1.父传子——props
    • 2.子传父——自定义事件
  • 七、父子组件的访问方式
    • 1.父访问子——$children
    • 2.父访问子——$refs
    • 3.子访问父——`$parent`与`$root`

Vue.js学习笔记——10.组件化开发(一)
Vue.js学习笔记——12.组件化开发(三)

六、父子组件的通信

1.父传子——props

在实际开发中,我们从服务器请求到了很多数据,并不是在整个页面的大组件来展示的,而是需要下面的子组件进行展示,这时不会让子组件再次发生一个网络请求,而是直接让父组件将数据传递给子组件。父组件向子组件传递数据有两种方式:一是通过props;二是通过事件。

在组件中,使用选项props来声明需要从父级接收到的数据,有两种方式:

  1. 字符串数组,数组中的字符串就是传递时的名称;
  2. 对象,对象可以设置传递时的类型,也可以设置默认值等;
    篇幅有限,这里只说明常用的对象方式。

由于Vue实例可以看作所有组件的根组件,Vue实例的数据要传入子组件时,在注册时往props传入一个对象,然后在使用时用v-bind将props中的属性和data中的数据绑定即可实现传值。
举例:


<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
head>
<body>
<div id="app">
  
  <cpn :cmovies="movies" :cmessage="message">cpn>
div>


<template id="cpn">
  <div>
    <ul>
      <li v-for="item in cmovies">{
    {item}}li>
    ul>
    <p>{
    {cmessage}}p>
  div>
template>

<script src="../js/vue.js">script>
<script>
  // 注册全局组件
  Vue.component(`cpn`,{
      
    template:`#cpn`,
    props:{
      
    //指定类型
      cmessage:String,
      cmovies:Array
    }
  })

  const app = new Vue({
      
    el:"#app",
    data:{
      
      message:`你好啊`,
      movies:[`海王`,`海贼王`,`海尔兄弟`]
    }
  })
script>
body>
html>

执行结果:
Vue.js学习笔记——11.组件化开发(二)_第1张图片
指定类型支持以下类型:

  1. String
  2. Number
  3. Boolean
  4. Array
  5. Object
  6. Date
  7. Function
  8. Symbol

除了指定类型,还可以设置默认值或是否必填等:

Vue.component(`cpn`,{
     
    template:`#cpn`,
    props:{
     
      // 基础的类型检查('null'匹配任何类型)
      propA:Number, 
      // 多个可能的类型
      propB:[String,Number], 
      //  必填的字符串
      propC:{
     
        type:String,
        required:true
      }, 
      //  带默认值的数字
      propD:{
     
        type: Number,
        default:100
      },
      //  带有默认值的对象
      propE:{
     
        type:Object,
        // 对象或数组默认值必须从一个工厂函数获取
        default: function () {
     
          return {
     message: `hello`}
        }
      },
      // 自定义验证函数
      propF:{
     
        validator:function (value) {
     
         // 这个值必须匹配下列字符串中的一个
          return [`success`,`warning`,`danger`].indexOf(value) !== -1
        }
      }
    }
 })

需要注意的是v-bind中不支持驼峰语法,如需绑定propA或childMyMessage这样命名的属性就要在绑定时写成用-连接:

2.子传父——自定义事件

当子组件有数据传递到父组件时,需要通过自定义事件来实现。v-on不仅可以用于监听DOM事件,还可以用于组件间的自定义事件。
自定义事件的流程:

  1. 在子组件中,通过$emit()来触发事件;
  2. 在父组件中,通过v-on来监听子组件事件;

举例:


<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
head>
<body>

<div id="app">

  <cpn @item-click="cpnClick">cpn>
div>


<template id="cpn">
  <div>
  
    <button v-for="item in categories" @click="btnClick(item)">{
    {item.name}}button>
  div>
template>

<script src="../js/vue.js">script>
<script>
  // 注册全局组件
  Vue.component(`cpn`,{
      
    template:`#cpn`,
    data(){
      
      return {
      
        categories: [
          {
      id: `aaa`, name: `热门推荐`},
          {
      id: `bbb`, name: `家电家器`},
          {
      id: `ccc`, name: `手机数码`},
        ]
      }
    },
    methods:{
      
      btnClick(item){
      
        //发射事件$emit(发射事件名,发射参数)
        this.$emit(`item-click`,item)
      }
    }
  })

  const app = new Vue({
      
    el:"#app",
    data:{
      

    },
    methods:{
      
      cpnClick(item){
      
        console.log(item.name);
      }
    }
  })
script>
body>
html>

执行结果:
Vue.js学习笔记——11.组件化开发(二)_第2张图片
原本methods需要有参数而监听时没有加括号,就会默认传入事件参数,而在这里因为监听的是组件的自定义事件,所以会默认传一个自定义事件中btnClick(item){this.$emit(‘item-click’,item)}发射的参数即item。
还需要注意我这个版本的Vue的v-on所监听的事件名(即此处:@item-click)好像也不支持驼峰语法,写了驼峰会报错,例子中我都给改成了横杠连接。

七、父子组件的访问方式

有时我们父子之间并不需要传递数据,可能只是想访问父组件或者子组件的对象进行一些操作,这就需要用到:

  1. 父组件访问子组件:使用$children$refs
  2. 子组件访问父组件:使用$parent

1.父访问子——$children

this.$children是一个数组类型,它包含所有子组件对象,先来看看组件对象内有什么。
举例:


<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
head>
<body>
<div id="app">
  
  <cpn>cpn>
  <cpn>cpn>
  <cpn>cpn>
  <button @click="btnClick">按钮button>
div>


<template id="cpn">
  <div>
    {
    {message}}
  div>
template>

<script src="../js/vue.js">script>
<script>
  const app = new Vue({
      
    el:"#app",
    data:{
      

    },
    methods:{
      
      btnClick(){
      
        console.log(this.$children);
      }
    },
    components:{
      
      cpn:{
      
        template:`#cpn`,
        data(){
      
          return {
      
            message:`我是子组件的message`
          }
        },
        methods:{
      
          showMessage(){
      
            console.log(`我是子组件的方法`);
          }
        }
      }
    }
  })
script>
body>
html>

执行结果:
Vue.js学习笔记——11.组件化开发(二)_第3张图片
点击按钮打印组件对象可以看到有3个子组件对象,每一个对象内包括很多属性,也包括子组件data中的message和methods里的方法,那么就可以通过访问对象属性的方法来访问子组件的属性了。
往btnClick()添加:

		console.log(this.$children[0].message);
        this.$children[1].showMessage();

执行结果:
Vue.js学习笔记——11.组件化开发(二)_第4张图片
即可访问this.$children数组中,0号子组件对象的message和1号子组件对象的showMessage()。

2.父访问子——$refs

通过this.$children数组访问子组件时,一旦之后添加了组件,数组内的顺序就可能发生改变,使得想固定访问某个组件变得困难,这时就需要使用this.$refs
this.$refs数组内默认是没有任何东西的,需要在使用组件时添加ref属性才会生效。
举例:


<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
head>
<body>
<div id="app">
  
  <cpn>cpn>
  <cpn ref="aaa">cpn>
  <cpn>cpn>
  <button @click="btnClick">按钮button>
div>


<template id="cpn">
  <div>
    {
    {message}}
  div>
template>

<script src="../js/vue.js">script>
<script>
  const app = new Vue({
      
    el:"#app",
    data:{
      

    },
    methods:{
      
      btnClick(){
      
        console.log(this.$refs);
        console.log(this.$refs.aaa);
        this.$refs.aaa.showMessage()
      }
    },
    components:{
      
      cpn:{
      
        template:`#cpn`,
        data(){
      
          return {
      
            message:`我是子组件的message`
          }
        },
        methods:{
      
          showMessage(){
      
            console.log(`我是子组件的方法`);
          }
        }
      }
    }
  })
script>
body>
html>

执行结果:
Vue.js学习笔记——11.组件化开发(二)_第5张图片
ref属性相当于给组件取了个名字,在this.$refs中取得的是一个对象,给对象取的名字就是key,value为它的组件对象,通过this.$refs.ref属性值访问组件对象在进行下一步访问。

3.子访问父——$parent$root

在子组件内想要访问父组件的元素,就要通过this.$parentthis.$rootthis.$parent是访问当前组件的父组件,this.$root是访问根组件,即访问Vue实例。
举例:


<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
head>
<body>
<div id="app">
  
  <cpn>cpn>
div>


<template id="cpn">
  <div>
    我是cpn组件
    <ccpn>ccpn>
  div>
template>

<template id="ccpn">
  <div>
    我是ccpn组件
    <button @click="btnClick">按钮button>
  div>
template>

<script src="../js/vue.js">script>
<script>
// 1.Vue实例
  const app = new Vue({
      
    el:"#app",
    data:{
      
      message:`你好啊`
    },
    //2.子组件
    components:{
      
      cpn:{
      
        template:`#cpn`,
        data(){
      
          return{
      
            message:`我是子组件的message`
          }
        },
        //3.子组件的子组件
        components:{
      
          ccpn:{
      
            template:`#ccpn`,
            methods:{
      
              btnClick(){
      
                console.log(this.$parent);
                console.log(this.$parent.message);
                console.log(this.$root);
                console.log(this.$root.message);
              }
            }
          }
        }
      }
    }
  })
script>
body>
html>

执行结果:
Vue.js学习笔记——11.组件化开发(二)_第6张图片
例子中在Vue实例内注册了cpn组件,有在cpn组件中注册了ccpn组件(禁止套娃! ) ,即ccpn的父组件是cpn,cpn组件的父组件是Vue实例。在ccpn中通过this.$parent访问到的是cpn的组件对象,通过this.$root访问到的是跟组件,即Vue实例。

Vue.js学习笔记——10.组件化开发(一)
Vue.js学习笔记——12.组件化开发(三)

你可能感兴趣的:(Vue.js学习笔记,vue.js)