Vue学习--Day10

前言

组件是Vue.js最核心的功能,在前端应用中可以采用模块化的开发,实现可重用、可扩展。
组件是带有名字的可复用的Vue实例,因此在根Vue实例中的各个选项在组件中也一样可以使用,唯一的例外是el选项,这是只用于根实例的特有选项。

在这里插入图片描述

一、注册组件的基本步骤

  • 组件的使用分成三个步骤:

1.创建组件构造器 调用Vue.extend()方法创建组件构造器
2.注册组件 调用Vue.component()方法注册组件
3.使用组件 在Vue实例的作用范围内使用组件

例:

<div id="hey">

  <my-cpn></my-cpn>

</div>
<script src="../vue.js"></script>
<script>
  //1.创建组件构造器对象
  const cpnC = Vue.extend({
    template: `
        <div>
          <h2>我是你</h2>
          <p>谢谢</p>
        </div>
    `
  })
  //2.注册组件
  Vue.component('my-cpn',cpnC)



  const app = new Vue({
    el: '#hey',
    data: {
      message: '你好啊!'
    },
  })
</script>

在这里插入图片描述

二、全局组件和局部组件

  • 全局组件使用Vue.component()方法来注册,该方法接受两个参数,第一个参数是组件的ID(即名字),第二个参数是一个函数对象(使用Vue.extend()方法创建的组件构造器),也可以是一个选项对象

Vue.component ( id , [definition] )
案例:略,同上

  • 局部组件是在Vue实例的选项对象中使用component选项来注册。

案例:


<div id="hey">

  <my-cpn></my-cpn>

</div>
<script src="../../vue.js"></script>
<script>
  //1.创建组件构造器对象
  const cpnC = Vue.extend({
    template: `
        <div>
          <h2>我是你</h2>
          <p>谢谢</p>
        </div>
    `
  })

  const app = new Vue({
    el: '#hey',
    data: {
      message: '你好啊!'
    },
    components:{
      'my-cpn': cpnC
    }
  })
</script>

在这里插入图片描述

三、父组件与子组件

<div id="hey">
  <cpn2></cpn2>
<!--  不能使用<cpn1></cpn1>-->

</div>
<script src="../../vue.js"></script>
<script>
  //1.创建第一个组件构造器(子组件)
  const cpnC1 = Vue.extend({
    template: `
        <div>
          <h2>我是你</h2>
          <p>谢谢</p>
        </div>
    `
  })
  //2创建第二个组件构造器(父组件)
  const cpnC2 = Vue.extend({
    template:`
      <div>
      <h2>我是他</h2>
      <p>不客气</p>
      <cpn1></cpn1>
      </div>
      `,
    components:{
      cpn1:cpnC1
    }
  })
  //根组件
  const app = new Vue({
    el: '#hey',
    data: {
      message: '你好啊!'
    },
    components:{
      cpn2: cpnC2
    }
  })
</script>

在这里插入图片描述
在这里插入图片描述

四、注册组件语法糖

  • Vue为了简化注册组件的过程,提供了注册的语法糖
  • 主要是省去了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替
//1.创建组件构造器对象
  const cpnC = Vue.extend({
    template: `
        <div>
          <h2>我是你</h2>
          <p>谢谢</p>
        </div>
    `
  })

  const app = new Vue({
    el: '#hey',
    data: {
      message: '你好啊!'
    },
    components:{
      'my-cpn': cpnC
    }
  })
//语法糖形式
  //1.全局组件
  Vue.component('cpn1',{
    template:`
    <div>
          <h2>我是你</h2>
          <p>谢谢</p>
     </div>`
  })

  //2.局部组件
  const app= new Vue({
    el: '#hey',
    data: {
      message: '你好啊!'
    },
    components:{
      'my-cpn': {
        template:`
      <div>
          <h2>我是他</h2>
          <p>不客气</p>
     </div>`

      }
    }
  })

五、组件模板抽离方法

  • 将template模板中的html分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰。
  • Vue提供了两种方案来定义html模块内容:

    使用

<body>
<div id="app">
  <cpn1></cpn1>
  <cpn2></cpn2>
</div>
<!--组件模板抽离的第一种写法-->
<script type="text/x-template" id="cpn1">
  <div>
    <h2>我是你</h2>
    <p>谢谢</p>
  </div>
</script>

<!--第二种写法:template标签-->
<template id="cpn2">
  <div>
    <h2>我是他</h2>
    <p>不客气</p>
  </div>
</template>
<script src="../../vue.js"></script>
<script>
  // 注册组件:第一种模板抽离写法
  Vue.component('cpn1',{
    template: '#cpn1'
  })
  // 注册组件:第二种模板抽离写法
  Vue.component('cpn2',{
    template: '#cpn2'
  })
  const app = new Vue({
    el: '#app',
    data: {
      msg: '欢迎使用Vue.js'
    }
  })
