Home Web Front-end JS Tutorial Vue operates data changes and updates the view

Vue operates data changes and updates the view

May 03, 2018 am 10:28 AM
Change renew view

This time I will bring you vue operation data to change and update the view. What are the precautions for vue operation data to change and update the view? The following is a practical case, let's take a look.

Preface

Three months ago I read the vue source code to analyze how to achieve responsive data. The name of the article is vue source code for responsive data. Final analysis When the data changes, Watcher's update() method will be called. So let's continue to see what update() does after three months. (I have done a project with react-native in the past three months, and I have no intention of summarizing it. Because it seems too simple).

The narrative method of this article is to follow the logic of looking at the source code. The version of vue I checked is 2.5.2. I forked a copy of the source code for recording Note.

Purpose

Only by clarifying the direction of investigation can we reach the goal. Let’s talk about the target behavior first: what method is executed to update the view after the data changes. Then prepare to start with This direction aims to find the answer starting from the entrance of vue source code.

Start from the previous conclusion

Let’s review the previous conclusion first:

When vue is constructed, it will Observer objects are created on data (and some other fields), getters and setters are intercepted, getters trigger dependency collection, and setters trigger notify.

The other object is Watcher, and watch will be called once when registering watch object, thus triggering the getter of the watch object, and collecting the dependencies into the deps of the current Watcher. When any setter of dep is triggered, the current Watcher will be notified to call the update() method of the Watcher.

So here Start by registering the rendering-related Watcher.

The file is found in src/core/instance/lifecycle.js.

new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */)
Copy after login

mountComponent

The rendering-related Watcher is called in the mountComponent() method, so let's search where this method is called. There are only two places, namely src/platforms/web/runtime/index.js and src/platforms/weex /runtime/index.js, taking web as an example:

Vue.prototype.$mount = function (
 el?: string | Element,
 hydrating?: boolean
): Component {
 el = el && inBrowser ? query(el) : undefined
 return mountComponent(this, el, hydrating)
}
Copy after login
It turns out that the $mount() method calls mountComponent(), (or specifying the el field during vue construction will also automatically call $mount() ) method), because the rendering objects of web and weex (what is weex? I have introduced it in other articles before) are different, so when publishing, different files should be introduced and finally different dists cannot be published (this problem is left for later Study the entire process of vue).

The following is the mountComponent method:

export function mountComponent (
 vm: Component,
 el: ?Element,
 hydrating?: boolean
): Component {
 vm.$el = el // 放一份el到自己的属性里
 if (!vm.$options.render) { // render应该经过处理了, 因为我们经常都是用template或者vue文件
 // 判断是否存在render函数, 如果没有就把render函数写成空VNode来避免红错, 并报出黄错
 vm.$options.render = createEmptyVNode
 if (process.env.NODE_ENV !== 'production') {
  /* istanbul ignore if */
  if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||
  vm.$options.el || el) {
  warn(
   'You are using the runtime-only build of Vue where the template ' +
   'compiler is not available. Either pre-compile the templates into ' +
   'render functions, or use the compiler-included build.',
   vm
  )
  } else {
  warn(
   'Failed to mount component: template or render function not defined.',
   vm
  )
  }
 }
 }
 callHook(vm, 'beforeMount')
 let updateComponent
 /* istanbul ignore if */
 if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
 // 不看这里的代码了, 直接看else里的, 行为是一样的
 updateComponent = () => {
  const name = vm._name
  const id = vm._uid
  const startTag = `vue-perf-start:${id}`
  const endTag = `vue-perf-end:${id}`
  mark(startTag)
  const vnode = vm._render()
  mark(endTag)
  measure(`vue ${name} render`, startTag, endTag)
  mark(startTag)
  vm._update(vnode, hydrating)
  mark(endTag)
  measure(`vue ${name} patch`, startTag, endTag)
 }
 } else {
 updateComponent = () => {
  vm._update(vm._render(), hydrating)
 }
 }
 // we set this to vm._watcher inside the watcher's constructor
 // since the watcher's initial patch may call $forceUpdate (e.g. inside child
 // component's mounted hook), which relies on vm._watcher being already defined
 // 注册一个Watcher
 new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */)
 hydrating = false
 // manually mounted instance, call mounted on self
 // mounted is called for render-created child components in its inserted hook
 if (vm.$vnode == null) {
 vm._isMounted = true
 callHook(vm, 'mounted')
 }
 return vm
}
Copy after login
This code actually only does 3 things:

  • Call beforeMount Hook

  • Create Watcher

  • Call mounted hook

