vue中$nextTick详细讲解

更新日期: 2021-07-02阅读: 1.3k标签: vue

1.功能描述

今天我们要实现这个一个小功能; 页面渲染完成后展示一个div元素; 当点击这个div元素后; div元素消失; 出现一个input元素;并且input元素聚焦
想必大家我觉得简单,我们一起来看看~ 创建一个组件,组件名称NextTick.vue; 在页面中引入注册。

2.父组件

<template>
  <div>
    <next-tick></next-tick>
  </div>
</template>

<script lang="ts">
import NextTick from "../components/NextTick.vue"
export default {
  name:"About",
  components:{
    NextTick
  },
}
</script>

3.子组件NextTick.vue

<template>
    <div>
        <div>我是组件</div>
        <div v-if="flag" class="sun" @click="handerClick">显示input</div>
        <input v-else ref="inputRef" class="yuelaing"/>
    </div>
</template>
<script>
export default {
    data(){
        return{
            flag:true,
        }
    },
    methods: {
        handerClick(){
            this.flag=false;
            this.$refs.inputRef.focus();
        },
    },
}
</script>

4为什么是undefined

this.flag=false;
this.$refs.inputRef.focus();

当执行页面操作的时候,this.$refs.inputRef.focus(); 是需要消耗时间的(还没有还得及刷新;还是旧的页面) 此时还没有获取到dom元素。 所以会报错。

解决方式1: 
因此只要让页面能够获取元素就行;使用setTimeout
setTimeout(()=>{
this.$refs.inputRef.focus();
},100)

这样来处理这个问题,是可以的; 但是显得非常的不专业;

解决方式2: 

当组件根据最新的data数据,重新在视图上完成渲染后,在执行里面的函调函数

this.$nextTick(()=>{
this.$refs.inputRef.focus();
})


5.将v-if更改为v-show可以获取焦点吗?

有人说:因为v-if是动态创建和销毁; 在创建和销毁的过程中,是需要时间的! 所以才会使用v-if获取不到元素节点
用v-show就可以避免。 感觉说的有点道理? 我们尝试一下将v-if换成v-show
<template>
    <div>
        <div>我是组件</div>
        <div v-show="flag" class="sun" @click="handerClick">显示input</div>
        <input v-show="!flag" ref="inputRef" class="yuelaing"/>
    </div>
</template>
<script>
export default {
    data(){
        return{
            flag:true,
        }
    },
    methods: {
        handerClick(){
            this.flag=false;
            console.log( this.$refs.inputRef);
            this.$refs.inputRef.focus();
        },
    },
}
</script>

6.实际结果

我们发现虽然是页面没有报错,但是还没有聚焦; 改为v-show明显也不能够解决这个问题。
之所以会出现这个问题 是因为子组件中将this.flag=false后, 立刻去执行了下面的代码 this.$refs.inputRef.focus(); 而在执行的时候,视图还没没有来得及刷新; 还是旧的页面,此时还不能够获取到dom元素 因此出现了undefined; 也就是为什么我们加上延时后就可以聚焦了;
当组件根据最新的data数据, 重新在视图上完成渲染后,在执行里面的函调函数 这就是$nextTick的基本用法
this.$nextTick(()=>{
this.$refs.inputRef.focus();
})

7.将组件变成页面可以获取焦点吗?

又有人说:因为是子组件,子组件比父组件后渲染。 所以没有获取到元素节点。 
这也是理由.... 感觉还没有上一个小伙伴说的对 为了解决疑惑。我们决定将子组件变成页面在看看
<template>
  <div>
    <div>我是组件</div>
    <div v-show="flag" class="sun" @click="handerClick">显示input</div>
    <input v-show="!flag" ref="inputRef" class="yuelaing"/>
  </div>
</template>
<script>
export default {
  data(){
    return{
        flag:true,
    }
  },
  methods: {
      handerClick(){
        this.flag=false;
        this.$refs.inputRef.focus();
      },
  },
}
</script>
我们发现仍然不可以; 这就充分说明了: 更新data的数据后,vue并不是实时更新的。 
数据更新到显示到页面有时间差, 我们在时间差内调用页面数据,当然获取不到。 也就是说:Vue在更新 DOM 时是异步执行的

8.为什么会有$nextTick

之所以会有$nextTick; 因为在vue中数据发生变化后; 视图上的dom并不会立刻去跟新; dom的跟新是需要时间的 下面我们通过一个小实验来看一下
<template>
  <div>
    <div ref="unique">
      <h1>{{ cont }}</h1>
    </div>
    <div  class="sun" @click="handerClick">改变值</div>
  </div>
