1.组件
-
Vue有两大核心内容
- 指令
- 组件
-
什么是组件化【为什么要用组件?】
- 为了避免多人开发造成的冲突
- 为了加快开发效率
- 为了便利更新和维护
- 组件化:就是使用具有独立公共的一个整体(组件)来进行项目开发的趋势(流行)
-
什么是组件?
- 组件是一个html css js img 等的一个聚合体
- 在Vue中使用了一个叫做单文件组件的技术来实现组件
- 它是一个 xxx.vue 文件
- 这个文件在浏览器中不能运行,必须经过编译(gulp webpack )才能运行
-
Vue里面是如何实现组件的?
Vue.extend()
- 通过实例化Vue构造器函数得到一个Vue实例,这个实例我们称之为‘根实例’,它是最大的父级
- 这个根实例是以标签的形式存在的,那么我们也称之为‘根组件’
- 根实例也是一个组件,但是我们得到的只是根组件
- Vue.extend() 它就是对Vue功能的扩展,这个扩展就是组件
- Vue是通过Vue.extend() 来实现【扩展】Vue的功能的,这个功能就是组件
- 思考: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选项是一个函数,而根实例中是对象【面试】
原因:
- 组件是一个独立的整体,那么数据也应该是一个独立的
- 多人开发,数据如果不是独立的,那么数据就会冲突
- javascript最大的特点:函数式编程,而函数本身就有一个独立作用域
-
为什么组件中的data函数要有返回值,并且返回值是一个对象,不能是其他吗?
原因:因为data选项要经过ES5 Object.defineProperty 属性进行getter和setter设置
-
数据中数据的使用
- 组建的数据,适用范围只能在组件的模板中
-
-
组件通信
-
父子组件通信
-
父组件中定义一个数据
-
在父组件的模板中,用v-bind将父组件的数据绑定在子组件身上
<Son :aa="money"></Son> //aa属性为自定义
-
在子组件的选项中,通过props选项来接收这个属性
-
这个属性可以在子组件的模板中以全局变量的形式使
<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
- props属性验证
-
-
子父组件通信
-
自定义事件
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操作【第三方库实例化(静态数据)】
- beforeCreat () {}
-
运行中
- beforUpdate 组件更新前
- 触发条件:组件的数据发生改变
- 任务 :VDOM重新生成,然后通过diff算法和以前的VDOM对比,生成patch补丁对象【内部进行】【举例:见面的结果】
- updated 组件更新结束
- 触发条件:组件的数据发生改变
- 任务:将patch补丁对象进行渲染生成真实DOM 【举例:证明第一次相亲失败,换了一人】
- 意义:
- 可以操作DOM【第三方库的实例化(动态数据)】
- 总结:平时大家使用updated进行第三方库实例化
- beforUpdate 组件更新前
-
销毁
-
意义: 用来完成善后工作【计时器,第三方库实例,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() } }
-