Vue的组件系统

本文详细介绍了Vue的组件系统,包括组件的概念、注册与使用方式、组件通信、扩展以及组件的生命周期。重点讲解了Vue.extend()在组件实现中的作用,组件的命名规则,以及如何通过is属性解决父子级标签解析问题。此外,还阐述了组件通信的各种方法,如props、自定义事件、ref、事件总线和Vuex。最后,探讨了组件的生命周期,包括8个关键钩子函数及其应用场景。
摘要由CSDN通过智能技术生成
1.组件
  • Vue有两大核心内容

    • 指令
    • 组件
  • 什么是组件化【为什么要用组件?】

    • 为了避免多人开发造成的冲突
    • 为了加快开发效率
    • 为了便利更新和维护
    • 组件化:就是使用具有独立公共的一个整体(组件)来进行项目开发的趋势(流行)
  • 什么是组件?

    • 组件是一个html css js img 等的一个聚合体
    • 在Vue中使用了一个叫做单文件组件的技术来实现组件
      • 它是一个 xxx.vue 文件
      • 这个文件在浏览器中不能运行,必须经过编译(gulp webpack )才能运行
  • Vue里面是如何实现组件的?

    Vue.extend()

    1. 通过实例化Vue构造器函数得到一个Vue实例,这个实例我们称之为‘根实例’,它是最大的父级
    2. 这个根实例是以标签的形式存在的,那么我们也称之为‘根组件’
    3. 根实例也是一个组件,但是我们得到的只是根组件
    4. Vue.extend() 它就是对Vue功能的扩展,这个扩展就是组件
    5. Vue是通过Vue.extend() 来实现【扩展】Vue的功能的,这个功能就是组件
    6. 思考:Vue.extend() 如何使用?
      • 通过new Vue.extend() 发现和 new Vue 一样 —排除
      • 组件就是一个以标签化呈现的东西,所以应该像标签一样使用
      • 但是无论是 HTML3 还是 HTML5 肯定不会同意它随意使用标签的
      • Vue会将组件编译成 HTML 结构
      • Vue这个处理过程,我们就称之为‘组件注册’
      • 总结:
        • Vue是通过Vue.extend() 来实现组件的
        • Vue的组件使用时需要注册
  • Vue中是如何使用组件的?

    • 组建注册

      • 全局注册

        //Vue.component(组件的名称,组件的配置)
        const Hello = Vue.extend({
            template:'<div>Hello 组件</div>'
        })
        Vue.component('Hello',Hello)
        
        //简写
        Vue.componen('Hello',{
            template:'<div>Hello 组件</div>'
        })
        
      • 局部注册

        局部注册使用 components 选项来完成

        局部注册只在当前注册的实例范围内有效

        new Vue({
            el:'#app',
            components:{//局部注册组件的选项
                //组件的名称:组件的选项
                'Hello':{
                   template:'<div>Hello 这里是局部注册</div>' 
                }   
            }
        })
        
    • 组件的命名:一定要避免和原生标签冲突 ,如:Header header 就不可以

      • 大驼峰 HeadTitle

        使用

        <head-title></head-title>
        
      • 小写+横杠 head-title

        使用

        <head-title></head-title>
        
      • 一个单词 Hello

      ​ 使用

      <hello></hello>   
      //或者
      <Hello></Hello>//推荐     
      
    • 组件的使用规则

      • 组件在父子级是有直接关系的标签中是不能直接解析的,会出问题

      • 直接父子级关系的标签

        ul li
        ol li
        table tr  td
        dl dd dt
        select option
        
      • 如何解决这个问题

        使用 is 属性 来解决

        <div id="app">
           <table border="1">
               <tr>
               <td>1</td>
               <td>1</td>
               <td>1</td>
               </tr>
               <tr is = "Hello"></tr>
            </table>
        </div>
        
        Vue.component('Hello',{
            template:`
            <tr>
               <td>2</td>
               <td>2</td>
               <td>2</td>
             </tr>
        `
        })
        new Vue({
            el:"#app"
        })
        
    • 动态组件

      • 业务: 点击开关切换两个组件

      • template写在实例范围内,会被直接解析,并且将来不会在html结构中出现

      • template模板内直接子元素有且仅有一个

      • Vue提供了一个 component 组件

      • 通过keep-alive组件实现动态组件的缓存,加快组件的切换速度

        <div id="app">
            <button @click="typeChange">
                点击
            </button>
            <keep-alive>
            <component :is="type"></component>
            </keep-alive>
        </div>
        <template id="hello-box">
            <div>
                <h3>
                    手机号登录
                </h3>
                <input type="text" placeholder="请输入手机号"/>
            </div>
        </template>
        
        new Vue({
            el:'#app',
            data:{
                type:'PhoneLogin'
            },
            methods:{
                typeChange(){
                    this.type=(this.type === 'PhoneLogin') && 'UserLogin' || 'PhoneLogin'
                }
            },
            components:{
                'PhoneLogin':{
                    template:'#hello-box'
                },
                'UserLogin':{
                    template:'<div>用户名和密码登录</div>'
                }
            }
        })
        