(hahaha)Then the core is Create Watcher.

Look at the parameters of Watcher: vm is this, updateComponent is a function, noop is empty, null is empty, true means RenderWatcher.

Look at isRenderWatcher in Watcher :

if (isRenderWatcher) {
  vm._watcher = this
 }
Copy after login
Yes, I just made a copy to judge something when the watcher patches for the first time (from the comments, I still don’t know what it is for).

The only problem that remains unsolved is what updateComponent is.

updateComponent

The second parameter of Watcher's

constructor If the function is passed, then this function becomes the getter of the watcher. If you are smart, you should have guessed that the getters of all the data in the view must be called in this updateComponent, so that dependencies can be established in the watcher so that the view can respond to data changes. .

updateComponent = () => {
  vm._update(vm._render(), hydrating)
 }
Copy after login
Then go to vm._update() and vm._render().

Found the ._render() method in src/core/instance/render.js.

Vue.prototype._render = function (): VNode {
 const vm: Component = this
 const { render, _parentVnode } = vm.$options // todo: render和_parentVnode的由来
 // reset _rendered flag on slots for duplicate slot check
 if (process.env.NODE_ENV !== 'production') {
  for (const key in vm.$slots) {
  // $flow-disable-line
  vm.$slots[key]._rendered = false
  }
 }
 if (_parentVnode) {
  vm.$scopedSlots = _parentVnode.data.scopedSlots || emptyObject
 }
 // set parent vnode. this allows render functions to have access
 // to the data on the placeholder node.
 vm.$vnode = _parentVnode
 // render self
 let vnode
 try {
  vnode = render.call(vm._renderProxy, vm.$createElement)
 } catch (e) {
  // catch其实不需要看了, 都是做异常处理, _vnode是在vm._update的时候保存的, 也就是上次的状态或是null(init的时候给的)
  handleError(e, vm, `render`)
  // return error render result,
  // or previous vnode to prevent render error causing blank component
  /* istanbul ignore else */
  if (process.env.NODE_ENV !== 'production') {
  if (vm.$options.renderError) {
   try {
   vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e)
   } catch (e) {
   handleError(e, vm, `renderError`)
   vnode = vm._vnode
   }
  } else {
   vnode = vm._vnode
  }
  } else {
  vnode = vm._vnode
  }
 }
 // return empty vnode in case the render function errored out
 if (!(vnode instanceof VNode)) {
  if (process.env.NODE_ENV !== 'production' && Array.isArray(vnode)) {
  warn(
   'Multiple root nodes returned from render function. Render function ' +
   'should return a single root node.',
   vm
  )
  }
  vnode = createEmptyVNode()
 }
 // set parent
 vnode.parent = _parentVnode
 return vnode
 }
}
Copy after login
This method does:

  • Generate VNode based on the render method of the current vm. (The render method may be compiled from the template or vue file, so the inference is written directly The render method is the most efficient)

  • If there is a problem with the render method, call the renderError method first, and if it fails, read the last vnode or null.

  • If there is a parent node, put it in its own .parent attribute.

  • Finally return VNode

So the core is this sentence :

vnode = render.call(vm._renderProxy, vm.$createElement)
Copy after login
I don’t know what render(), vm._renderProxy, vm.$createElement are.

先看vm._renderProxy: 是initMixin()的时候设置的, 在生产环境返回vm, 开发环境返回代理, 那么我们认为他是一个可以debug的vm(就是vm), 细节之后再看.

vm.$createElement的代码在vdom文件夹下, 看了下是一个方法, 返回值一个VNode.

render有点复杂, 能不能以后研究, 总之就是把template或者vue单文件和mount目标parse成render函数.

小总结: vm._render()的返回值是VNode, 根据当前vm的render函数

