Vue中的ref属性和$nextTick

275 阅读1分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路。

ref属性

1.被用来给元素或子组件注册引用信息(id的替代者)。

2.应用在html标签上获取真实的DOM元素。

3.应用在组件标签上获取组件实例对象。

使用方式:直接给标签加ref属性。

获取标签的DOM元素

...
<button ref="button" @click="getDom">ref获取DOM</button>
...
getDom() {
  console.log(this.$refs.button);
}
...

image.png

获取组件实例对象

通过在组件标签上加ref属性,可以获取到该组件的实例对象。

...
<button ref="button" @click="getDom">ref获取DOM</button>
<one-component ref="oneComponent"></one-component>
...
import oneComponent from '@/components/oneComponent'
...
components:{ oneComponent },
...
getDom() {
  console.log(this.$refs.button);
  console.log(this.$refs.oneComponent);
}
...

image.png

通过组件实例对象,可以获取该组件的一些属性值。

获取子组件的data、调用子组件的方法等。

当然这也可以使用组件通信实现。

$nextTick

在Vue的方法中,在一个回调内,并不是数值一发生改变就重新渲染模板,而是整个回调运行完以后,再根据修改的值渲染模板,更新DOM。

nextTick指定一个回调,指定的回调在DOM更新之后再执行。

使用方法:

// this.$nextTick(回调函数)
this.$nextTick(function(){})

作用:在下一次DOM更新结束后执行其指定的回调。

使用场景:当数据改变后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。

简单的说就是等到组件DOM更新完成后,再执行nextTick所指定的回调函数,从而保证回调函数可以操作到最新的DOM元素。

场景:点击按钮,显示input框,并使input框获取焦点。

理解的是:点击按钮->显示input框->再获取input的DOM元素->使用focus获取焦点。

使用下面的代码是不对的

<template>
  <div>
    <input type="text" v-if="isShow" ref="input" placeholder="输入框"/>
    <button @click="showInput">显示输入框,并获取焦点。</button>
  </div>
</template>

<script>
export default {
  name: "oneComponent",
  data() {
    return {
      isShow: false
    };
  },
  methods: {
    showInput(){
      // 显示输入框
      this.isShow = true;
      // 获取焦点
      console.log(this.$refs.input);
      this.$refs.input.focus();
    }
  },
};
</script>

<style  lang="less">
</style>

image.png

可以看出来,this.$refs没有input,所以就没有focus属性。

这是因为在Vue中,在一个回调函数中,不是数据一改变就渲染模板,而是当整个回调运行完以后才重新渲染模板生成新的DOM。

上面的代码就是在showInput()函数的回调中,运行了this.isShow = true,但是此时回调还没运行完,此时页面不会重新渲染模板,input框没出来。此时接着向下运行回调函数中的代码,this.$refs.input.focus(),这时由于页面还没渲染,所以找不到this.$refs.input,当回调中代码运行完以后,才渲染页面,生成新的DOM。

使用nextTick解决:

<template>
  <div>
    <input type="text" v-if="isShow" ref="input" placeholder="输入框"/>
    <button @click="showInput">显示输入框,并获取焦点。</button>
  </div>
</template>

<script>
export default {
  name: "oneComponent",
  data() {
    return {
      isShow: false
    };
  },
  methods: {
    showInput(){
      // 显示输入框
      this.isShow = true;
      // 获取焦点
      this.$nextTick(function(){
        console.log(this.$refs.input);
        this.$refs.input.focus();
      })
    }
  },
};
</script>

<style  lang="less">
</style>

image.png

这样就能正确获取到input框的DOM元素了。