20201020王杉
学习内容:
一、组件的生命周期:
在项目中,所有的js代码都是写在new vue的内部的,new vue 的外部不能写任何js代码。但是,有些是需要在页面加载完成后
-
什么是组件的生命周期?
答:一个组件加载过程中所经历的各个阶段
-
为什么要使用组件的生命周期?
答:在组件的加载过程中,我们可能会执行一些操作,就好像“当页面加载完成后,”,当我们希望在组件加载完成后的过程中,到某个阶段,自动执行一件事情的时候就是使用生命周期
-
组件的生命周期包含四个阶段:
①创建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() 方法,组件被销毁,但是页面的元素不会消失,只是不再更新
-
在这四个阶段前后,都会自动触发一个回调函数--钩子函数(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上销毁之后调用销毁之后调用
二、组件
-
什么是组件?
页面中一块拥有专属的html+css+js数据的可重用的页面独立区域 -
使用组件:
①定义组件(全局组件):Vue.component("组件名",{ //为了方便换行,这里使用模板字符串
//必须用唯一的父元素进行包裹
//每个组件其实都是一个微缩版的new Vue()
template:`<div> //唯一父元素
//组件的html片段,模板
</div>`
//data数据是在data的函数返回的
data(){
// 可以被反复调用
// 每次调用时会都新创建一个data对象
return { // 相当于new Vue 中的data
变量:变量值
}
},
//下面的和new Vue中书写一样
methods:{},
watch:{},
computed:{},
钩子函数(){},
...
})- 组件名推荐写法:todo-header,用横线分割多个单词,不推荐使用驼峰命名
- data:{count:1} 查看错误代码
- 自定义子组件中的data必须是一个函数,然后函数返回一个包含子组件模型数据的对象
- 在父组件模板汇总,必须只能有一个父级根元素(如果不加唯一父元素,报错:。。。)
- 组件最终会翻译为普通的html显示,html要定义在template中
- return 因为每个组件,为了避免在重用时,模型数据数相互影响,就要必须有自己专属的对象,而不是共用一个对象,只有通过函数,动态创建{},才能反复创建多个模型数据对象,分别服务于各自所属的组件
- new Vue() 是根组件
②页面中使用组件:
提示:组件其实就是一个可重用的自定义的html标签而已,组件名其实就是自定义标签名
<组件名></组件名>
原理:当new vue扫描页面时,如果发现了不认识的自定义html标签,就会到内存中,vue大家庭中查找自定义的组件,只要找到同名的组件,先用组件的template内容代替当前自定义标签的位置,为这个区域创建一个微缩的new vue对象副本,并创建一个当前组件专属的data对象副本,包含专属的变量。所以,此时这个小的组件区域,就拥有了专属的html和数据和一个微缩版的new vue 组件对象。
html模板写法(2种)
-
直接写在template属性中,问题,不符合内容与行为的分离原则,不便于编写和维护,同时无法利用IDE的html语法提示功能
-
写在一个单独的template元素中(强烈推荐)
提示:template来自html5标准,专门用于声明一段html模板片段,html5标准中,template默认就不显示(display:none),是专门给js准备的,用动态反复加载内容
①html中
<template id="xxx"> <唯一父元素>
组件的html片段
</唯一父元素>
</template>②
Vue.component("组件名",{ template:"选择器"
})三、组件化开发(重点&难点):
- 什么是组件化开发?
一个页面其实是由多个组件聚合而成的一个大型的页面。在代码层面上,一个组件一个可反复使用的自定义的标签。当我们拿到一个页面后,都是现将一个大的完整的页面划分为多个功能区域(组件),然后再由多人分工协作完成每个区域(组件)的开发,最后再拼接起来显示
- 为什么要使用组件化开发?
松耦合(一个功能出现问题,不会影响其他功能的使用),便于重用,便于大项目的维护,便于协作开发
- 什么时候使用组件化开发?
所有页面,都是由多个组件组合而成的,凡是重用的,必须先定义组件,再来重复使用,开发使用的就是组件化开发
- 面向组件式的开发
一个页面,都是由多块区域,多级组件组成的,当拿到一个网页后,先划分区域,每个区域,包括其子区域,都可以做成一个独立的组件,每个区域都有专属的数据、html元素、css样式
a. 拿到页面后先划分组件区域,从上到下,从左到右,从外到内的原则,按区域划分,按是否重用划分
b. 为每个组件创建独立的组件文件(.js,开发都是.vue),其中就包含组件的html和js
c. 在主页面或父组件中,使用<组件名>引入子组件到页面或父组件中
- 自定义组件(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
-
创建全局空的Vue实例:bus
var bus=new Vue();
-
发送者:
可以再任意时候,触发bus上的自定义事件
bus.$emit("自定义的事件",this.数据)
3.接受者
提示:在bus上绑定自定义事件,并提供处理函数
Vue.component("...",{ ...,
mounted(){
bus.$on("自定义事件",(参数)=>{
// 必须使用箭头函数:内外this一致,公用
// 要求this指向的是当前组件对象
// 参数:得到兄弟传来的值
})
}
})
近期评论