20201020王杉

学习内容:

一、组件的生命周期:

在项目中,所有的js代码都是写在new vue的内部的,new vue 的外部不能写任何js代码。但是,有些是需要在页面加载完成后

  1. 什么是组件的生命周期?

    答:一个组件加载过程中所经历的各个阶段

  2. 为什么要使用组件的生命周期?

    答:在组件的加载过程中,我们可能会执行一些操作,就好像“当页面加载完成后,”,当我们希望在组件加载完成后的过程中,到某个阶段,自动执行一件事情的时候就是使用生命周期

  3. 组件的生命周期包含四个阶段:

    ①创建create(对象)–必经阶段

    a.创建完成new Vue对象,但是尚未挂载到DOM树上,此时\(el:undefined(this.\)el)$el:指的是new vue对象中的el

    b.引入创建data对象,同时请保镖–可以操作data中的变量,可以ajax请求并初始化数据

    c.引入methods中的函数–可以调用methods中的函数

    d.暂时不会扫描DOM树,生成虚拟DOM树,暂时不会进行DOM操作

    ②挂载mount(页面内容)–必经阶段

    a.扫描真实的DOM树,生成虚拟的DOM树,组件会挂载到DOM树上,组件首次加载完成,此时的$el: 中就有了DOM元素

    b. 首次加载数据到页面中显示

    c. 可以执行DOM操作

    ③更新update–只有当data中的数据被改变的时候触发组件所绑定的model数据发生了变化,需要更新视图

    ④销毁 destroy–只有主动调用\(destroy() 销毁当前new Vue时才触发调用了\)destroy() 方法,组件被销毁,但是页面的元素不会消失,只是不再更新

  4. 在这四个阶段前后,都会自动触发一个回调函数–钩子函数(8个)

    beforeCreate()

    实例创建之前自动调用–$el:undefined,data:undefined

    created() 对应创建阶段create

    实例创建完成自动调用–$el:undefined,data:{..}—可以进行获取或操作模型数据 — 进行ajax请求

    beforeMount()

    实例挂载到DOM树之前调用–$el:DOM对象,data:{…}

    mounted()

    实例才会被挂载到DOM上,$el:DOM对象,data:(…)对应挂载阶段mount此时既有data对象,又有虚拟DOM树,所有,开发中的ajax请求都要放在mounted()中才最保险

    beforeUpdate()

    实例中模型数据发生改变需要重新更新DOM之前调用

    updated()

    对应更新阶段 update,实例中的模型数据发生改变需要更新DOM之后调用

    注意:不要随意使用更新阶段,尽量少使用

    beforeDestroy()

    实例被从DOM上销毁之前调用

    destroyed()

    对应销毁阶段 destroy,实例被从DOM上 在这四个阶段前后,都会自动触发一个回调函数–钩子函数(8个)

    beforeCreate() 实例创建之前自动调用–$el:undefined,data:undefined

    created() 对应创建阶段create

    ​ 实例创建完成自动调用–$el:undefined,data:{..}—可以进行获取或操作模型数据 — 进行ajax请求

    beforeMount() 实例挂载到DOM树之前调用–$el:DOM对象,data:{…}

    mounted() 实例才会被挂载到DOM上,$el:DOM对象,data:(…)

    对应挂载阶段mount

    此时既有data对象,又有虚拟DOM树,所有,开发中的ajax请求都要放在mounted()中才最保险

    beforeUpdate() 实例中模型数据发生改变需要重新更新DOM之前调用

    updated() 对应更新阶段 update,实例中的模型数据发生改变需要更新DOM之后调用

    注意:不要随意使用更新阶段,尽量少使用

    beforeDestroy() 实例被从DOM上销毁之前调用

    destroyed() 对应销毁阶段 destroy,实例被从DOM上销毁之后调用销毁之后调用