2.组件通信
  • 组件的嵌套

    • 子组件以标签的形式要在父组件的模板中使用
  • 组件中数据的定义

    • 为什么组件中的data选项是一个函数,而根实例中是对象【面试】

      原因:

      1. 组件是一个独立的整体,那么数据也应该是一个独立的
      2. 多人开发,数据如果不是独立的,那么数据就会冲突
      3. javascript最大的特点:函数式编程,而函数本身就有一个独立作用域
    • 为什么组件中的data函数要有返回值,并且返回值是一个对象,不能是其他吗?

      原因:因为data选项要经过ES5 Object.defineProperty 属性进行getter和setter设置

    • 数据中数据的使用

      • 组建的数据,适用范围只能在组件的模板中
  • 组件通信

    • 父子组件通信

      1. 父组件中定义一个数据

      2. 在父组件的模板中,用v-bind将父组件的数据绑定在子组件身上

        <Son :aa="money"></Son> //aa属性为自定义
        
      3. 在子组件的选项中,通过props选项来接收这个属性

      4. 这个属性可以在子组件的模板中以全局变量的形式使

        <div id="app">
          <Father/>  
        </div>
        <!-- father 组件 start-->
        <template id="father">
        <div>
            <h3>
                这里是 父组件
            </h3>
            <hr/>
            <Son :aa="money"></Son>
        </div>
        </template>
        <!-- father 组件 end-->
        
        <!-- son 组件 start-->
        <template id="son">
        <div>
            <h4>
                这里是子组件
            </h4>
            <p>
                老爸每月给我 {{ aa }} 生活费
            </p>
            </div>
        </template>
        <!-- son 组件 end-->
        
        Vue.component('Father',{
            template:'#father',
            data(){
                return {
                    money:3000
                }
            }
        });
        Vue.component('Son',{
            template:'#son',
            props:['aa']
        })
        
      • Props选项
        • props属性验证
          • props可以是一个对象
          • props中的 validator 函数
          • props 第三方属性验证 :vue-validator-help
    • 子父组件通信

      • 自定义事件

        this.$emit
        
      • 子父通信流程

        //1.先在子组件中定义一个数据
        Vue.component('Son',{
            tempalte:'#son',
            data(){
                return {
                    money:1000
                }
            }
        });
        //2. 在父组件中也定义一个数据,这个数据用来接收子组件传递过来的数据
         Vue.component('Father',{
                    template: '#father',
                    data () {
                      return {
                        bank: 1000
                      }
                    }
                  })
        //3.在父组件中定义一个事件处理程序,用于改变父组件定义的数据,这个事件处理程序是有参数的,这个参数就是子组件传递过来的数据
        Vue.component('Father',{
            template:'#father',
            data(){
                return {
                    bank:1000
                }
            },
            methods:{
                bankAdd( val ){//val就是子组件给的数据
                    this.bank += val;
                }
            }
        });
        //4.将这事件处理程序用过事件绑定的形式绑定在子组件
        <Son @aa="bankapp></Son>
        //5.在子组件中定义一个事件处理程序,这事件处理程序中通过this.$emit触发自电子定义事件,并传递以参数
        Vue.component('Son',{
            template:'#son',
            data(){
                return {
                    money:1000
                }
            },
            methods:{
                give(){
                    this.$emit('aa',this,mone y)
                }
            }
        })
        
        <tempolate id="son">
        <div>
        <h4>
        这里是子组件
        </h4>
        <button @click="give" ></botton>
        </div>
        </template>
        
    • 非父子组件通信

      • ref

      • bus事件总线

    • 多组件状态共享

      • Vuex
