深入解读VUE中的异步渲染的实现

yizhihongxing

深入解读VUE中的异步渲染的实现

Vue中的异步渲染主要是采用了Next Tick机制,将数据的变化尽可能异步处理,从而防止同步过程中出现性能问题。

Next Tick 的实现

Next Tick 是指在下一次事件循环之前执行的操作。Vue 中使用了 microtask(微任务) 实现 Next Tick 机制。在具体实现中,使用了 setImmediate(IE 下支持,性能优于 setTimeout)和 MutationObserver,以及 MessageChannel(主流浏览器支持)等方式实现。
在 Vue 的可响应性系统中,如果你用 setIntervalsetImmediatesetTimeout 等函数应用于更新你的视图或状态,那么将不会实现异步更新。

实现原理示例代码如下:

// Dom 更新需要异步处理
Vue.prototype.$nextTick = function (fn: Function) {
    return nextTick(fn, this)
}

// 做兼容检查,如果浏览器支持 microTask 的话,使用它
if (typeof Promise !== 'undefined' && isNative(Promise)) {
  const p = Promise.resolve()
  resetFn = () => {
    p.then(flushCallbacks)
    // In problematic UIWebViews, Promise.then doesn't completely break, but
    // it can get stuck in a weird state where callbacks are pushed into the
    // microtask queue but the queue isn't being flushed, until the browser
    // needs to do some other work, e.g. handle a timer. Therefore we can
    // "force" the microtask queue to be flushed by adding an empty timer.
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) ||
  // PhantomJS and iOS 7.x
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  // use MutationObserver where native Promise is not available,
  // e.g. PhantomJS IE11, iOS7, Android 4.4
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, {
    characterData: true
  })
  resetFn = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true
} else if (typeof MessageChannel !== 'undefined' && (
  isNative(MessageChannel) ||
  // PhantomJS
  MessageChannel.toString() === '[object MessageChannelConstructor]'
)) {
  // 用 MessageChannel
  const channel = new MessageChannel()
  const port = channel.port2
  channel.port1.onmessage = flushCallbacks
  resetFn = () => {
    port.postMessage(1)
  }
  isUsingMicroTask = true
} else {
  // 使用 setImmediate 或 setTimeout
  /* istanbul ignore next */
  resetFn = () => {
    setTimeout(flushCallbacks, 0)
  }
}

示例

异步更新页面视图

我们在组件中,可以通过异步方式来更新页面的视图。比如,当页面上有个 loading ,在数据请求完成之前,我们可以显示该 loading 信息,等待数据加载完成后再更新页面视图。代码示例如下:

<template>
  <div>
    <p v-if="showLoading">加载中...</p>
    <ul>
      <li v-for="item in items" :key="item.id">{{ item.title }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data () {
    return {
      showLoading: true,
      items: []
    }
  },
  methods: {
    fetchData () {
      // 模拟数据请求操作
      setTimeout(() => {
        // 更新数据
        this.items = [
          { id: 1, title: '文章1' },
          { id: 2, title: '文章2' },
          { id: 3, title: '文章3' }
        ]
        // 更新完数据之后,将 showLoading 设置为 false
        this.showLoading = false
      }, 2000)
    }
  },
  mounted () {
    this.fetchData()
  }
}
</script>

异步更新状态

在 Vue 组件中,我们经常会需要进行状态的更新,在视图的更新中常常使用 v-model 来与组件之间进行数据的双向绑定。但是,如果进行一些特殊操作(比如异步操作)时,需要手动更新状态,改变视图。核心 API 是通过 this.$set()Vue.set() 来实现的。代码示例如下:

<template>
  <div>
    <p>状态:{{ status }}</p>
    <button @click="changeStatus">更改状态</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      status: ''
    }
  },
  methods: {
    changeStatus () {
      setTimeout(() => {
        // 异步更改状态
        this.$set(this, 'status', '已更改')
      }, 2000)
    }
  }
}
</script>

结语

