Vue3 组件笔记
            十二月 03, 2020
            
  
        
        VUE组件
- 了解组件化
- 了解什么是组件
- vue是如何注册组件的
- vue组件的嵌套和组合如何实现
- v-is
- 通信
- 组件过渡动效
- 组件生命周期
注册
html部分
| 1 | <div id="app"> | 
局部注册
| 1 | Vue.createApp({ | 
全局注册
| 1 | Vue.createApp({}) | 
vue2和vue3的不同点,
1. vue3中发现template中可以直接写多个元素 | vue2 中template下的直接子元素有且仅有一个
2. vue3中销毁阶段的钩子函数为beforeUnmount和Unmount | vue2中是beforeDestroy和destroyed
组件嵌套
组件嵌套就是将子组件以标签的形式放到父组件template中
html部分
| 1 | <div id="app"> | 
组件嵌套-局部
| 1 | Vue.createApp({ | 
组件嵌套-全局
| 1 | Vue.createApp({}) | 
组件-组合-插槽
插槽的基本使用
| 1 | <div id="app"> | 
具名插槽
- 在#app内的组件中创建template标签 并给它设置指令v-slot:nameVal
- 在下面template中内部插槽slot 中设置name=”nameVal”
- 具名插槽是一对一的 上方#app内的标签顺序颠倒都没事
| 1 | <div id="app"> | 
作用域插槽
- 组件是一个独立的聚合体,那么组件的数据应该由自己来定义,组件内通过data来定义
- 单向数据绑定,将数据绑定给slot
- 设置v-slot:nameVal=”scoped” // scoped是自定义的
- 渲染数据
js部分
| 1 | Vue.createApp({}) | 
html部分
| 1 | <div id="app"> | 
组件的几个常用选项(案例:反向数据)
js部分
| 1 | Vue.createApp({}) | 
html部分
| 1 | <div id="app"> | 
v-is
组件v-is
- 组件不能违背html基本规则
- v-is=”‘’” (双引号里面接单引号)
表格案例
| 1 | <div id="app"> | 
js部分
| 1 | Vue.createApp({}) | 
v-is 案例
做一个用户密码或者手机号验证码的登陆页面
js部分
| 1 | Vue.createApp({ | 
html部分
| 1 | <div id="app"> | 
通信
过渡动效
- vue提供了一个内置组件: transition
- 属性mode 表示transition组件的过度的顺序 out-in(一般用这个)/in-out
- 属性enter-active-class 表示的是过度进入时的过渡效果
- 属性leave-active-class 表示的是过渡离开的过渡效果
| 1 | <transition | 
生命周期

挂载阶段
虚拟DOM在created – beforeMount生成,真实DOM在mounted拿到
- beforeCreate()- 该钩子函数表示组件创建前。
- 初始化事件和生命周期钩子函数
 
- created()- 该钩子函数表示创建结束,
- 这里我们有了组件。初始化注入【option】并且数据响应式【数据改变,界面改变】处理
 
- beforeMount()
 判断组件是否有template选项?- yes 使用render函数来编译 template 得到虚拟DOM对象模型
- no 使用el.innerHTML来代替模板
 
- mounted() - 创建app.$el来代替el 渲染虚拟DOM为真实DOM
 
- mounted案例1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12<div id="app"> 
 <Hello></Hello>
 </div>
 <template id="hello">
 <!-- 这里的标签我们称之为 jsx[javascript+xml] 是VDOM的一种简化型写法 -->
 <!-- jsx是对js语法的一种扩展,有了他我们就可以在标签中书写js了 -->
 <div>
 hello
 <p> 123 </p>
 </div>
 </template>1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18const app = Vue.createApp({}) 
 app.component('Hello',{
 template: '#hello',
 beforeCreate () {
 console.log('挂载-beforeCreate')
 },
 created () {
 console.log('挂载-created')
 },
 beforeMount () {
 console.log('挂载-beforeMount')
 },
 mounted () {
 console.log('挂载-mounted')
 document.querySelector('p').style.background = 'red'
 }
 })
 app.mount('#app')
更新阶段
触发要求: 1. 数据要改变 2. 数据得使用 可以触发多次。updated可以做真实DOM操作
- beforeUpdate()- 它表示组件更新前
- 任务: 用来监听数据改变的
 
- updated()- 它表示组件更新结束了
- 任务:虚拟DOM渲染生成,并且通过diff算法比对新旧的虚拟DOM,得到一个patch补丁对象【虚拟DOM】,重新将patch补丁对象渲染到页面,也就是说我们又一次可以得到了真实DOM
 
- 案例1 
 2
 3
 4
 5
 6
 7
 8
 9<div id="app"> 
 <Hello></Hello>
 </div>
 <template id="hello">
 <div>
 <button @click="add">add</button>
 <p> {{ count }} </p>
 </div>
 </template>1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25Vue.createApp({}) 
 .component('Hello', {
 data() {
 return {
 count: 1
 }
 },
 methods: {
 add() {
 this.count++
 }
 },
 template: '#hello',
 updated() {
 // 上面写了一个方法
 // 点击按钮就数据自增
 // 每次数据改变时触发updated()钩子函数,发送请求
 axios('http://59.110.226.77:3000/api/category')
 .then(res => {
 console.log('res', res);
 })
 .catch(error => Promise.reject(error))
 }
 })
 .mount('#app')
销毁阶段
任选其一beforeUnmount或unmounted,他会自动删除组件的事件、指令、computed、watch,但需要手动删除计时器/定时器、window/document身上事件,清楚第三方实例,释放内存
- beforeUnmount()- 它表示组件销毁前
- 自动销毁组件定义methods/指令/computed/watch
- 手动操作:- 清除计时器和定时器
- 清除绑定在window/document身上的事件
- 清除第三方实例
 
 
- unmounted() 同上
- 案例1 
 2
 3
 4
 5
 6
 7
 8
 9<div id="app"> 
 <button @click="setFlag">切换</button>
 <Hello v-if="flag"></Hello>
 </div>
 <template id="hello">
 <div>
 <p>hello</p>
 </div>
 </template>1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43// 设置类 
 function People(name) {
 this.name = name
 }
 Vue.createApp({
 data() {
 return {
 flag: true // v-if可以来控制组件的销毁
 }
 },
 methods: {
 setFlag() {
 this.flag = !this.flag
 }
 }
 })
 .component('Hello', {
 template: '#hello',
 mounted() {
 // 在组件挂载后
 // 设置第三方实例
 // 设置计时器
 // 设置window身上事件resize
 this.people = new People('zhangsan')
 this.timer = setInterval(() => {
 console.log('计时器', this.people);
 }, 1000);
 window.onresize = function () {
 console.log('监听浏览器可视窗口尺寸');
 }
 },
 unmounted() {
 // console.log('销毁');
 // 销毁后不会清楚第三方实例,计时器,window身上事件
 // 必须手动消除
 delete this.people
 clearInterval(this.timer)
 window.onresize = null
 }
 })
 .mount('#app')
缓存阶段
触发条件: keep-alive[缓存组件] 如果缓存时间过久,可以自动去清楚缓存在deactivated()中设置
- activated()- 表示你正在前台显示
 
- deactivated()- 表示你正在后台缓存
 
- 案例
 等待补充…
错误处理阶段
任务: 父组件捕获子组件的错误,使用另外一个界面来代替错误的子组件,而这个界面我们称呼为 回退UI。 errorCaptured 写在父组件中
- errorCaptured(error, instance, info){}- error 错误 instance 组件 info 具体信息
 
- 案例1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15<div id="app"> 
 <Father></Father>
 </div>
 <template id="father">
 <div>
 <div v-if="flag"> 回退UI -- 您的网络有延迟,请重试 </div>
 <Son v-else></Son>
 </div>
 </template>
 <template id="son">
 <div>
 son
 </div>
 </template>1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24Vue.createApp({}) 
 .component('Father', {
 template: '#father',
 data() {
 return {
 flag: false
 }
 },
 errorCaptured(error, instance, info) {
 // 写在父组件中
 // 如果子组件抛出错误会触发
 console.log('触发');
 if (error) { // 如果错误存在的话
 this.flag = true // 改变flag从而改变页面
 }
 }
 })
 .component('Son', {
 template: '#son',
 mounted() {
 throw new Error('出错了') // 在挂载阶段仍出个自定义错误
 }
 })
 .mount('#app')
虚拟DOM跟踪阶段
- renderTracked()- 触发的操作是get
- 挂载的虚拟DOM和更新阶段虚拟DOM都会被追踪到
 
- renderTriggered()- 触发的操作是set
- 更新阶段虚拟DOM都会被追踪到
 
- 案例1 
 2
 3
 4
 5
 6
 7
 8
 9
 10<div id="app"> 
 <Hello></Hello>
 </div>
 <template id="hello">
 <div>
 <button @click="add">+</button>
 <p> {{ count }} </p>
 </div>
 </template>1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27Vue.createApp({}) 
 .component('Hello', {
 template: '#hello',
 data() {
 return {
 count: 1,
 list: null
 }
 },
 methods: {
 add() {
 this.count++ // 这将导致renderTriggered调用
 }
 },
 renderTracked({ key, target, type }) {
 console.log('key', key);
 console.log('target', target);
 console.log('type', type);
 // 当组件第一次渲染时,这将被记录下来
 },
 renderTriggered({ key, target, type }) {
 console.log('key', key);
 console.log('target', target);
 console.log('type', type);
 }
 })
 .mount('#app')
查看评论