3.扩展
  • 2.5 slot slot-scope
    • slot 具名插槽 (必须会)
    • slot-scope(了解)
  • 2.6 v-slot(必须会)
4.组件的生命周期【组建的钩子有哪些?】
  • 为什么要使用生命周期?

  • 我们想要使用组件,那么就得在组件的特定阶段完成特定的任务(特定时间点完成特定任务)

  • 名词–钩子:机遇

    • 特定时间点,触发一个方法
  • 组建的而生命周期分为三个阶段: 初始化 、运行中 、销毁

    8个钩子函数(熟练掌握)

    • 生命周期钩子不允许写成箭头函数,因为箭头函数会改变this指向

    • 初始化

      • beforeCreat () {}
        • 组件即将创建
        • 任务: 初始化事件,并且为整个生命周期的开始做准备 【举例:相亲–父母给你做准备和谋划】
        • 意义:
          • 数据未获取,真实DOM未拿到
          • 数据请求,数据修改
      • created () {}
        • 组件创建结束
        • 任务:进行数据的注入和数据的反应【举例:父母告诉你了让你相亲】
        • 意义:
          • 数据拿到了,真实DOM未拿到
          • 数据请求,数据修改
      • beforeMount () {}
        • 组件即将挂载
        • 任务:判断组件是否有el/template选项,如果有那么使用render函数将template模板中的jsx转换成VDOM对象模型,如果没有,需要我们使用$mount/outerHTML手动挂载 【举例:男女双方互加微信,聊天】
        • 意义:
          • 更多的是内部完成任务,我们外部就不干预了
          • 数据请求,数据修改
      • mounted () {}
        • 组件挂在结束
        • 任务: 将VDOM渲染为真实DOM,然后挂载到页面中,这个时候我们在页面中可以看到内容了 【举例:网络约见面】
        • 意义:
          • 操作真实DOM【可以进行第三方库实例化】
          • 数据请求,数据修改
      • 总结 :
        • 我们常将数据请求写在created中,因为created钩子是第一次获得数据的地方
        • mounted钩子函数可以进行DOM操作【第三方库实例化(静态数据)】
    • 运行中

      • beforUpdate 组件更新前
        • 触发条件:组件的数据发生改变
        • 任务 :VDOM重新生成,然后通过diff算法和以前的VDOM对比,生成patch补丁对象【内部进行】【举例:见面的结果】
      • updated 组件更新结束
        • 触发条件:组件的数据发生改变
        • 任务:将patch补丁对象进行渲染生成真实DOM 【举例:证明第一次相亲失败,换了一人】
        • 意义:
          • 可以操作DOM【第三方库的实例化(动态数据)】
      • 总结:平时大家使用updated进行第三方库实例化
    • 销毁

      • 意义: 用来完成善后工作【计时器,第三方库实例,window.onscroll】

      • 组件的销毁有两种形式

        • 内部销毁【举例: 你可以将这个信息告诉父亲 】

          $destroy

          • 组件会被销毁掉,但是组件的DOM外壳还在

          • 外部销毁 【举例:你父母得知相亲的结果是由别人告知的】

            • 通过开关销毁【推荐】
      • 组件的销毁会触发两个钩子函数【 没啥差别, 任意选择一个使用 】

        • beforDestroy () {} 销毁前
        • destroyed () {} 销毁结束
5.自定义过滤器
  • 注意点:

    • 是对已有数据进行格式化
    • 过滤器也可以传递参数
    • 过滤器要使用管道符才能起作用
      • 管道符 --回调函数中的返回值是什么,格式化后的数据就是什么
  • 分类

    • 全局过滤器

      Vue.filter(过滤器名称,回调函数)
      
    • 局部过滤器

    filters:{
        //过滤器名称:回调函数
        'dateFilter':(val,type) =>{//val就是要过滤的数据
            var date = new Date(val)
            return date.getFullYear()+type+(date.getMonth()+1)+type+date.getDate()
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值