vue2生命周期
| 生命周期 | 描述 | 使用场景 | 具体分析 |
|---|---|---|---|
| beforeCreate | 组件实例被创建之初 | 执行时组建实例还未创建,通常用于插件开发中执行一些初始化任务 | 初始化Vue实例 |
| create | 组件实例已经完全创建 | 组件初始化完毕,各种数据可以使用,常用于异步数据获取 | 1.完成数据观测,属性与方法的运算,watch、event事件回调的配置 2.可调用methods中的方法,访问和修改data数据触发相应式渲染dom,可通过computed和watch完成数据计算 3.vm.$el并没有被创建 |
| beforeMount | 组件挂载之前 | 未执行渲染、更新,dom未创建 | 1.在此阶段可获取vm.$el 2.此阶段vm.$el虽已完成DOM初始化,但并未挂载在el选项上 |
| mounted | 组件挂载到实例上去之后 | 初始化结束,dom已创建,可用于获取访问数据和dom元素 | vm.$el已经完成DOM的挂载与渲染,此刻打印vm.$el,发现之前的挂载点及内容已被替换成新的DOM |
| beforeUpdate | 组件数据发生变化,更新之前 | 更新前,可用于获取更新前各种状态 | 1.更新的数据必须是被渲染在模版上的(el、template、render之一)2.此刻view层还未更新 3.若在beforeUpdate中再次修改数据,不会再次触发更新方法 |
| update | 组件数据更新之后 | 更新后,所有状态已是最新 | 1.完成view层的更新 2.若在update中再次修改数据,会再次触发更新方法(beforeUpdate、update) |
| beforeDestroy | 组件实例销毁之前 | 销毁前,可用于一些定时器和订阅的取消 | 实例被销毁前调用,此时实例属性与方法仍可访问 |
| destroy | 组件实例销毁之后 | 组建已销毁,作用同上 | 1.完全销毁一个实例。可清理它与其他实例的链接,接棒他的全部指令及事件监听器 2.并不能清除Dom,仅仅销毁实例 |
数据请求在created和mouted的区别
created 是在组件实例一旦创建完成的时候立刻调用,这时候页面dom节点并未生成; mounted 是在页面 dom 节点渲染完毕之后就立刻执行的。触发时机上 created 是比 mounted 要更早的,两者的相同点:都能拿到实例对象的属性和方法。讨论这个问题本质就是触发的时机,放在 mounted 中的请求有可能导致页面闪动(因为此时页面 dom 结构已经生成),但如果在页面加载前完成请求,则不会出现此情况。建议对页面内容的改动放在 created 生命周期当中。
mvvm和双向绑定
Vue 是数据双向绑定的框架,核心功能便是“数据双向绑定”,双向绑定由三个重要部分构成
- 数据层(Model):应用的数据及业务逻辑.
- 视图层(View):应用的展示效果,各类UI组件
- 业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图关联起来而上面的这个分层的架构方案
ViewModel:
- 数据变化后更新视图
- 视图变化后更新数据当然,它还有两个主要部分组成
- 监听器(Observer):对所有数据的属性进行监听
- 解析器(Compiler):对每个元素节点的指令进行扫描跟解析,根据指令模板替换数据,以及绑定相应。的更新函数
组件通信
vue中每一个.vue可以视作为组件,通信的本质是信息同步。 每个组件都有自己的作用域,在工作业务中不同组件存在需要传递信息、共享数据。 组件通信分为:
- 父子组件之间的通信
- 兄弟组件之间的通信
- 祖孙与后代组件之间的通信
- 非关系组件之间的通信
Vue2常见的8种组件通信:
- 通过
props传递 - 通过
$emit触发自定义事件 - 使用
ref EventBusparent或rootattrs与listenersProvide与Inject- Vuex
可参考代码链接:# Vue3的8种和Vue2的12种组件通信,值得收藏
- 父子关系的组件数据传递选择
props与$emit进行传递,也可选择ref兄弟关系的组件数据传递可选择$bus,其次可以选择$parent进行传递 - 祖先与后代组件数据传递可选择
attrs与listeners或者Provide与Inject - 复杂关系的组件数据传递可以通过
vuex存放共享的变量
vuex
适用场景:复杂关系的组件数据传递,Vuex 作用相当于一个用来存储共享变量的容器
state用来存放共享变量的地方getter,可以增加一个 getter 派生状态,(相当于 store 中的计算属性),用来获得共享变量的值mutations用来存放修改state的方法。actions也是用来存放修改state的方法,不过action是在mutations的基础上进行。常用来做一些异步操作。
vue2和vue3生命周期区别
常用生命周期对比如下表所示。
| vue2 | vue3 |
|---|---|
| beforeCreate | |
| created | |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeDestroy | onBeforeUnmount |
| destroyed | onUnmounted |
Vue 2 的生命周期钩子如下所示:
- 创建阶段 beforeCreate created
- 挂载前后 beforeMount mounted
- 更新阶段 beforeUpdate updated
- 销毁阶段 beforeDestroy destroyed
- 错误处理 errorCaptured
- 异步组件 activated deactivated
- 服务端渲染 serverPrefetch
Vue 3 的生命周期钩子如下所示:
- 创建阶段 setup (Composition API),beforeCreate 和 created 被 setup 替代
- 挂载阶段 beforeMount mounted
- 更新阶段 beforeUpdate updated
- 销毁阶段 beforeUnmount unmounted
- 错误处理 errorCaptured
- 异步组件 activated deactivated
- 服务端渲染 serverPrefetch
<template> // Vue2 中只能有一个根节点
<div class='form-element'>
...
</div>
</template>
<script>
export default {
props: ['secondNum'], //父组件传过来的值,默认为0
data () { // 创建
return {
firstNum: 0,
msg: "123456"
}
},
computed: {
thirdNum () {
console.log('computed', this.firstNum, this.secondNum)
return this.firstNum + this.secondNum + '元' }
},
watch: {
//简单形式
// msg(newValue, oldValue) {
// console.log("newValue", newValue);
// console.log("oldValue", oldValue);
// }
//对象形式
msg: {
deep: true,
immediate: true,//初始化是否执行
handler(newValue, oldValue) {
console.log("newValue", newValue);
console.log("oldValue", oldValue);
},
}
},
created () {
console.log('created', this.firstNum, this.secondNum)
},
beforeMount () {
console.log('beforeMount', this.firstNum, this.secondNum)
},
mounted () {
console.log('mounted', this.firstNum, this.secondNum)
},
beforeUpdate () {
console.log('beforeUpdate', this.firstNum, this.secondNum)
},
updated () {
console.log('updated', this.firstNum, this.secondNum)
},
methods: {
btnClick () {
this.firstNum = 'firstNum' + Math.random() * 999 console.log('methods', this.firstNum, this.secondNum)
}
}
}
</script>
<template> //Vue3 中支持多个根节点
<div class='form-element'>
...
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
props: {
title: String
},
const state = reactive({
username: '',
password: '',
lowerCaseUsername: computed(() => state.username.toLowerCase())
})
const count = ref(1) // 有人这么用 const arr = ref([])
console.log(arr.value) // []
// 也有人这么用,一个组件里所有的属性全部定义在一个对象里,有点 Vue2 data 的味道
const data = reactive({ name: '沐华', age: 18, ... })
console.log(data.name) // 沐华
// 也有人一个组件里 ref 和 reactive 两种都用,随便你
// 这样虽然能拿到 name / age,但是会变成普通变量,没有响应式效果了
const { name, age } = data // 取出来一个响应式属性
const name = toRef(data, 'name') // 这样解构出来的所有属性都是有响应式的
const { name, age } = toRefs(data) // 不管是 toRef 还是 toRefs,这样修改是会把 data 里的 name 改掉的
// 就是会改变源对象属性,这才是响应式该有的样子 name.value = '沐沐华华'
// 请求接口函数
const getData = () => { xxxApi.then(() => { ... }) }
onMounted(() => {
console.log('title: ' + props.title)
getData()
})
// 监听
const msg = ref('1111')
//简单的没有其他设置的监听
// watch(msg, (newVal, oldVal) => {
// console.log('监听msg变化', newVal, oldVal)
// })
//对象形式
watch(msg, (newVal, oldVal) => {
console.log('监听msg变化', newVal, oldVal)
}, {
immediate: true,
deep: true
})
// 组件卸载前,对应 Vue2 的 beforeDestroy
onBeforeUnmount(() => {
clearTimeout(timer)
window.removeAddEventListener('...')
})
// 退出缓存组件,对应 Vue2 的 deactivated
onDeactivated(() => {
clearTimeout(timer)
window.removeAddEventListener('...')
})
return {
login,
state
}
}
}
</script>