Vue.js-11:第十一章 - Vue 中 ref 的使用

 一、前言

  在之前的前端開發中,爲了實現我們的需求,通常採用的方案是通過 JS/Jquery 直接操縱頁面的 DOM 元素,得益於 Jquery 對於 DOM 元素優異的操作能力,我們可以很輕易的對獲取到的 DOM 元素進行操作。但是,當我們開始在前端項目中使用 Vue 這類的 MVVM 框架之後,對於 DOM 的操作我們就應當完全的交給框架,而我們只需要關注於數據。難道,在 Vue 中就不能手動獲取到頁面上的 DOM 元素了嗎,答案當然是可以手動獲取到 DOM 元素的,在 Vue 中我們可以通過使用 ref 實現獲取 DOM 元素的功能,當然,這也只是 ref 其中一項的功能。本章,我們就來學習 Vue 中 ref 的相關使用。

  學習系列目錄地址:https://www.cnblogs.com/danvic712/p/9549100.html

  倉儲地址:https://github.com/Lanesra712/VueTrial/blob/master/chapter02-bronze/ref.html

 二、乾貨合集

  ref 在 Vue 中是用來給元素或是子組件註冊引用信息到父組件或是 Vue 實例上,註冊後的引用信息都會呈現在父組件/Vue 實例的 $.refs 上,這時,我們就可以通過 $.refs 獲取到引用的 DOM 對象或是子組件信息。

  例如,我們可以獲取到頁面上添加了 ref 的 input 輸入框的值,對於子組件來說,我們可以直接獲取到子組件 data 選項中的數據,或是直接調用子組件的方法。

  1、虛擬 DOM

  在我們使用 JS/Jquery 直接對 DOM 元素進行操作時,不管是對元素樣式的修改(背景顏色從紅色變成藍色)還是對頁面中的某些佈局進行動態調整(通過點擊按鈕在列表中添加一行新的數據),這都會造成頁面的重新渲染,從而影響我們網站的性能。而在 Vue 中,通過在內存中生成與真實 DOM 與之對應的數據結構(虛擬 DOM),當頁面發生變化時,通過新的虛擬 DOM 樹與舊的虛擬 DOM 樹進行比對,就能很快的找出差異點,從而得出應施加到真實 DOM 上的改動。

虛擬DOM(圖片版權屬於 Vue 作者尤雨溪)

  2、使用 ref 獲取頁面 DOM 元素

  在使用 JS/Jquery 獲取頁面的 DOM 元素時,我們一般是根據 id、class、標籤、屬性等其它標識來獲取到頁面上的 DOM 元素。嗯,可以說,我們很難拋棄 Jquery 的一個重大原因,就是當我們需要獲取到頁面上的 DOM 元素時,使用 Jquery 的 API 相比於原生的 JS 代碼,簡單到極致,有木有。

document.getElementById('id').value => $('#id').val()

  那麼,難道我們在 Vue 中獲取 DOM 元素還是採用這樣的方式?

  答案當然是否定的,這種直接操縱 DOM 元素的方式,與我們使用 Vue 的初衷不符,雖然能達成效果,但是卻不提倡,這裏我們就可以使用 ref 來獲取頁面上的 DOM 元素。

  在下面的代碼中,我在 input 上添加了一個 ref 屬性,之後,我們就可以在 Vue 實例中獲取到這個 input 輸入框的值。這裏,我在 beforeMount、mounted 這兩個 Vue 中的生命週期鉤子函數以及一個按鈕的點擊事件中嘗試獲取到這個 input 輸入框的值。

<div id="app">
    <input type="text" ref="msgText" v-model="msg" />
    <button @click="getElement">獲取元素值</button>
</div>

<script>
    var vm = new Vue({
        el: "#app",
        data: {
            msg: 'Hello ref'
        },
        beforeMount() {
            console.log('beforeMount: ' + this.$refs.msgText.value)
        },
        mounted() {
            console.log('mounted: ' + this.$refs.msgText.value)
        },
        methods: {
            getElement() {
                console.log(this.$refs.msgText.value)
            }
        }
    });
</script>

  運行代碼,從結果中可以看到,在 beforeMount 這個鉤子函數中,我們是無法獲取到這個 DOM 元素的值,結合之前學習的 Vue 生命週期的相關知識,當執行到 beforeMount 鉤子函數時,Vue 雖然已經將模板編譯完成,但是尚未掛載到頁面 DOM 元素上,因此我們可以得出 ref 是在頁面渲染完成後才被創建的。

  可以看到,當我們在 input 輸入框中添加了 ref 屬性後,在當前的 Vue 實例的 $.refs 上就掛載了當前的 input 框對象。

  3、使用 ref 獲取子組件對象

  同使用 ref 獲取頁面的 DOM 元素相似,當我們需要獲取子組件時,只需要將使用到子組件上的地方添加 ref 屬性即可。在下面的示例代碼中,我添加了一個子組件,當我們點擊 Vue 實例上的按鈕時,會先調用子組件的方法,然後獲取子組件的數據。

<div id="app">
    <input type="text" ref="msgText" v-model="msg" />
    <button @click="getElement">獲取元素值</button>

    <hr>

    <child ref="childComponent"></child>
</div>

<template id="child">
    <div>
        <input type="datetime" name="datetime" v-model="local">
        <button @click="getLocalData">獲取當前時間</button>
    </div>
</template>

<script>
    var vm = new Vue({
        el: "#app",
        data: {
            msg: 'Hello ref'
        },
        mounted() {
            console.log('mounted: ' + this.$refs.msgText.value)
        },
        methods: {
            getElement() {
                console.log('input 輸入框的值爲:' + this.$refs.msgText.value)
                this.$refs.childComponent.getLocalData()
                console.log('子組件 input 輸入框的值爲:' + this.$refs.childComponent.local)
            }
        },
        components: {
            'child': {
                template: '#child',
                data() {
                    return {
                        local: ''
                    }
                },
                methods: {
                    getLocalData() {
                        var date = new Date()
                        this.local = date.toLocaleString()
                    }
                },
            }
        }
    });
</script>

  可以看到,當我們將 ref 添加到子組件上,我們就可以在 Vue 實例上獲取到這個註冊的組件引用,同註冊的 DOM 元素一樣,我們都可以使用添加的 ref 屬性值作爲 key 獲取到註冊的對象。此時,我們就可以獲取到這個子組件上的 data 選項和 methods 選項。

 三、總結

  因爲 Vue 採用 Virtual DOM 的做法渲染網頁,如果我們直接操作 DOM,很容易產生實際網頁跟 Vue 產生的 Virtual DOM 不同步的問題,而通過使用 ref 屬性之後,在一些需要獲取 DOM 元素的情況下,我們就可以很方便的獲取 DOM 元素。當然,當我們決定在項目中使用 Vue,還是需要轉變我們的思路,將操作 DOM 轉變成操作數據。同樣的,通過將 ref 屬性添加到子組件上,我們就可以很輕鬆的獲取到子組件的相關信息,這無疑給父組件獲取子組件數據、調用子組件的方法提供了一種新的思路。

 四、參考

  1、網頁性能管理詳解

  2、重排重繪,看這一篇就夠了

  3、Vue作者尤雨溪:Vue 2.0,漸進式前端解決方案

  4、vue中的 ref 和 $refs

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章