接下来看vm._update()

Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
 const vm: Component = this
 if (vm._isMounted) {
  callHook(vm, 'beforeUpdate')
 }
 // 记录update之前的状态
 const prevEl = vm.$el
 const prevVnode = vm._vnode
 const prevActiveInstance = activeInstance
 activeInstance = vm
 vm._vnode = vnode
 // Vue.prototype.patch is injected in entry points
 // based on the rendering backend used.
 if (!prevVnode) { // 初次加载, 只有_update方法更新vm._vnode, 初始化是null
  // initial render
  vm.$el = vm.patch( // patch创建新dom
  vm.$el, vnode, hydrating, false /* removeOnly */,
  vm.$options._parentElm,
  vm.$options._refElm
  )
  // no need for the ref nodes after initial patch
  // this prevents keeping a detached DOM tree in memory (#5851)
  vm.$options._parentElm = vm.$options._refElm = null
 } else {
  // updates
  vm.$el = vm.patch(prevVnode, vnode) // patch更新dom
 }
 activeInstance = prevActiveInstance
 // update vue reference
 if (prevEl) {
  prevEl.vue = null
 }
 if (vm.$el) {
  vm.$el.vue = vm
 }
 // if parent is an HOC, update its $el as well
 if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
  vm.$parent.$el = vm.$el
 }
 // updated hook is called by the scheduler to ensure that children are
 // updated in a parent's updated hook.
 }
Copy after login

我们关心的部分其实就是patch()的部分, patch()做了对dom的操作, 在_update()里判断了是否是初次调用, 如果是的话创建新dom, 不是的话传入新旧node进行比较再操作.

结论

vue的视图渲染是一种特殊的Watcher, watch的内容是一个函数, 函数运行的过程调用了render函数, render又是由template或者el的dom编译成的(template中含有一些被observe的数据). 所以template中被observe的数据有变化触发Watcher的update()方法就会重新渲染视图.

遗留

render函数是在哪里被编译的
vue源码发布时引入不同平台最后打成dist的流程是什么
patch和VNode的分析

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

jQuery实现输入文字超过规定行数时自动添加省略号

ElTableColumn添加搜索归纳功能

The above is the detailed content of Vue operates data changes and updates the view. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat Commands and How to Use Them
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to fix Blizzard Battle.net update stuck at 45%? How to fix Blizzard Battle.net update stuck at 45%? Mar 16, 2024 pm 06:52 PM

Blizzard Battle.net update keeps stuck at 45%, how to solve it? Recently, many people have been stuck at the 45% progress bar when updating software. They will still get stuck after restarting multiple times. So how to solve this situation? We can reinstall the client, switch regions, and delete files. To deal with it, this software tutorial will share the operation steps, hoping to help more people. Blizzard Battle.net update keeps stuck at 45%, how to solve it? 1. Client 1. First, you need to confirm that your client is the official version downloaded from the official website. 2. If not, users can enter the Asian server website to download. 3. After entering, click Download in the upper right corner. Note: Be sure not to select Simplified Chinese when installing.

Epic Seven's February 22nd update: The second week of Miracle Maid Kingdom begins Epic Seven's February 22nd update: The second week of Miracle Maid Kingdom begins Feb 21, 2024 pm 05:52 PM

Epic Seven has been confirmed to be updated non-stop at 11 noon on February 22. This update will bring us a lot of new activities and content, including an increase in the limited summoning rate of Leia and Sweet Miracle, an update to the mysterious card pool, The second week of the special side story Miracle Maid Kingdom has begun. Let’s take a look at this update. Mobile game update schedule: The Seventh Epic will be updated on February 22nd: The Miracle Maid Kingdom will open for the second week ※The chance of limited summoning of "Leia" & "Sweet Miracle" is up! ■Limited Summoning Chance Up Time: -2024/02/22 (Thursday) 11:00 ~ 2024/03/07 (Thursday) 10:59 ■Character Attributes & Occupations: Natural Attributes, Warrior ■Character Introduction: Four-person Band The sub-vocalist of "Miracle Maid Kingdom" and Bei

Simple steps to update pip version: done in 1 minute Simple steps to update pip version: done in 1 minute Jan 27, 2024 am 09:45 AM

Done in one minute: How to update the pip version, specific code examples are required. With the rapid development of Python, pip has become a standard tool for Python package management. However, as time goes by, pip versions are constantly updated. In order to be able to use the latest features and fix possible security vulnerabilities, it is very important to update the pip version. This article will explain how to quickly update pip in one minute and provide specific code examples. First, we need to open a command line window. In Windows systems, you can use