</template>
<script>
export default {
  data(){
    return{
      cont:'我是默认值'
    }
  },
  methods: {
      handerClick(){
        this.cont='我改变了默认值';
        console.log('1==>',this.$refs.unique.innerText);
        this.$nextTick(()=>{
          console.log('2==>',this.$refs.unique.innerText);
        })
      },
  },
}
</script>

我们发现,第一次的值和第二次的值,是不一样的; 因为视图上dom的跟新是需要之间的; 我们在这个之间差内去获取元素值; 仍然是旧值;所以第一次的值是最初的值; 第二次的值才是改变后的值; 由于我们希望跟新数据后,仍然可以立刻获取dom上的值 所以vue提供了$nextTick就可以解决这个问题


9.Vue.nextTick和this.$nextTick差别

Vue.nextTick是全局方法 this.$nextTick( [callback] ) 是实例方法。
我们都知道一个页面可以有多个实例, 也就是说this.$nextTick可以精确到某个实例上。 其实本质上两个是一样的。 只是一个是全局,一个是精确到某一个实例。 精确度不一样而已。

10.使用 nextTick的一个小技巧

我们都知道在生命周期mounted渲染的时候, 不能百分百保证所有的子组件都能够被渲染, 因此我们可以在mounted里面使用 this.$nextTick, 这样就能保证所有的子组件都能被渲染到。
mounted钩子在服务器端渲染期间不被调用。
mounted: function () {
  this.$nextTick(function () {
    //在数据发生变化,
    //重新在视图上完成渲染后,在执行里面的方法
    //这一句话等同与:
   //将回调延迟到下次 DOM 更新循环之后执行
   //等同于:在修改数据之后,然后等待 DOM 更新后在执行
  })
}

链接: https://fly63.com/article/detial/10477

VueJS 实际开发中会遇到的问题

VueJS 实际开发中会遇到的问题,主要写一些 官方手册 上没有写,但是实际开发中会遇到的问题,需要一定知识基础。

vue与后台交互ajax数据

Vue.js是一套构建用户界面的渐进式的前端框架。 vueJS与后台交互数据的方法我所了解的有以下几种

Vuejs讲解之:响应式、过渡效果、过渡状态

Vue是一套构建用户界面的JS渐进式框架。 Vue 只关注视图层, 采用自底向上增量开发的设计。讲解js高级之响应式、过渡效果、过渡状态。

Vue响应式开发,深入理解Vue.js响应式原理

深入理解Vue.js响应式原理。Vue教程有关的视频都讲到,我习惯响应式开发,在更早的Angular1时代,我们叫它:数据绑定(Data Binding)。你只需要在Vue实例的 data() 块中定义一些数据,并绑定到HTML

vue中慎用style的scoped属性

在vue组件中,为了使样式私有化(模块化),不对全局造成污染,可以在style标签上添加scoped属性以表示它的只属于当下的模块,这是一个非常好的举措,但是为什么要慎用呢?因为scoped往往会造成我们在修改公共组件(三方库或者项目定制的组件)的样式困难,需要增加额外的工作量

基于vue移动端UI框架有哪些?vue移动端UI框架总汇

vue现在使用的人越来越多了,这篇文章主要整理一些比较优秀的移动端ui框架,推荐给大家,例如:mint UI、vux、vonic、vant、cube-ui、Muse-ui、Vue-Carbon、YDUI等

使用webpack提升vue应用的4种方式

webpack是开发Vue单页应用必不可少的工具,它能管理复杂的构建步骤,并且优化你的应用大小和性能, 使你的开发工作流更加简单。在这篇文章中,我将解释使用webpack提升你的Vue应用的4种方式,包括:单文件组件、优化Vue构建过程、浏览器缓存管理、代码分离

Vue2.0用户权限控制解决方案

Vue-Access-Control是一套基于Vue/Vue-Router/axios 实现的前端用户权限控制解决方案,通过对路由、视图、请求三个层面的控制,使开发者可以实现任意颗粒度的用户权限控制。

组件化的概念/特性/优点,Vue组件的使用

Web 中的组件其实就是页面组成的一部分,具有高内聚性,低耦合度,互冲突等特点,有利于提高开发效率,方便重复使用,简化调试步骤等。vue 中的组件是一个自定义标签形式,扩展原生的html元素,封装可重用的代码。

Vue2实例详解与生命周期

Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理、数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个Vue实例生成、编译、挂着、销毁等过程进行js控制。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!