検索
ホームページウェブフロントエンドVue.jsVue インスタンスをマウントするにはどうすればよいですか?インスタンスのマウントのプロセスについて話しましょう

Vue インスタンスをマウントするにはどうすればよいですか?次の記事では、Vue インスタンスのマウントのプロセスについて説明します。お役に立てば幸いです。

Vue インスタンスをマウントするにはどうすればよいですか?インスタンスのマウントのプロセスについて話しましょう

Vue2 は長い間注目されており、Vue3 さえも使用され始めています。誰もが Vue2 を徐々に習得する必要があります。さらに深く考えると、たとえ大手メーカーと関わりたくないとしても、ソースコードレベルに到達するよう努めるべきです。 Vueインスタンスのマウント処理はインタビューでもよく登場するテストポイントですが、今回はソースコードをもとにステップバイステップで分析していきます! (学習ビデオ共有: vuejs チュートリアル)

1. 思考

誰もが聞いたことがある知っている、知っているそれじゃあこの文。

では、new Vue()について考えたことがあるかどうかはわかりませんが、このプロセスでは正確に何が行われるのでしょうか?

プロセスでは、データのバインドを完了する方法、データをビューにレンダリングする方法などを説明します。

2. 分析

最初に Vue

のコンストラクターを見つけます。ソース コードの場所: src/core/インスタンス /index.js

function Vue (options) {
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}

options は、data、methods、およびその他の一般的に使用されるメソッドなど、ユーザーによって渡される構成項目です。

Vue構築関数は _init メソッドを呼び出しますが、このメソッドはこのファイルには存在しないことがわかりましたが、よく見ると次のことがわかります。ファイルの最後には多くの初期化メソッドが定義されています。

initMixin(Vue);     // 定义 _init
stateMixin(Vue);    // 定义 $set $get $delete $watch 等
eventsMixin(Vue);   // 定义事件  $on  $once $off $emit
lifecycleMixin(Vue);// 定义 _update  $forceUpdate  $destroy
renderMixin(Vue);   // 定义 _render 返回虚拟dom

まず、initMixin メソッドを確認すると、このメソッドが Vue プロトタイプの _init メソッドを定義していることがわかります。

ソース コードの場所: src/core/instance/init.js

Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    // a uid
    vm._uid = uid++
    let startTag, endTag
    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      startTag = `vue-perf-start:${vm._uid}`
      endTag = `vue-perf-end:${vm._uid}`
      mark(startTag)
    }

    // a flag to avoid this being observed
    vm._isVue = true
    // merge options
    // 合并属性,判断初始化的是否是组件,这里合并主要是 mixins 或 extends 的方法
    if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else { // 合并vue属性
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }
    /* istanbul ignore else */
    if (process.env.NODE_ENV !== 'production') {
      // 初始化proxy拦截器
      initProxy(vm)
    } else {
      vm._renderProxy = vm
    }
    // expose real self
    vm._self = vm
    // 初始化组件生命周期标志位
    initLifecycle(vm)
    // 初始化组件事件侦听
    initEvents(vm)
    // 初始化渲染方法
    initRender(vm)
    callHook(vm, 'beforeCreate')
    // 初始化依赖注入内容,在初始化data、props之前
    initInjections(vm) // resolve injections before data/props
    // 初始化props/data/method/watch/methods
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')

    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      vm._name = formatComponentName(vm, false)
      mark(endTag)
      measure(`vue ${vm._name} init`, startTag, endTag)
    }
    // 挂载元素
    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  }

上記のコードを注意深く読むと、次の結論が得られます:

  • beforeCreate を呼び出す前に、データの初期化が完了していません。dataprops などのプロパティにはアクセスできません。 ## 作成時
  • 、データは初期化されており、属性
  • data および props にアクセスできますが、dom のマウントは完了していませんしたがって、dom 要素にはアクセスできません。 マウント方法は、vm.$mount
  • メソッドを呼び出すことです
  • initState
メソッドはcomplete

props/ data/method/ watch/methods の初期化。 ソースコードの場所: src/core/instance/state.js

export function initState (vm: Component) {
  // 初始化组件的watcher列表
  vm._watchers = []
  const opts = vm.$options
  // 初始化props
  if (opts.props) initProps(vm, opts.props)
  // 初始化methods方法
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    // 初始化data  
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}
ここでは主に data