How to install Angular on Ubuntu 24.04 How to install Angular on Ubuntu 24.04 Mar 23, 2024 pm 12:20 PM

Angular.js is a freely accessible JavaScript platform for creating dynamic applications. It allows you to express various aspects of your application quickly and clearly by extending the syntax of HTML as a template language. Angular.js provides a range of tools to help you write, update and test your code. Additionally, it provides many features such as routing and form management. This guide will discuss how to install Angular on Ubuntu24. First, you need to install Node.js. Node.js is a JavaScript running environment based on the ChromeV8 engine that allows you to run JavaScript code on the server side. To be in Ub

Lantern and Dungeon updated on February 29: Remastered version ╳ 'Legend of Nezha' linkage Lantern and Dungeon updated on February 29: Remastered version ╳ 'Legend of Nezha' linkage Feb 28, 2024 am 08:13 AM

Lantern and Dungeons has been confirmed to be updated on February 29th. After the update, the remastered version of Lantern and Dungeons will be launched, and the remastered version will also be linked to the Legend of Nezha. The remastered version will also bring a new profession, and players can directly Job changes, dungeon content will also be expanded, new dungeon areas will be opened, etc. Mobile game update schedule Lantern and Dungeon updated on February 29th: Remastered version ╳ "Legend of Nezha" linkage version key content New profession, why are you invited to change jobs? Lamplighters can actually change jobs? Such cool equipment is really It makes people greedy. I heard that after changing jobs, the lantern holder can also learn many cool skills. Goro exclaimed: Thai pants are hot! The Legend of Nezha is coming together! Stepping on the hot wheel, holding the circle of heaven and earth in hand ♫ ~ The little heroes with both wisdom and courage: Nezha and Little Dragon Girl are about to come

How to change the starting delivery price of Meituan Takeout merchant version How to change the starting delivery price of Meituan Takeout merchant version Mar 27, 2024 pm 07:20 PM

In the operation process of the Meituan Takeout Merchant Edition, the setting of the starting delivery price is a crucial link. A reasonable starting delivery price can not only help merchants control costs, but also increase order amounts to a certain extent, thus increasing overall revenue. However, many merchants don’t know much about how to modify the minimum delivery price. So in the following article, the editor of this website will bring you detailed starting price setting guide for merchants. If you want to know more, come to the following article to find out! In the Meituan Takeout Merchant Center, log in and enter the store settings, then select store management. In the switch navigation at the top of the store management page, select delivery information, and then click Add Delivery Area to complete the operation. Once you add a location, the corresponding shipping costs will automatically appear. After completing your order, you will receive

Windows cannot access the specified device, path, or file Windows cannot access the specified device, path, or file Jun 18, 2024 pm 04:49 PM

A friend's computer has such a fault. When opening "This PC" and the C drive file, it will prompt "Explorer.EXE Windows cannot access the specified device, path or file. You may not have the appropriate permissions to access the project." Including folders, files, This computer, Recycle Bin, etc., double-clicking will pop up such a window, and right-clicking to open it is normal. This is caused by a system update. If you also encounter this situation, the editor below will teach you how to solve it. 1. Open the registry editor Win+R and enter regedit, or right-click the start menu to run and enter regedit; 2. Locate the registry "Computer\HKEY_CLASSES_ROOT\PackagedCom\ClassInd"

How to update MSI graphics card driver? MSI graphics card driver download and installation steps How to update MSI graphics card driver? MSI graphics card driver download and installation steps Mar 13, 2024 pm 08:49 PM

MSI graphics cards are the mainstream graphics card brand on the market. We know that graphics cards need to install drivers to achieve performance and ensure compatibility. So how to update the MSI graphics card driver to the latest version? Generally, MSI graphics card drivers can be downloaded and installed from the official website. Let’s find out more below. Graphics card driver update method: 1. First, we enter the "MSI official website". 2. After entering, click the "Search" button in the upper right corner and enter your graphics card model. 3. Then find the corresponding graphics card and click on the details page. 4. Then enter the "Technical Support" option above. 5.Finally go to “Driver & Download”

See all articles