二、组件

  1. 什么是组件?
    页面中一块拥有专属的html+css+js数据的可重用的页面独立区域

  2. 使用组件:
    ①定义组件(全局组件):

    Vue.component("组件名",{
    //为了方便换行,这里使用模板字符串
    //必须用唯一的父元素进行包裹
    //每个组件其实都是一个微缩版的new Vue()
    template:`<div> //唯一父元素
    //组件的html片段,模板
    </div>`
    //data数据是在data的函数返回的
    data(){
    // 可以被反复调用
    // 每次调用时会都新创建一个data对象
    return { // 相当于new Vue 中的data
    变量:变量值
    }
    },
    //下面的和new Vue中书写一样
    methods:{},
    watch:{},
    computed:{},
    钩子函数(){},
    ...
    })
    1. 组件名推荐写法:todo-header,用横线分割多个单词,不推荐使用驼峰命名
    2. data:{count:1} 查看错误代码
    3. 自定义子组件中的data必须是一个函数,然后函数返回一个包含子组件模型数据的对象
    4. 在父组件模板汇总,必须只能有一个父级根元素(如果不加唯一父元素,报错:。。。)
    5. 组件最终会翻译为普通的html显示,html要定义在template中
    6. return 因为每个组件,为了避免在重用时,模型数据数相互影响,就要必须有自己专属的对象,而不是共用一个对象,只有通过函数,动态创建{},才能反复创建多个模型数据对象,分别服务于各自所属的组件
    7. new Vue() 是根组件

    ②页面中使用组件:

    提示:组件其实就是一个可重用的自定义的html标签而已,组件名其实就是自定义标签名

    <组件名></组件名>

    原理:当new vue扫描页面时,如果发现了不认识的自定义html标签,就会到内存中,vue大家庭中查找自定义的组件,只要找到同名的组件,先用组件的template内容代替当前自定义标签的位置,为这个区域创建一个微缩的new vue对象副本,并创建一个当前组件专属的data对象副本,包含专属的变量。所以,此时这个小的组件区域,就拥有了专属的html和数据和一个微缩版的new vue 组件对象。

    html模板写法(2种)

    1. 直接写在template属性中,问题,不符合内容与行为的分离原则,不便于编写和维护,同时无法利用IDE的html语法提示功能

    2. 写在一个单独的template元素中(强烈推荐)

    提示:template来自html5标准,专门用于声明一段html模板片段,html5标准中,template默认就不显示(display:none),是专门给js准备的,用动态反复加载内容

    ①html中

    <template id="xxx">
        <唯一父元素>
    组件的html片段
    </唯一父元素>
    </template>

    Vue.component("组件名",{
     template:"选择器"
    })

    三、组件化开发(重点&难点):

    1. 什么是组件化开发?

    一个页面其实是由多个组件聚合而成的一个大型的页面。在代码层面上,一个组件一个可反复使用的自定义的标签。当我们拿到一个页面后,都是现将一个大的完整的页面划分为多个功能区域(组件),然后再由多人分工协作完成每个区域(组件)的开发,最后再拼接起来显示

    1. 为什么要使用组件化开发?

    松耦合(一个功能出现问题,不会影响其他功能的使用),便于重用,便于大项目的维护,便于协作开发

    1. 什么时候使用组件化开发?

    所有页面,都是由多个组件组合而成的,凡是重用的,必须先定义组件,再来重复使用,开发使用的就是组件化开发

    1. 面向组件式的开发

    一个页面,都是由多块区域,多级组件组成的,当拿到一个网页后,先划分区域,每个区域,包括其子区域,都可以做成一个独立的组件,每个区域都有专属的数据、html元素、css样式

    a. 拿到页面后先划分组件区域,从上到下,从左到右,从外到内的原则,按区域划分,按是否重用划分

    b. 为每个组件创建独立的组件文件(.js,开发都是.vue),其中就包含组件的html和js

    c. 在主页面或父组件中,使用<组件名>引入子组件到页面或父组件中

    1. 自定义组件(2种)

    ①全局组件:可以再页面中任何一部分使用组件

    ②局部组件:只能用于特定的父组件内的组件,也称为子组件

    A.创建子组件对象

    var 子组件对象名={
     template:`html片段`,
    data(){return {...}},
    ...
    }

    注意:

    a 子组件对象就是一个很普通的js对象

    b 要求对象的内容和vue组件规定一致

    c 对象名暂时使用驼峰命名,不要用-

    B.在父组件中添加components成员,其中包含当前父组件下的所有子对象的对象名

    父组件对象:{
     template:`html片段`,
    data(){return {...}},
    ...,
    components:{
    子组件对象名,....,....
    }
    }

    a. 子组件文件,就必须在父组件之前引入

    b. components会自动将js中驼峰命名的子组件对象名,翻译为 – 分割的子组件标签名,所以将来依然是在js中用驼峰,在html中用-。之间的差异由components自动翻译

    C.将子组件对象添加到父组件中,在父组件的template中使用<子组件标签名/>引入子组件内容

    父组件对象:{

    template:... <子组件对象名/> ...,

    data(){return {…}},

    …,

    components:{

    ​ 子组件对象名,….,….

    }

    }

    注意:vue中的组件分为三大类(全局组件、局部组件、根组件)

    组件的嵌套:子组件中,也可以包含components属性

    \6. 组件间的通信/数据传递(难点)

    问题:待办事项列表两大部分功能

    a. 添加区域,负责向待办事项列表添加一个新的任务;

    b. 列表区域,负责显示出待办事项列表中的内容;

    也就是说,todADD和todoList两个组件都需要用到同一个待办事项列表(数组)

    解决:将共用的数组保存到父组件中一份,方便所有的子组件来使用

    问题:vue中子组件不能直接使用父组件内的数据,因为每个组件的数据都是专属的,不是共享的

    解决:vue中组件间的传值

    ①父子间传值

    a. 父传子

    父组件(用绑定属性值的方式)

    父组件:{
     template:`
    ...
    <子组件标签 :自定义的属性名="父组件的数据"></子组件标签>
    `
    }
    子组件(孩子从父组件放数据的位置取出数据)
    子组件对象:{
    template:``,
    ...
    props:["自定义属性名"]
    }

    提示:props中的自定义属性名用法和data中的自己的变量是一样的,data中的变量怎么用,props中的自定义属性就怎么用

    1.在子组件的template的html内,可直接在指令或绑定语法中用“自定义的属性名”来使用父组件传来的数据

    2.子组件对象js内,任何位置都可以用“this.自定义属性名”使用父组件传来的数据

    b. 子传父

    子组件:

    js中,任何使用:

    this.$emit("父组件自定义的事件名",this.数据)

    父组件:

    父组件对象:{
     template:`
    ​ <子组件标签 @自定义事件=“父组件的处理函数”></子组件标签>
    ​ ...
    `,
    methods:{
    父组件的处理函数(参数){
    参数包含子组件触发事件($emit)时,传递过来的数据
    }
    }
    }

    ②兄弟间传值

    提示:数据总线机制 bus,vuex

    1. 创建全局空的Vue实例:bus

      var bus=new Vue();

    2. 发送者:

    可以再任意时候,触发bus上的自定义事件

    bus.$emit("自定义的事件",this.数据)

    3.接受者

    提示:在bus上绑定自定义事件,并提供处理函数

    Vue.component("...",{
     ...,
    mounted(){
    bus.$on("自定义事件",(参数)=>{
    ​ // 必须使用箭头函数:内外this一致,公用
    ​ // 要求this指向的是当前组件对象
    ​ // 参数:得到兄弟传来的值
    })
    }
    })

标签

评论

this is is footer