vue $mount 和 el的区别说明

(编辑:jimmy 日期: 2024/12/24 浏览:2)

两者在使用效果上没有任何区别,都是为了将实例化后的vue挂载到指定的dom元素中。

如果在实例化vue的时候指定el,则该vue将会渲染在此el对应的dom中,反之,若没有指定el,则vue实例会处于一种“未挂载”的状态,此时可以通过$mount来手动执行挂载。

注:如果$mount没有提供参数,模板将被渲染为文档之外的的元素,并且你必须使用原生DOM API把它插入文档中。

例如:

var MyComponent = Vue.extend({
 template: '<div>Hello!</div>'
})

// 创建并挂载到 #app (会替换 #app)
new MyComponent().$mount('#app')

// 同上
new MyComponent({ el: '#app' })

// 或者,在文档之外渲染并且随后挂载
var component = new MyComponent().$mount()
document.getElementById('app').appendChild(component.$el)

补充知识:Vue 实例挂载方法($mount)的实现

在 Vue 的 _init 方法中已经回调了beforeCreate 和created这两个生命周期钩子,在此之后就进行了实例的挂载

  if (vm.$options.el) { // 挂载实例
   vm.$mount(vm.$options.el);
  }

在挂载函数中,将要进行 beforeMount 和 mounted 的回调。

在不同的平台下对于 $mount 函数的实现是有差异的,下面考虑 web 平台的 runtime-with-compiler 版本 , 其在web平台下的定义如下(src/platforms/web/runtime/index.js)

import { mountComponent } from 'core/instance/lifecycle';

Vue.prototype.$mount = function(
 el"htmlcode">
import Vue from './runtime/index';
const mount = Vue.prototype.$mount; // 缓存 上面的 $mount 方法
Vue.prototype.$mount = function(
 el"htmlcode">
export function mountComponent(
 vm: Component,
 el: "htmlcode">
constructor(
  vm: Component,
  expOrFn: string | Function,
  cb: Function,
  options"htmlcode">
  if (typeof expOrFn === 'function') {
   this.getter = expOrFn;
  }

也就是说updateComponent()方法被设置为了getter()方法

看到构造函数的最后

  this.value = this.lazy
   "htmlcode">
  const vm = this.vm;
  try {
   value = this.getter.call(vm, vm);
  }

我们看到调用了getter()方法,也就是调用了updateComponent()方法。

2. 为什么根实例的$vnode为空

在initRender()函数中有如下代码

const parentVnode = vm.$vnode = options._parentVnode;

也就是说 当前实际的 $vnode 值为其父节点的vnode值

而根实例没有父节点,故其$vnode值就为空了,所以会执行

 if (vm.$vnode == null) {
  vm._isMounted = true;
  callHook(vm, 'mounted');
 }

那么子节点的mounted回调是在那里执行的呢?

在 path()(core/vdom/patch.js) 函数中有如下代码

 function invokeInsertHook(vnode, queue, initial) {
  if (isTrue(initial) && isDef(vnode.parent)) {
   vnode.parent.data.pendingInsert = queue;
  }
  else {
   for (let i = 0; i < queue.length; ++i) {
    queue[i].data.hook.insert(queue[i]); // 这里
   }
  }
 }

在循环queue的时候,调用了 insert()方法,该方法为 VNodeHooks,其在componentVNodeHooks(core/vdom/create-component.js)中声明,代码如下

const componentVNodeHooks = {
 insert(vnode: MountedComponentVNode) {
  const { context, componentInstance } = vnode;

  if (!componentInstance._isMounted) {
   componentInstance._isMounted = true;
   callHook(componentInstance, 'mounted'); // 这里
  }
  if (vnode.data.keepAlive) {
   if (context._isMounted) {
    queueActivatedComponent(componentInstance);
   }
   else {
    activateChildComponent(componentInstance, true /* direct */);
   }
  }
 },
}

由于 path() 方法在 _update()函数中调用,这部不再重点说明。

下节我们将来说说render() 和 _update() 方法的实现

以上这篇vue $mount 和 el的区别说明就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。

一句话新闻

一文看懂荣耀MagicBook Pro 16
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?