## の初期化方法を見ていきます。 # initData

(これは initState<pre class='brush:php;toolbar:false;'>function initData (vm: Component) { let data = vm.$options.data // 获取到组件上的data data = vm._data = typeof data === &amp;#39;function&amp;#39; ? getData(data, vm) : data || {} if (!isPlainObject(data)) { data = {} process.env.NODE_ENV !== &amp;#39;production&amp;#39; &amp;&amp; warn( &amp;#39;data functions should return an object:\n&amp;#39; + &amp;#39;https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function&amp;#39;, vm ) } // proxy data on instance const keys = Object.keys(data) const props = vm.$options.props const methods = vm.$options.methods let i = keys.length while (i--) { const key = keys[i] if (process.env.NODE_ENV !== &amp;#39;production&amp;#39;) { // 属性名不能与方法名重复 if (methods &amp;&amp; hasOwn(methods, key)) { warn( `Method &quot;${key}&quot; has already been defined as a data property.`, vm ) } } // 属性名不能与state名称重复 if (props &amp;&amp; hasOwn(props, key)) { process.env.NODE_ENV !== &amp;#39;production&amp;#39; &amp;&amp; warn( `The data property &quot;${key}&quot; is already declared as a prop. ` + `Use prop default value instead.`, vm ) } else if (!isReserved(key)) { // 验证key值的合法性 // 将_data中的数据挂载到组件vm上,这样就可以通过this.xxx访问到组件上的数据 proxy(vm, `_data`, key) } } // observe data // 响应式监听data是数据的变化 observe(data, true /* asRootData */) }</pre> と同じファイル上にあります) 上記のコードを注意深く読むと、次の結論が得られます:

初期化sequence:

props

,
    methods
  • , datadata(コンポーネントを定義するときに関数形式またはオブジェクト形式を選択できます) Functional 形式のみ可能です)
  • データの応答性については、ここでは詳細な説明は行いません。 前述したように、マウント方法は vm.$mount
  • メソッドを呼び出すことです。

ソース コード: <pre class='brush:php;toolbar:false;'>Vue.prototype.$mount = function ( el?: string | Element, hydrating?: boolean ): Component { // 获取或查询元素 el = el &amp;&amp; query(el) /* istanbul ignore if */ // vue 不允许直接挂载到body或页面文档上 if (el === document.body || el === document.documentElement) { process.env.NODE_ENV !== &amp;#39;production&amp;#39; &amp;&amp; warn( `Do not mount Vue to &lt;html&gt; or &lt;body&gt; - mount to normal elements instead.` ) return this } const options = this.$options // resolve template/el and convert to render function if (!options.render) { let template = options.template // 存在template模板,解析vue模板文件 if (template) { if (typeof template === &amp;#39;string&amp;#39;) { if (template.charAt(0) === &amp;#39;#&amp;#39;) { template = idToTemplate(template) /* istanbul ignore if */ if (process.env.NODE_ENV !== &amp;#39;production&amp;#39; &amp;&amp; !template) { warn( `Template element not found or is empty: ${options.template}`, this ) } } } else if (template.nodeType) { template = template.innerHTML } else { if (process.env.NODE_ENV !== &amp;#39;production&amp;#39;) { warn(&amp;#39;invalid template option:&amp;#39; + template, this) } return this } } else if (el) { // 通过选择器获取元素内容 template = getOuterHTML(el) } if (template) { /* istanbul ignore if */ if (process.env.NODE_ENV !== &amp;#39;production&amp;#39; &amp;&amp; config.performance &amp;&amp; mark) { mark(&amp;#39;compile&amp;#39;) } /** * 1.将temmplate解析ast tree * 2.将ast tree转换成render语法字符串 * 3.生成render方法 */ const { render, staticRenderFns } = compileToFunctions(template, { outputSourceRange: process.env.NODE_ENV !== &amp;#39;production&amp;#39;, shouldDecodeNewlines, shouldDecodeNewlinesForHref, delimiters: options.delimiters, comments: options.comments }, this) options.render = render options.staticRenderFns = staticRenderFns /* istanbul ignore if */ if (process.env.NODE_ENV !== &amp;#39;production&amp;#39; &amp;&amp; config.performance &amp;&amp; mark) { mark(&amp;#39;compile end&amp;#39;) measure(`vue ${this._name} compile`, &amp;#39;compile&amp;#39;, &amp;#39;compile end&amp;#39;) } } } return mount.call(this, el, hydrating) }</pre> 上記のコードを読むと、次の結論が得られます。

ルート要素を

body

または
    html
  • オブジェクトに定義できますtemplate/render または直接使用します
  • template
  • el は、要素セレクター が最終的に render 関数に解析され、呼び出しが行われることを意味します。
  • compileToFunctions
  • templaterender 関数に解析しますtemplate
  • を解析する手順は大まかに分けられます

html

ドキュメントのフラグメントを
    ast
  • 記述子に解析ast 記述子を文字列に解析
  • GeneraterenderFunction
  • render
  • 関数を生成します。
vm

にマウントした後、 mount メソッドが再度呼び出されます ソース コードの場所: src/platforms/web/runtime/index.js

// public mount method
Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
): Component {
  el = el && inBrowser ? query(el) : undefined
  // 渲染组件
  return mountComponent(this, el, hydrating)
}

Calling mountComponentレンダリング コンポーネント

export function mountComponent (
  vm: Component,
  el: ?Element,
  hydrating?: boolean
): Component {
  vm.$el = el
  // 如果没有获取解析的render函数,则会抛出警告
  // render是解析模板文件生成的
  if (!vm.$options.render) {
    vm.$options.render = createEmptyVNode
    if (process.env.NODE_ENV !== &#39;production&#39;) {
      /* istanbul ignore if */
      if ((vm.$options.template && vm.$options.template.charAt(0) !== &#39;#&#39;) ||
        vm.$options.el || el) {
        warn(
          &#39;You are using the runtime-only build of Vue where the template &#39; +
          &#39;compiler is not available. Either pre-compile the templates into &#39; +
          &#39;render functions, or use the compiler-included build.&#39;,
          vm
        )
      } else {
        // 没有获取到vue的模板文件
        warn(
          &#39;Failed to mount component: template or render function not defined.&#39;,
          vm
        )
      }
    }
  }
  // 执行beforeMount钩子
  callHook(vm, &#39;beforeMount&#39;)

  let updateComponent
  /* istanbul ignore if */
  if (process.env.NODE_ENV !== &#39;production&#39; && config.performance && mark) {
    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 = () => {
      // 实际调⽤是在lifeCycleMixin中定义的_update和renderMixin中定义的_render
      vm._update(vm._render(), hydrating)
    }
  }
  // we set this to vm._watcher inside the watcher&#39;s constructor
  // since the watcher&#39;s initial patch may call $forceUpdate (e.g. inside child
  // component&#39;s mounted hook), which relies on vm._watcher being already defined
  // 监听当前组件状态,当有数据变化时,更新组件
  new Watcher(vm, updateComponent, noop, {
    before () {
      if (vm._isMounted && !vm._isDestroyed) {
        // 数据更新引发的组件更新
        callHook(vm, &#39;beforeUpdate&#39;)
      }
    }
  }, 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, &#39;mounted&#39;)
  }
  return vm
}

上記のコードを読むと、次の結論が得られます:

beforeCreate

フック
  • define ## をトリガーします。 #updateComponentページ ビューをレンダリングするメソッド
  • コンポーネント データをリッスンし、変更されたら、
  • beforeUpdateライフ フック
  • updateComponent メソッドは主に
  • vue
初期化中に実行されます。 宣言された

renderupdate メソッド render が主に使用されます。 vnode

ソース コードを生成する場所: src/core/instance/render.js

// 定义vue 原型上的render方法
Vue.prototype._render = function (): VNode {
    const vm: Component = this
    // render函数来自于组件的option
    const { render, _parentVnode } = vm.$options

    if (_parentVnode) {
        vm.$scopedSlots = normalizeScopedSlots(
            _parentVnode.data.scopedSlots,
            vm.$slots,
            vm.$scopedSlots
        )
    }

    // 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 {
        // There&#39;s no need to maintain a stack because all render fns are called
        // separately from one another. Nested component&#39;s render fns are called
        // when parent component is patched.
        currentRenderingInstance = vm
        // 调用render方法,自己的独特的render方法, 传入createElement参数,生成vNode
        vnode = render.call(vm._renderProxy, vm.$createElement)
    } catch (e) {
        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 !== &#39;production&#39; && 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
        }
    } finally {
        currentRenderingInstance = null
    }
    // if the returned array contains only a single node, allow it
    if (Array.isArray(vnode) && vnode.length === 1) {
        vnode = vnode[0]
    }
    // return empty vnode in case the render function errored out
    if (!(vnode instanceof VNode)) {
        if (process.env.NODE_ENV !== &#39;production&#39; && Array.isArray(vnode)) {
            warn(
                &#39;Multiple root nodes returned from render function. Render function &#39; +
                &#39;should return a single root node.&#39;,
                vm
            )
        }
        vnode = createEmptyVNode()
    }
    // set parent
    vnode.parent = _parentVnode
    return vnode
}

_updateメイン関数は、patch

を呼び出し、

vnode## を挿入します。 #実数のDOMに変換し、ページソース コードの場所: src に更新します。 /core/instance/lifecycle.js<pre class='brush:php;toolbar:false;'>Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) { const vm: Component = this const prevEl = vm.$el const prevVnode = vm._vnode // 设置当前激活的作用域 const restoreActiveInstance = setActiveInstance(vm) vm._vnode = vnode // Vue.prototype.__patch__ is injected in entry points // based on the rendering backend used. if (!prevVnode) { // initial render // 执行具体的挂载逻辑 vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */) } else { // updates vm.$el = vm.__patch__(prevVnode, vnode) } restoreActiveInstance() // 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 &amp;&amp; vm.$parent &amp;&amp; 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&amp;#39;s updated hook. }</pre><h2 id="strong-三-结论-strong"><strong>三、结论</strong></h2> <ul> <li> <code>new Vue的时候会调用_init方法

  • 定义$set$get$delete$watch等方法
  • 定义$on$off$emit$off等事件
  • 定义_update$forceUpdate$destory生命周期
  • 调用$mount进行页面的挂载
  • 挂载的时候主要是通过mountComponent方法
  • 定义updateComponent更新函数
  • 执行render生成虚拟DOM
  • _update将虚拟DOM生成真实DOM结构,并且渲染到页面中
  • (学习视频分享:web前端开发编程入门

    以上がVue インスタンスをマウントするにはどうすればよいですか?インスタンスのマウントのプロセスについて話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明
    この記事は掘金社区で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
    Vue.jsとReactの未来:傾向と予測Vue.jsとReactの未来:傾向と予測May 09, 2025 am 12:12 AM

    Vue.jsとReactの将来の傾向と予測は次のとおりです。1)Vue.jsはエンタープライズレベルのアプリケーションで広く使用され、サーバー側のレンダリングおよび静的サイト生成でブレークスルーを行いました。 2)Reactは、サーバーコンポーネントとデータ収集で革新され、並行性モデルをさらに最適化します。

    Netflixのフロントエンド:テクノロジースタックに深く潜りますNetflixのフロントエンド:テクノロジースタックに深く潜りますMay 08, 2025 am 12:11 AM

    Netflixのフロントエンドテクノロジースタックは、主にReactとReduxに基づいています。 1.反応は、高性能のシングルページアプリケーションを構築するために使用され、コンポーネント開発を通じてコードの再利用性とメンテナンスを改善します。 2。国家管理には、状態の変更が予測可能で追跡可能であることを確認するために、国家管理に使用されます。 3.ツールチェーンには、コードの品質とパフォーマンスを確保するために、Webpack、Babel、Jest、および酵素が含まれています。 4.パフォーマンスの最適化は、ユーザーエクスペリエンスを向上させるためのコードセグメンテーション、怠zyな読み込み、サーバー側のレンダリングを通じて達成されます。

    Vue.jsおよびFrontend:インタラクティブなユーザーインターフェイスの構築Vue.jsおよびFrontend:インタラクティブなユーザーインターフェイスの構築May 06, 2025 am 12:02 AM

    Vue.jsは、非常にインタラクティブなユーザーインターフェイスを構築するのに適したプログレッシブフレームワークです。そのコア機能には、レスポンシブシステム、コンポーネント開発、ルーティング管理が含まれます。 1)レスポンシブシステムは、Object.DefinePropertyまたはプロキシを介したデータ監視を実現し、インターフェイスを自動的に更新します。 2)コンポーネント開発により、インターフェイスを再利用可能なモジュールに分割できます。 3)Vuerouterは、ユーザーエクスペリエンスを向上させるための単一ページアプリケーションをサポートしています。

    Vuejsの欠点は何ですか?Vuejsの欠点は何ですか?May 05, 2025 am 12:06 AM

    vue.jsの主な欠点には次のものが含まれます。1。エコシステムは比較的新しいものであり、サードパーティのライブラリとツールは他のフレームワークほど豊富ではありません。 2。複雑な関数では、学習曲線が急になります。 3.コミュニティのサポートとリソースは、反応や角度ほど広範ではありません。 4.パフォーマンスの問題は、大規模なアプリケーションで発生する可能性があります。 5。バージョンのアップグレードと互換性の課題が大きくなります。

    Netflix:フロントエンドフレームワークを発表しますNetflix:フロントエンドフレームワークを発表しますMay 04, 2025 am 12:16 AM

    Netflixは、Reactをフロントエンドフレームワークとして使用します。 1.反応のコンポーネント開発と仮想DOMメカニズムは、パフォーマンスと開発効率を向上させます。 2。WebpackとBabelを使用して、コードの構築と展開を最適化します。 3.パフォーマンスの最適化のために、コードセグメンテーション、サーバー側のレンダリング、キャッシュ戦略を使用します。

    Vue.jsによるフロントエンド開発:利点とテクニックVue.jsによるフロントエンド開発:利点とテクニックMay 03, 2025 am 12:02 AM

    Vue.jsの人気の理由には、シンプルさと簡単な学習、柔軟性、高性能が含まれます。 1)そのプログレッシブフレームワークの設計は、初心者が段階的に学ぶのに適しています。 2)コンポーネントベースの開発により、コードの保守性とチームコラボレーション効率が向上します。 3)レスポンシブシステムと仮想DOMは、レンダリングパフォーマンスを改善します。

    Vue.js vs. React:使いやすさと学習曲線Vue.js vs. React:使いやすさと学習曲線May 02, 2025 am 12:13 AM

    Vue.jsは使いやすく、スムーズな学習曲線があり、初心者に適しています。 Reactは急な学習曲線を持っていますが、柔軟性が強いため、経験豊富な開発者に適しています。 1.Vue.jsは、単純なデータバインディングとプログレッシブデザインを介して簡単に始められます。 2.反応には、仮想DOMとJSXを理解する必要がありますが、より高い柔軟性とパフォーマンスの利点を提供します。

    Vue.js vs. React:どのフレームワークがあなたに適していますか?Vue.js vs. React:どのフレームワークがあなたに適していますか?May 01, 2025 am 12:21 AM

    Vue.JSは、高速開発や小規模プロジェクトに適していますが、Reactは大規模で複雑なプロジェクトにより適しています。 1.Vue.jsは簡単で学習しやすく、迅速な開発や小規模プロジェクトに適しています。 2.反応は強力で、大規模で複雑なプロジェクトに適しています。 3. Vue.jsの進歩的な特徴は、徐々に機能を導入するのに適しています。 4。複雑なUIおよびデータ集約型アプリケーションを扱うとき、Reactのコンポーネントと仮想DOMはうまく機能します。

    See all articles

    ホットAIツール

    Undresser.AI Undress

    Undresser.AI Undress

    リアルなヌード写真を作成する AI 搭載アプリ

    AI Clothes Remover

    AI Clothes Remover

    写真から衣服を削除するオンライン AI ツール。

    Undress AI Tool

    Undress AI Tool

    脱衣画像を無料で

    Clothoff.io

    Clothoff.io

    AI衣類リムーバー

    Video Face Swap

    Video Face Swap

    完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

    ホットツール

    SublimeText3 Linux 新バージョン

    SublimeText3 Linux 新バージョン

    SublimeText3 Linux 最新バージョン

    Dreamweaver Mac版

    Dreamweaver Mac版

    ビジュアル Web 開発ツール

    EditPlus 中国語クラック版

    EditPlus 中国語クラック版

    サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

    ZendStudio 13.5.1 Mac

    ZendStudio 13.5.1 Mac

    強力な PHP 統合開発環境

    MantisBT

    MantisBT

    Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。