为什么出现ref

在没有学习Vue之前,我们实现直接操作页面上的DOM元素都是通过JS/jQuery,因为jQueryDOM元素的操作非常的方便。但是学习了Vue之后,对DOM的操作完全交给VM了,这个时候手动的获取DOM元素再使用JS/jQuery就没有那么方便。于是出现了ref,即ref的功能之一就是获取DOM元素的,当然还有其他的功能。
所以ref主要的两个作用如下:

  • 使用ref获取页面DOM元素
  • 使用 ref获取子组件对象

ref使用原理

refVue中是用来给元素或是子组件注册引用信息到父组件或是 Vue实例上,注册后的引用信息都会呈现在父组件/Vue实例的 $.refs 上,这时,我们就可以通过$.refs 获取到引用的 DOM 对象或是子组件信息。

使用ref获取DOM元素使用案例

例如,我们可以获取到页面上添加了 refinput输入框的值,对于子组件来说,我们可以直接获取到子组件data 选项中的数据,或是直接调用子组件的方法。

在下面的代码中,我在 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 元素上,还只是挂载在虚拟DOM上,因此我们可以得出 ref是在页面渲染完成后才被创建的

使用 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中的虚拟DOM)的做法渲染网页,如果我们直接操作 DOM,很容易产生实际网页跟 Vue 产生的 Virtual DOM 不同步的问题,而通过使用ref 属性之后,在一些需要获取 DOM 元素的情况下,我们就可以很方便的获取 DOM 元素。当然,当我们决定在项目中使用 Vue,还是需要转变我们的思路,将操作 DOM 转变成操作数据。同样的,通过将ref属性添加到子组件上,我们就可以很轻松的获取到子组件的相关信息,这无疑给父组件获取子组件数据、调用子组件的方法提供了一种新的思路。

Logo

前往低代码交流专区

更多推荐