</script>

在这里插入图片描述

六、组件data必须是函数

  • 这是因为组件是可复用的Vue实例,如果还是允许使用先前根实例的数据定义方式,那么所有复用的组件实例都将共享同一份数据,显然这很容易导致混乱。
  • 采用函数定义方式,那么每个组件实例都将拥有自己的一份返回对象的独立拷贝,每复用一次组件,data函数就执行一次,从而返回一个新的数据对象。
<div id="app">
  <cpn></cpn>
</div>


<template id="cpn">
  <div>
    <h2>当前计数:{{counter}}</h2>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>
<script src="../../vue.js"></script>
<script>
  // 注册组件:第一种模板抽离写法
  Vue.component('cpn',{
    template: '#cpn',
    data(){
      return {
        counter:0
      }
    },
    methods:{
      increment() {
        this.counter++
      },

      decrement() {
        this.counter--
      }
    }
  })

  const app = new Vue({
    el: '#app',
    data: {
      msg: '欢迎使用Vue.js'
    }
  })
</script>

在这里插入图片描述

七、使用prop向子组件传递数据

  • 给组件元素设置属性,组件内部如何接收呢?

    首先需要在组件内部注册一些自定义的属性,成为prop,这些prop是放在组建的props选项中定义的;
    之后在使用组件时,就可以把这些prop的名字作为元素的属性名来使用,通过属性向组件传递数据,这些数据将作为组件实例的属性被使用。

<div id="app">
  <cpn :cmovies="movies" :cmessage="message"></cpn>
</div>


<template id="cpn">
  <div>
    <p>{{cmovies}}</p>
    <h2>{{cmessage}}</h2>
  </div>
</template>
<script src="../../vue.js"></script>
<script>
  // 注册组件:第一种模板抽离写法
  Vue.component('cpn',{
    template: '#cpn',
    props:['cmovies','cmessage'],
    data(){
      return {
      }
    }
  })

  const app = new Vue({
    el: '#app',
    data: {
      message:'你好啊',
      movies:['海王','你好,李焕英','唐人街探案']
    }
  })
</script>

在这里插入图片描述

八、prop验证

Vue.component('my-component', {
  props: {
    // 基础类型检测 (`null`和‘undefined’会通过任何类型验证)
   age: Number,
    // 多种类型
    tell: [String, Number],
    // 必传且是字符串
    username: {
      type: String,
      required: true
    },
    // 数字,有默认值
    sizeOfPage: {
      type: Number,
      default: 100
    },
    // 数组/对象的默认值应当由一个工厂函数返回
    greeting: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    info: {
      validator: function (value) {
        return value > 10
      }
    }
  }
})

当prop验证失败了,如果使用的是开发版本会抛出一条警告。

type可以是下面的原生构造器:

  • String
  • Number
  • Boolean
  • Function
  • Object
  • Array

type也可以是一个自定义构造器,使用instanceof检测。

九、驼峰标识

  • HTML中的属性名是不区分大小的,浏览器在加载HTML页面的时候,会统一转换为小写字母,采用camelCase(驼峰命名法)的prop名要使用其等价的kebab-case(短横线命名)名字来使用。如果在字符串模板中或单文件组件内使用,则没有这个使用。

十、监听子组件事件(子传父)

  • 在Vue.js中,通过自定义事件来实现子组件的某些功能和父组件通信。
  • 子组件使用$emit()方法触发事件,负组件使用v-on指令监听子组件的自定义事件。
  • $emit()方法的语法形式如下:

    vm.$emit(eventName,[…args])
    eventName是事件名,args是附加参数,这些参数会传给监听器的回调函数。如果子组件需要向父组件传递数据,就可以通过第二个参数来传。


<!--父组件模板-->
<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="../../vue.js"></script>
<script>
  //1.子组件
  const cpn={
    template:'#cpn',
    data(){
      return{
        categories:[
          {id:'aaa',name: '热门推荐'},
          {id:'bbb',name: '手机数码'},
          {id:'ccc',name: '家用家电'},
          {id:'ddd',name: '电脑办公'},
        ]
      }
    },
    methods:{
      btnClick(item){
        this.$emit('item-click',item)
      }

    }
  }

  //2.父组件
  const app = new Vue({
    el: '#app',
    data: {
      message:'你好啊',

    },
    components:{
      cpn
    },
    methods:{
        cpnClick(item){
          console.log('cpnClick',item);
        }
    }
  })
</script>

在这里插入图片描述
参考:
https://www.bilibili.com/video/BV15741177Eh?p=59
https://book.douban.com/subject/35019549/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值