天天看點

updated && beforeUpdate() Updated()&& 生命周期-銷毀階段 && vue的[email protected]總結 - 銷毀階段

updated && beforeUpdate() 和 Updated()鈎子函數 && 生命周期-銷毀階段-外部銷毀 && 生命周期-銷毀階段-内部銷毀 && vuejs 的 nextTick

updated 鈎子函數

  • 頁面資料已更新
  • 任務通過diff算法對比新舊DOM,生成patch更新檔對象,然後将更新檔對象渲染為真實DOM,
  • 渲染的是變化部分
  • 得到真實DOM,可以進行DOM操作
<body>
    <div id="app">
        <Hello></Hello>
    </div>

    <template id="hello">
        <div>
            <button @click = "changeInfo"> changeInfo </button>
            <p> {{ info }} </p>
        </div>
    </template>
</body>
<script src="../../lib/vue.js"></script>
<script>
    new Vue({
        el: '#app',
        components: {
            'Hello': {
                template: '#hello',
                data() {
                    return {
                        info: 'hello'
                    }
                },
                methods: {
                    changeInfo() {
                        this.info = '距離國慶沒幾天了'
                    }
                },
                beforeupdate() { //執行個體未完全建立出來執行 
                    console.log(this.info);
                    console.log('beforeCreate');
                },
                updated() { //頁面資料已更新
                    //任務通過diff算法對比新舊DOM,生成patch更新檔對象,然後将更新檔對象渲染為真實DOM,
                    //渲染的是變化部分
                    //得到真實DOM,可以進行DOM操作
                    document.querySelector('p').style.background = 'blue'
                    console.log('updated')
                },
            },
        }
    })
</script>
           

beforeUpdate() 和 Updated()鈎子函數

----Swiper執行個體動态,但是還是有點小問題(後面會解決的)

在mounted()鈎子函數時是Swiper靜态的
<body>

    <div id="app">
        <Swiper></Swiper>
    </div>

    <template id="swiper">
        <div class="swiper-container">
            <div class="swiper-wrapper">
                <div class="swiper-slide"
                    v-for="banner in banners"
                    :key="banner.id">
                    <img :src="banner.img"
                        alt="error">
                </div>
            </div>
            <!-- 如果需要分頁器 -->
            <div class="swiper-pagination"></div>

            <!-- 如果需要導航按鈕 -->
            <div class="swiper-button-prev"></div>
            <div class="swiper-button-next"></div>

            <!-- 如果需要滾動條 -->
            <div class="swiper-scrollbar"></div>
        </div>
    </template>
</body>
<script src="../../lib/vue.js"></script>
<script>
    new Vue({
        el: '#app',
        components: {
            'Swiper': {
                template: '#swiper',
                data() {
                    return {
                        banners: []
                    }
                },
                beforeCreate() { //執行個體未完全建立出來執行 
                    console.log('beforeCreate');
                },
                created() { //methods和data已經初始化,常用于操作資料,發起ajax請求
                    fetch('./mock/banner.json', {
                            method: 'get'
                        })
                        .then((response) => {
                            return response.json()
                        })
                        .then((result) => {
                            this.banners = result;
                        })
                        .catch(err => console.log(err));
                },
                beforeMount() { //挂載資料之前
                    console.log('beforeMount');
                },
                mounted() { //記憶體中的模闆已挂載到頁面中
                    // var mySwiper = new Swiper('.swiper-container', {
                    //     loop: true, // 循環模式選項

                    //     // 如果需要分頁器
                    //     pagination: {
                    //         el: '.swiper-pagination',
                    //     },

                    //     // 如果需要前進後退按鈕
                    //     navigation: {
                    //         nextEl: '.swiper-button-next',
                    //         prevEl: '.swiper-button-prev',
                    //     },

                    //     // 如果需要滾動條
                    //     scrollbar: {
                    //         el: '.swiper-scrollbar',
                    //     },
                    // })

                },
                beforeUpdate() { //資料更新之前
                    //資料更新,但是頁面上還是舊資料
                    console.log('beforeUpdate');
                },
                updated() { //頁面資料已更新
                    var mySwiper = new Swiper('.swiper-container', {
                        loop: true, // 循環模式選項

                        // 如果需要分頁器
                        pagination: {
                            el: '.swiper-pagination',
                        },

                        // 如果需要前進後退按鈕
                        navigation: {
                            nextEl: '.swiper-button-next',
                            prevEl: '.swiper-button-prev',
                        },

                        // 如果需要滾動條
                        scrollbar: {
                            el: '.swiper-scrollbar',
                        },
                    })
                },
                beforeDestroy() { //vue銷毀之前
                    console.log('beforeDestroy');
                },
                destroyed() { //已完全銷毀

                },
            }
        }
    })
