Vue3 Day5-Vue3的生命周期

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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值