5.1 Vue3的生命周期
vue2 vue3
beforeCreate setup()
created setup()
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestroy onBeforeUnmount
destroyed onUnmounted
activated onActivated
deactivated onDeactivated
非语法糖生命周期写法
父组件 App.vue
<template>
<div>
<button @click="type='tab1'">显示tab1</button>
<button @click="type='tab2'">显示tab2</button>
<!-- 动态组件 -->
<keep-alive>
<component :is="type"></component>
</keep-alive>
<!-- 子组件 -->
<HelloWorld v-if="show"></HelloWorld>
<button @click="isShow">显示吗</button>
</div>
</template>
<script>
import tab1 from './components/tab1.vue'
import tab2 from './components/tab2.vue'
import HelloWorld from './components/HelloWorld.vue'
import {
ref
} from 'vue'
export default {
components: {
tab1,
tab2,
HelloWorld
},
beforeCreate() {
console.log('beforeCreate');
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMount');
},
mounted() {
console.log('mounted');
},
beforeUpdate() {
console.log('beforeUpdate');
},
updated() {
console.log('updated');
},
activated() {
console.log('activated');
},
deactivated() {
console.log('deactivated');
},
beforeUnmount() {
console.log('beforeUnmount');
},
unmounted() {
console.log('unmounted');
},
setup() {
let type = ref('tab1')
// 子组件:探讨父子组件生命周期执行顺序
let show = ref(true)
let isShow = () => {
show.value = !show.value
}
return {
type,
show,
isShow
}
}
}
</script>
<style scoped>
</style>
子组件
HelloWorld.vue
<template>
<div>子组件</div>
</template>
<!-- setup取代了export default -->
<script>
import {
ref,
reactive
} from 'vue'
export default {
beforeCreate() {
console.log('子beforeCreate');
},
created() {
console.log('子created')
},
beforeMount() {
console.log('子beforeMount');
},
mounted() {
console.log('子mounted')
},
beforeUpdate() {
console.log('子beforeUpdate');
},
updated() {
console.log('子updated');
},
activated() {
console.log('子activated');
},
deactivated() {
console.log('子deactivated');
},
beforeUnmount() {
console.log('子组件beforeUnmount');
},
unmounted() {
console.log('子组件unmounted');
}
}
</script>
<style scoped>
div {
color: #aa0000;
}
</style>
tab1.vue
<template>
<div>我是tab1</div>
</template>
<!-- setup取代了export default -->
<script>
</script>
<style scoped>
div {
color: #f60;
}
</style>
tab2.vue
<template>
<div>我是tab2</div>
</template>
<!-- setup取代了export default -->
<script>
</script>
<style scoped>
div {
color: #f60;
}
</style>
语法糖生命周期写法
父组件 App.vue
<template>
<div>
<button @click="tab11">显示tab1</button>
<button @click="tab22">显示tab2</button>
<!-- 动态组件 -->
<keep-alive>
<component :is="type"></component>
</keep-alive>
<!-- 子组件 -->
<HelloWorld v-if="show"></HelloWorld>
<button @click="isShow">显示吗</button>
</div>
</template>
<script setup>
import tab1 from './components/tab1.vue'
import tab2 from './components/tab2.vue'
import HelloWorld from './components/HelloWorld.vue'
import {
ref,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
// vue3 注册动态组件用defineOptions()
defineOptions({
components: {
tab1,
tab2
}
})
onBeforeMount(() => {
console.log('onBeforeMount');
})
onMounted(() => {
console.log('onMounted');
})
onBeforeUpdate(() => {
console.log('onBeforeUpdate');
})
onUpdated(() => {
console.log('onUpdated');
})
onBeforeUnmount(() => {
console.log('onBeforeUnmount');
})
onUnmounted(() => {
console.log('onUnmounted');
})
let type = ref('tab1')
let tab11 = () => {
type.value = 'tab1'
}
let tab22 = () => {
type.value = 'tab2'
}
// 子组件:探讨父子组件生命周期执行顺序
let show = ref(true)
let isShow = () => {
show.value = !show.value
}
// vue3 父子组件生命周期执行顺序
// 父setup-父beforeCreated-父created-父beforeMounted-子beforeCreate-子Create-子beforeMount-父activated-子mounted-父mounted
//在setup语法糖情况下 没有beforeCreate 和created这两个生命周期
</script>
<style scoped>
</style>
子组件
HelloWorld.vue
<template>
<div>子组件</div>
</template>
<!-- setup取代了export default -->
<script setup>
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
onBeforeMount(() => {
console.log('子onBeforeMount');
})
onMounted(() => {
console.log('子onMounted');
})
onBeforeUpdate(() => {
console.log('子onBeforeUpdate');
})
onUpdated(() => {
console.log('子onUpdated');
})
onBeforeUnmount(() => {
console.log('子onBeforeUnmount');
})
onUnmounted(() => {
console.log('子onUnmounted');
})
</script>
<style scoped>
div {
color: #aa0000;
}
</style>
tab1.vue
<template>
<div>我是tab1</div>
</template>
<!-- setup取代了export default -->
<script setup>
import {
onActivated,
onDeactivated
} from 'vue'
onActivated(() => {
console.log('tab1-onActivated');
})
onDeactivated(() => {
console.log('tab1-onDeactivated');
})
</script>
<style scoped>
div {
color: #f60;
}
</style>
tab2.vue
<template>
<div>我是tab2</div>
</template>
<!-- setup取代了export default -->
<script setup>
import {
onActivated,
onDeactivated
} from 'vue'
onActivated(() => {
console.log('tab2-onActivated');
})
onDeactivated(() => {
console.log('tab2-onDeactivated');
})
</script>
<style scoped>
div {
color: #f60;
}
</style>
5.2 hooks函数
App.vue
<template>
<div>
<h1>屏幕尺寸</h1>
<div>宽度:{{width}}</div>
<div>高度:{{height}}</div>
</div>
</template>
<script setup>
import {
ref,
onMounted
} from 'vue'
import useWindowResize from './hooks/useWindowResize.js'
let {
width,
height
} = useWindowResize()
onMounted(() => {
document.title = 'hooks函数'
})
</script>
<style scoped>
</style>
hooks->useWindowResize.js
js文件名字必须以 use开头
import {
ref,
onMounted
} from 'vue'
// 封装的hooks的js文件名必须以 ‘use’开头
function useWindowResize() {
let width = ref(0)
let height = ref(0)
let onResize = () => {
width.value = window.innerWidth
height.value = window.innerHeight
}
onMounted(() => {
// 方法onResize 挂载时不用加括号
window.addEventListener('resize', onResize)
onResize()
})
return {
width,
height
}
}
export default useWindowResize
5.3 toRef()的使用
非语法糖
<template>
<div>
<h2>{{name}}</h2>
<h2>{{age}}</h2>
<button @click="change">改变吧</button>
</div>
</template>
<script>
import {
reactive,
toRef
} from 'vue'
export default {
setup() {
let person = reactive({
name: 'king',
num1: {
num2: {
age: 12
}
}
})
// toRef可以基于响应式对象上的一个属性,创建一个对应的 ref,这样创建的 ref 与其源属性保持同步:改变源属性的值将更新 ref 的值,反之亦然。
let name = toRef(person, 'name')
let age = toRef(person.num1.num2, 'age')
let change = () => {
name.value += '@'
age.value++
}
return {
person,
name,
age,
change
}
}
}
</script>
<style scoped>
</style>
语法糖
<template>
<div>
<h2>{{name}}</h2>
<h2>{{age}}</h2>
<button @click="change">改变吧</button>
</div>
</template>
<script setup>
import {
reactive,
toRef
} from 'vue'
let person = reactive({
name: 'king',
num1: {
num2: {
age: 12
}
}
})
// toRef可以基于响应式对象上的一个属性,创建一个对应的 ref,这样创建的 ref 与其源属性保持同步:改变源属性的值将更新 ref 的值,反之亦然。
let name = toRef(person, 'name')
let age = toRef(person.num1.num2, 'age')
let change = () => {
name.value += '@'
age.value++
}
</script>
<style scoped>
</style>
5.4 toRefs()的使用
<template>
<div>
<h2>{{name}}</h2>
<h2>{{age}}</h2>
<h2>{{school}}</h2>
<button @click="change">改变吧</button>
</div>
</template>
<script setup>
import {
ref,
reactive,
toRef,
toRefs
} from 'vue'
let person = reactive({
name: 'king',
school: '观音大士学府',
num1: {
num2: {
age: 12
}
}
})
// toRefs只能解构一层,多层级需要在toRefs中包裹多层例如:let {sex} = toRefs(person.job.j1)
let {
name,
school
} = toRefs(person)
let {
age
} = toRefs(person.num1.num2)
let change = () => {
name.value += '@'
age.value++
}
// 错误做法:
// 这里不能用ref来取代toRef 因为ref定义的数据已经和原数据不是一个数据了,即非同源
// let name = ref(person.name)
// console.log(name); //king
</script>
<style scoped>
</style>
5.5 shallowReactive与shallowRef
<template>
<div>
<!-- <h2>{{name}}</h2> -->
<h2>{{person.age}}</h2>
<h2>{{person.work.job.num}}</h2>
<button @click="change">改变吧</button>
</div>
</template>
<script setup>
import {
shallowRef,
shallowReactive
} from 'vue'
// shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理
// let name = shallowRef('king')
// let person = shallowRef({
// age: 12,
// work: {
// job: {
// num: 1
// }
// }
// })
// let change = () => {
// name.value += '@'
// // 如果shallowRef非要处理对象的,可以使用以下方法
// person.value = {
// age: 16
// }
// }
// shallowReactive:只处理对象最外层属性的响应式(浅响应式)
let person = shallowReactive({
age: 12,
work: {
job: {
num: 1
}
}
})
let change = () => {
// 产生响应式
// person.age++
// 不产生响应式
person.work.job.num++
console.log(person.work.job.num);
}
</script>
<style scoped>
</style>
5.6 readonly与shallowReadonly
<template>
<div>
<h2>{{person.age}}</h2>
<h2>{{person.work.job.num}}</h2>
<button @click="change">改变吧</button>
</div>
</template>
<script setup>
import {
shallowRef,
shallowReactive,
readonly,
shallowReadonly
} from 'vue'
// shallowReadonly:让一个响应式数据变为只读的(浅只读)
// let person = shallowReadonly({
// age: 12,
// work: {
// job: {
// num: 1
// }
// }
// })
// let change = () => {
// person.age++ //只读
// }
// readonly: 让一个响应式数据变为只读的(深只读)
let person = shallowReadonly({
age: 12,
work: {
job: {
num: 1
}
}
})
let change = () => {
person.work.job.num++ //只读
console.log(111);
}
</script>
<style scoped>
</style>