</script>
           

3-生命周期-銷毀階段-外部銷毀

destroy()

作用

- 善後: 清除Vue無法自動删除的副作用,比如: 計時器、滾動事件、第三方執行個體

<body>
    <div id="app">
        <button @click="destroy"> 銷毀 </button>
        <Hello v-if="flag"></Hello>
    </div>

    <template id="hello">
            <div>
                Hello
            </div>
        </template>
</body>
<script src="../../lib/vue.js"></script>
<script>
    Vue.component('Hello', {
        template: '#hello',
        mounted() { //記憶體中的模闆已挂載到頁面中
            this.timer = setInterval(() => {
                console.log(1)
            }, 1000);

            window.onscroll = function() {
                console.log('scroll')
            }
        },
        destroyed() { //已完全銷毀
        // 2. 作用
    // - 善後: 清除Vue無法自動删除的副作用,比如: 計時器、滾動事件、第三方執行個體
            clearInterval(this.timer);
            window.onscroll = null;
        },
    })
    new Vue({
        el: '#app',
        data: {
            flag: true
        },
        methods: {
            destroy() {
                this.flag = !this.flag;
            }
        },
    })
</script>
           

生命周期-銷毀階段-内部銷毀

<body>
    <div id="app">
        <Hello></Hello>
    </div>

    <template id="hello">
        <div class="hello-box">
            <button @click="destroy"> 内部銷毀 </button>
            Hello
        </div>
    </template>
</body>
<script src="../../lib/vue.js"></script>
<script>
    Vue.component('Hello', {
        template: '#hello',
        methods: {
            destroy() {
                this.$destroy();
            }
        },
        mounted() { //記憶體中的模闆已挂載到頁面中
            this.timer = setInterval(() => {
                console.log(1)
            }, 1000);

            window.onscroll = function() {
                console.log('scroll')
            }
        },
        beforeDestroy() { //vue銷毀之前
            console.log('beforeDestroy');
        },
        destroyed() { //已完全銷毀
            clearInterval(this.timer);
            window.onscroll = null;
            document.querySelector('.hello-box').remove();

            //delete this.arg
            //用delete 删除變量
        },

    })


    new Vue({
        el: '#app'
    })
</script>
           

總結 - 銷毀階段

  1. beforeDestroy 和 destroyed 沒啥差别
  2. 作用
    • 善後: 清除Vue無法自動删除的副作用 ,比如: 計時器、滾動事件、第三方執行個體
  3. 形式
    • 外部銷毀
    • 内部銷毀
      • 差別: 都可以删除元件,但是内部銷毀會留有元件真實DOM

    銷毀 觸發條件:元件被删除

    銷毀

    觸發條件:元件被删除

  • 銷毀

    觸發條件:元件被删除

    • 外部開關銷毀
    • 内部調用$destroy()

      這兩個鈎子函數沒有太大差別,是以我們統一說

      • beforeDestroy
      • destroyed
    • 外部銷毀
      • 通過開關完成
        • DOM被删除了,元件也被删除了
    • 内部銷毀
      • 通過調用$destroy()來完成
        • DOM沒有被删除,但是元件被删除了
        • Dom需要手動删除

