Rumah >hujung hadapan web >Soal Jawab bahagian hadapan >Apakah yang dilakukan oleh permulaan vue?

Apakah yang dilakukan oleh permulaan vue?

青灯夜游
青灯夜游asal
2022-12-21 18:44:132922semak imbas
Apa yang

lakukan: 1. Menggabungkan pilihan dan memproses kandungan konfigurasi komponen 2. Memulakan sifat yang berkaitan dengan kitaran hayat contoh vue 3. Memulakan pemantauan acara komponen tersuai 4. Memulakan pemaparan rendering slot yang diperlukan, fungsi pemaparan; dsb.; 5. Panggil fungsi sebelumCreate; 6. Mulakan data yang disuntik; , lekapkan elemen DOM.

Apakah yang dilakukan oleh permulaan vue?

Persekitaran pengendalian tutorial ini: sistem windows7, versi vue3, komputer DELL G3.

Buat tika

Fail src/instance/index.js ialah fail masukan untuk mencipta tika Vue

Akan ada beberapa pencampuran sebelum penciptaan Kaedah, kaedah dan sifat untuk memulakan kejadian

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
Lihat sahaja initMixin di sini dahulu

initMixin(Vue) initialization mixin

Fungsi kaedah initMixin adalah untuk mencampurkan dalam Vue's _init kaedah,_initInti kaedah ialah kaedah berikut

  • Gabungkan konfigurasi pilihan
  • initLifecycle(vm)
  • initEvents(vm)
  • initRender( vm)
  • callHook(vm, 'beforeCreate')
  • initInjections(vm) // selesaikan suntikan sebelum data/props
  • initState(vm)
  • initProvide(vm) // selesaikan sediakan selepas data/props
  • callHook(vm, 'dicipta')

0 konfigurasi pilihan

  vm.$options = mergeOptions(  // 合并options
    resolveConstructorOptions(vm.constructor),
    options || {},
    vm
  )

Gabungkan pilihan dan lekapkan atribut $options pada contoh. Apakah yang digabungkan? Terdapat dua situasi di sini:

  • Memulakan Vue baharu

    Apabila melaksanakan pembina new Vue, parameter ialah objek, iaitu konfigurasi Tersuai pengguna ; ia akan digabungkan dengan kaedah prototaip dan sifat API global yang ditakrifkan sebelum vue serta parameter dalam Vue.mixin global, dan ini akan digabungkan menjadi options baharu, dan akhirnya diberikan kepada Atribut baharu $options.

  • Pemulaan subkomponen

    Jika ia merupakan pemulaan subkomponen, selain menggabungkan perkara di atas, parameter komponen induk juga akan digabungkan jika terdapat induk komponen yang ditakrifkan dalam anak event, props, dsb. pada komponen.

Selepas bergabung, anda boleh mengakses fungsi data yang ditentukan pengguna melalui this.$options.data dan mengakses nama komponen yang ditentukan pengguna melalui this.$options.name Atribut gabungan ini sangat penting, akan digunakan dengan kerap.

1 initLifecycle(vm)

Fungsi utama ialah untuk mengesahkan hubungan ibu bapa-anak komponen dan memulakan beberapa sifat contoh.

export function initLifecycle(vm: Component) {
  const options = vm.$options  // 之前合并的属性
  
  let parent = options.parent;
  if (parent && !options.abstract) { //  找到第一个非抽象父组件
    while (parent.$options.abstract && parent.$parent) {
      parent = parent.$parent
    }
    parent.$children.push(vm)
  }
  
  vm.$parent = parent  // 找到后赋值
  vm.$root = parent ? parent.$root : vm  // 让每一个子组件的$root属性都是根组件
  
  vm.$children = []
  vm.$refs = {}
  
  vm._watcher = null
  ...
  vm._isDestroyed = false
  vm._isBeingDestroyed = false
}

2. initEvents(vm)