以上就是 Vue 中异步渲染的实现原理与示例。对于我们的开发来说,我们可以借助 Vue 提供的 Next Tick 机制,在特殊场景下使用异步更新视图和状态,从而轻松提升性能和流畅性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入解读VUE中的异步渲染的实现 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • ant design vue嵌套表格及表格内部编辑的用法说明

    Ant Design Vue 是一个基于 Vue.js 的 UI 组件库,是蚂蚁金服开源的一款 UI 组件库,主要目的是为开发人员提供高质量的企业级 UI 组件,支持 react、vue 以及 angular 三个框架。Ant Design Vue 组件库包含众多组件,如按钮、输入框、表格、弹窗、菜单等,最为优秀的一个组件就是表格。在表格中,Ant Desi…

    Vue 2023年5月28日
    00
  • Android面向切面基于AOP实现登录拦截的场景示例

    下面我来为您详细讲解“Android面向切面基于AOP实现登录拦截的场景示例”的完整攻略。 什么是AOP AOP(Aspect Oriented Programming),面向切面编程,是一种编程范式,它旨在解决开发中的横切关注点问题。横切关注点是指在整个应用中有多个不同的模块都需要共同解决的问题,比如日志、事务、缓存等。AOP可以帮助我们把这些横切关注点从…

    Vue 2023年5月28日
    00
  • Vue实现简单可扩展甘特图的方法详解

    Vue实现简单可扩展甘特图的方法详解 甘特图作为一种流行的进度管理工具,已经广泛应用于IT、建筑、工程等领域。在Vue框架下,实现简单可扩展甘特图的方法是比较简单的。 第一步:安装并引入依赖 需要安装npm包vue-gantt-echarts,使用npm或者yarn进行安装,然后在Vue文件中引入。示例如下: <template> <div…

    Vue 2023年5月27日
    00
  • vue3.2自定义弹窗组件结合函数式调用示例详解

    下面我来详细讲解“vue3.2自定义弹窗组件结合函数式调用示例详解”的完整攻略。 1. 简介 在Vue3.2中,我们可以通过自定义弹窗组件来方便地实现页面弹窗的功能,并且通过函数式调用的方式来减少对全局状态的依赖。 2. 自定义弹窗组件 首先,我们需要创建一个自定义的弹窗组件。可以使用Vue3的defineComponent函数来定义组件,代码如下: imp…

    Vue 2023年5月28日
    00
  • vue获取时间戳转换为日期格式代码实例

    本次我们将详细讲解一下“vue获取时间戳转换为日期格式代码实例”。 一、什么是时间戳 时间戳(Timestamp)是指格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。时间戳常用于计算时间间隔和标记时间等情况。 二、获取时间戳 在 Vue 中,可以使用 JavaScript 自带的 Date.now() 方法获取当前时间戳。代码如下: l…

    Vue 2023年5月27日
    00
  • React DnD如何处理拖拽详解

    React DnD是封装的HTML5拖放API的React组件,可用于构建拖放交互功能。下面详细讲解React DnD如何处理拖拽,在这个过程中,将提供两个示例说明。 1. 拖拽源 拖拽源是可以被拖拽的组件。在React DnD中,拖拽源分为两种:简单的拖拽源和自定义拖拽源。 简单拖拽源 简单的拖拽源指的是一个纯组件,该组件可以设置可以被拖拽的数据类型以及数…

    Vue 2023年5月28日
    00
  • Vuex的安装、搭建及案例详解

    Vuex的安装 在使用Vuex之前,需要在项目中安装Vuex依赖包。可以通过npm或者yarn进行安装。 使用npm安装: npm install vuex –save 使用yarn安装: yarn add vuex Vuex的搭建 Vuex的核心概念包括state、mutations、actions、getters和modules。 以下是一个简单的Vu…

    Vue 2023年5月27日
    00
  • 解决antd日期选择组件,添加value就无法点击下一年和下一月问题

    对于 Ant Design 的日期选择组件 DatePicker,如果我们在使用时添加了 value 属性,会发现无法点击下一年和下一月。这是因为添加了 value 属性后,Ant Design 会把组件的选中日期固定为这个值,并禁用掉下一年和下一月的按钮。解决这个问题的方法非常简单,在代码中添加一个叫做 allowClear 的属性,并将该属性的值设为 t…

    Vue 2023年5月29日
    00
合作推广
合作推广
分享本页
返回顶部