swiper-vuejs 的 nextTick

![](http://www.jqhtml.com/wp-content/uploads/2017/10/swiper1017-17.gif)

- 靜态資料
- 動态資料
  - updated中寫式,會有重複執行個體化問題
    - 第一個解決方案: 加判斷條件
    - 第二個解決方案: setTimout
      - 放在主線程後執行,異步隊列中,保證真實DOM渲染完成
    - 第三種解決方案: 推薦    Vue内部提供的  nextTick


      - ==nextTick表示真實DOM渲染完成之後才執行==
        - Vue.nextTick( callback )
        - this.$nextTick( callback )
           
案例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>vuejs的nextTick </title>
    <link href="https://cdn.bootcss.com/Swiper/4.5.1/css/swiper.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/Swiper/4.5.1/js/swiper.min.js"></script>
    <link rel="shortcut icon" href="../img/pikaqiu.jpg" type="image/x-icon" />
    <!--IE 位址欄前的圖示-->
    <link rel="Bookmark" href="../img/pikaqiu.jpg" type="image/x-icon">
    <!--收藏夾的圖示-->
    <style>
        .swiper-container {
            width: 600px;
            height: 300px;
        }
    </style>
</head>

<body>
    <div id="app">
        <Hello></Hello>
    </div>
    <template id="hello">
        <div>
            <input type="text" v-model = "num">
            <div class="swiper-container">
                <div class="swiper-wrapper">
                    <div class="swiper-slide"
                        v-for = "item in banners"
                        :key = "item.id"
                    >
                        <img :src = "item.img" alt="">
                    </div>
                </div>
                <!-- 如果需要分頁器 -->
                <div class="swiper-pagination"></div>
                
                <!-- 如果需要導航按鈕 -->
                <div class="swiper-button-prev"></div>
                <div class="swiper-button-next"></div>
                
                <!-- 如果需要滾動條 -->
                <div class="swiper-scrollbar"></div>
            </div>
        </div>
    </template>
</body>
<script src="../../lib/vue.js"></script>
<script>
    // nextTick 表示真是dom渲染結束 

    Vue.component('Hello', {
        template: '#hello',
        data() {
            return {
                banners: [],
                num: 0
            }
        },
        created() {
            fetch('./mock/banner.json')
                .then(data => data.json())
                .then(res => {
                    this.banners = res
                        // Vue.nextTick(function() {
                    this.$nextTick(function() { // 推薦
                        /* 
                            好處: 
                                1. 執行個體化執行一次
                                2. 真實DOM渲染結束之後才執行
                        */
                        var mySwiper = new Swiper('.swiper-container', {
                            loop: true, // 循環模式選項

                            // 如果需要分頁器
                            pagination: {
                                el: '.swiper-pagination',
                            },

                            // 如果需要前進後退按鈕
                            navigation: {
                                nextEl: '.swiper-button-next',
                                prevEl: '.swiper-button-prev',
                            },

                            // 如果需要滾動條
                            scrollbar: {
                                el: '.swiper-scrollbar',
                            },
                        })
                    })
                }).catch(err => console.log(err))
        },
        updated() {
            console.log('update')
                // 如果有其他資料改變,那麼updated鈎子也要出發,那麼會有重複執行個體化問題
                // var mySwiper = new Swiper('.swiper-container', {
                //     loop: true, // 循環模式選項

            //     // 如果需要分頁器
            //     pagination: {
            //         el: '.swiper-pagination',
            //     },

            //     // 如果需要前進後退按鈕
            //     navigation: {
            //         nextEl: '.swiper-button-next',
            //         prevEl: '.swiper-button-prev',
            //     },

            //     // 如果需要滾動條
            //     scrollbar: {
            //         el: '.swiper-scrollbar',
            //     },
            // })
        }
    })
    new Vue({
        el: '#app'
    })
</script>

</html>
           

繼續閱讀