Mulakan mendengar acara komponen tersuai, tambahkan ia kepada pada contoh ini. Fungsi utama adalah untuk menambah acara tersuai yang didaftarkan oleh komponen induk menggunakan v-on atau @ ke pusat acara komponen anak.

export function initEvents (vm: Component) {
  vm._events = Object.create(null)  // 事件中心
  vm._hasHookEvent = false
  // init parent attached events
  const listeners = vm.$options._parentListeners // 经过合并options得到的
  if (listeners) {
    updateComponentListeners(vm, listeners)
  }
}

3. initRender(vm)

Mulakan slot, fungsi pemaparan, dsb. yang diperlukan untuk pemaparan. Sebenarnya, ia hanya dua perkara. 1. Pemprosesan slot, 2. $createElm ialah pengisytiharan h dalam fungsi pemaparan

export function initRender(vm) {
  vm._vnode = null
  ...
  vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)  //转化编译器的
  vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)  // 转化手写的
  ...
}

4. Panggil fungsi cangkuk . Kini anda hanya perlu tahu bahawa ia akan melaksanakan kaedah kitaran hayat yang ditentukan pengguna, dan jika terdapat campuran bercampur, ia juga akan dilaksanakan.

Soalan temu bual berkaitan: Bolehkah pembolehubah yang ditakrifkan dalam data boleh diakses melalui ini dalam sebelumCreate hook Mengapa dan apa yang boleh dilakukan oleh cangkuk ini? beforeCreate

> Jawapan: Ia tidak boleh diakses kerana semasa fasa permulaan vue, pembolehubah dalam data belum lagi dipasang pada ini dan nilai akses pada masa ini akan tidak ditentukan . Cangkuk beforeCreate jarang digunakan dalam pembangunan perniagaan harian Apabila kaedah instantl di dalam pemalam dipasang melalui kaedah Vue.use, ia biasanya dilaksanakan dalam cangkuk beforeCreate Ini adalah cara vue-router dan vuex melakukannya.


5. initInjections(vm)

Jujukan pemulaan seterusnya ialah inject => Mulakan inject sebelum props/data Tujuannya adalah untuk menggunakan kandungan yang disuntik dalam props/data

Fungsi utama resolveInject adalah untuk membuat lapisan demi lapisan dari bawah ke atas data yang disuntik pada masa ini

export function resolveInject (inject: any, vm: Component): ?Object {
  if (inject) {
    // inject is :any because flow is not smart enough to figure out cached
    // 首先定义一个result返回找到的结果。
    const result = Object.create(null)
    const keys = hasSymbol
      ? Reflect.ownKeys(inject)
      : Object.keys(inject)
    // 接下来使用双循环查找,外层的for循环会遍历inject的每一项
    for (let i = 0; i < keys.length; i++) {
      const key = keys[i]
      // #6574 in case the inject object is observed...
      if (key === &#39;__ob__&#39;) continue
      const provideKey = inject[key].from
      let source = vm
      //然后再内层使用while循环自底向上的查找inject该项的父级是否有提供对应的依赖。
      while (source) {
        if (source._provided && hasOwn(source._provided, provideKey)) {
          result[key] = source._provided[provideKey]
          break
        }
        source = source.$parent
      }
      if (!source) {
        if (&#39;default&#39; in inject[key]) {
          const provideDefault = inject[key].default
          result[key] = typeof provideDefault === &#39;function&#39;
            ? provideDefault.call(vm)
            : provideDefault
        } else if (process.env.NODE_ENV !== &#39;production&#39;) {
          warn(`Injection "${key}" not found`, vm)
        }
      }
    }
    return result
  }
}

6. initState(vm)

初始化会被使用到的状态,状态包括props,methods,data,computed,watch五个选项。(这里先看props,methods,data)

export function initState (vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.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)
  }
}

6.1 initProps

  • 主要作用是检测子组件接受的值是否符合规则,以及让对应的值可以用this直接访问
function initProps(vm: Component, propsOptions: Object) {  // 第二个参数为验证规则
  const propsData = vm.$options.propsData || {}  // props具体的值 父组件传过来的
  const props = vm._props = {}  // 存放props  组件内可以通过这个访问到传过来的props
  const isRoot = !vm.$parent // 是否是根节点
  if (!isRoot) {   // 不是根节点则关闭响应式
    toggleObserving(false)
  }
  for (const key in propsOptions) {
    const value = validateProp(key, propsOptions, propsData, vm)
    defineReactive(props, key, value)
    if (!(key in vm)) {
      proxy(vm, `_props`, key)  // 代理 this.xx实际上访问的是 this._props.xx
    }
  }
  toggleObserving(true)
}

6.2 initMethods

  • 主要作用是将methods内的方法挂载到this下。
function initMethods (vm: Component, methods: Object) {
  const props = vm.$options.props
  for (const key in methods) {
    if(methods[key] == null) {  // methods[key] === null || methods[key] === undefined 的简写
      warn(`只定义了key而没有相应的value`)
    }
    if(props && hasOwn(props, key)) {
      warn(`方法名和props的key重名了`)
    }
    if((key in vm) && isReserved(key)) {
      warn(`方法名已经存在而且以_或$开头`)
    }
    vm[key] = typeof methods[key] !== &#39;function&#39; ? noop : bind(methods[key], vm)   //  相当于methods[key].bind(vm)
  }
}

6.3 initData

function initData (vm: Component) {
  let data = vm.$options.data
  data = vm._data = typeof data === &#39;function&#39;
    ? getData(data, vm)
    : data || {}
  if (!isPlainObject(data)) {
    data = {}
  }
  // 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 (methods && hasOwn(methods, key)) {
       warn(`和methods内的方法重名了`)
    }
    if (props && hasOwn(props, key)) {
      warn(`和props内的key重名了`)
    } else if (!isReserved(key)) {  // key不能以_或$开头
      proxy(vm, `_data`, key)
    }
  }
  // observe data
  observe(data, true /* asRootData */)
}

initProvide(vm)

很容易看出是把用户传进来的provide选项先获取到,如果是方法则执行一下再挂载到实例的_provided属性,不是则直接挂载到_provided属性

export function initProvide (vm: Component) {
  const provide = vm.$options.provide
  if (provide) {
    vm._provided = typeof provide === &#39;function&#39;
      ? provide.call(vm)
      : provide
  }
}

7.callHook(vm, 'created')

调用 created钩子函数

总结:Vue初始化都做了什么?

1、选项合并,处理组件的配置内容,将传入的options与构造函数本身的options进行合并(用户选项和系统默认的选项进行合并)

2、初始化vue实例生命周期相关的属性,定义了比如:root、root、root、parent、children、children、children、refs

3、初始化自定义组件事件的监听,若存在父监听事件,则添加到该实例上

4、初始化render渲染所需的slots、渲染函数等。其实就两件事:插槽的处理 和 $createElm的声明,也就是 render 函数中的 h 的声明

5、调用 beforeCreate 钩子函数,在这里就能看出一个组件在创建前和后分别做了哪些初始化

6、初始化注入数据,隔代传参时 先inject。作为一个组件,在要给后辈组件提供数据之前,需要先把祖辈传下来的数据注入进来

7、对props,methods,data,computed,watch进行初始化,包括响应式的处理

8、在把祖辈传下来的数据注入进来以后 再初始化provide

9、调用 created 钩子函数,初始化完成,可以执行挂载了

10、挂载到对应DOM元素上。如果组件构造函数设置了el选项,会自动挂载,所以就不用再手动调用$mount去挂载

【相关推荐:vuejs视频教程web前端开发

Atas ialah kandungan terperinci Apakah yang dilakukan oleh permulaan vue?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel sebelumnya:Apakah dua kaedah qs dalam vueArtikel seterusnya:Apakah dua kaedah qs dalam vue