最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解vue 組件注冊(cè)

 更新時(shí)間:2020年11月20日 11:08:21   作者:winter  
這篇文章主要介紹了vue 組件注冊(cè)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)vue 組件的相關(guān)知識(shí),感興趣的朋友可以了解下

一、了解組件注冊(cè)的兩種方式

1.1 全局組件的注冊(cè)方法

//main.js 
import Vue from 'vue' 
import App from './App' 
import router from './router' 
Vue.config.productionTip = false 

let Hello = { 
  name: 'hello', 
  template: '這是全局組件hello' 
} 
Vue.component('hello', Hello) 
new Vue({ 
  el: '#app', 
  router, 
  components: { App }, 
  template: '' 
})

上面我們就通過(guò)Vue.component()注冊(cè)了一個(gè)全局組件hello,接下來(lái)分析源碼實(shí)現(xiàn)的時(shí)候也是基于這個(gè)例子來(lái)進(jìn)行的。

1.2 局部組件的注冊(cè)

 <template>
 <div id="app">
  <img src="./assets/logo.png">
  <HelloWorld/>
 </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
 name: 'App',
 components:{
  HelloWorld
 }
}
</script>

像這樣就注冊(cè)了一個(gè)HelloWorld的局部組件。

二、全局組件注冊(cè)的源碼

1.Vue初始化的時(shí)候,會(huì)調(diào)用initGlobalAPI()

//【代碼塊1】
//代碼所在文件:src/core/global-api/index.js
export function initGlobalAPI(Vue: GlobalAPI){
  //...省略其他無(wú)關(guān)代碼
  initAssetRegisters(Vue)
  //這個(gè)方法就是用于組件注冊(cè)的方法
}

2.在initAssetRegisters()方法中執(zhí)行組件的定義

//【代碼塊2】
//代碼所在文件:src/core/global-api/assets.js
export function initAssetRegister(Vue){
  ASSET_TYPES.forEach(type=>{
    //ASSET_TYPES包括component、directive、filter
    Vue[type] = function(id, definition){
      //...一些條件判斷
      if(type === 'component' && isPlainObject(definition)){
        definition.name = definition.name || id 
        definition = this.options._base.extend(definition) 
        //將definition轉(zhuǎn)換為一個(gè)繼承于Vue的構(gòu)造函數(shù)
      }
      //...其他類型的處理
      
      this.options[type+'s'][id] = definition //將這個(gè)構(gòu)造函數(shù)掛載到Vue.options.components上
      return definition
    }
  })
}

此時(shí),我們可以單步調(diào)試一下我們上面的例子,來(lái)看一下definition一開始是什么,以及執(zhí)行掛載后Vue.options變成了什么樣子:

a.definition: 其實(shí)傳入的時(shí)候就是我們一開始定義的全局組件的具體內(nèi)容

b.Vue.options: 可以看到我們定義的全局組件hello已經(jīng)存在在Vue.options.components上了

3.實(shí)例化組件的時(shí)候,代碼會(huì)執(zhí)行到Vue.prototype._init()上面

//【代碼塊3】
//代碼所在文件:src/core/instance/init.js
Vue.prototype._init = function(options){
  //..省略其他無(wú)關(guān)代碼
  if(options && options._isComponent){ //組件
    initInternalComponent(vm, options)
  }else{ //非組件
    vm.$options = mergeOptions(
      resolveConstructorOptions(vm.constructor),
      options||{},
      vm
    )
  }
}

這里將自己定義的組件的options與Vue.options做了一個(gè)合并,并且賦值給了vm.$options,而通過(guò)【代碼塊2】我們可以知道全局組件的構(gòu)造函數(shù)已經(jīng)被放在了Vue.options.components上,所以經(jīng)過(guò)這一步,vm.$options.components上面也有了全局組件的構(gòu)造函數(shù)。所以現(xiàn)在在任意組件都能拿到全局組件,因?yàn)槿魏谓M件初始化的時(shí)候都會(huì)執(zhí)行這個(gè)合并。

我們可以通過(guò)單步調(diào)試上面的例子看一下現(xiàn)在的vm.$options上面有些什么

4.在創(chuàng)建vnode的過(guò)程中,會(huì)執(zhí)行_createElement方法

//【代碼塊4】
//代碼所在文件:src/core/vdom/create-element.js
export function _createElement(context, tag, data, children, normalization){
  if(typeof tag === 'string'){
    //...
    if(config.isReservedTag(tag)){
      //...保留的html標(biāo)簽
    }else if(isDef(Ctor = resolveAsset(context.$options, 'component', tag))){
      //已經(jīng)注冊(cè)過(guò)的全局組件
      vnode = createComponent(Ctor, data, context, children, tag)
    }else{
      //不是內(nèi)置標(biāo)簽也不是已經(jīng)注冊(cè)過(guò)的組件,就創(chuàng)建一個(gè)全新的vnode
      vnode = new VNode(
        tag, data, children,
        undefined, undefined, context
       )
    }
  }
}

上面代碼中有一個(gè)比較重要的方法resolveAsset(),用于判斷在context.$options.compononts(即vm.$options.components)上面是否能找到這個(gè)組件的構(gòu)造函數(shù),如果能找到,返回這個(gè)構(gòu)造函數(shù),(具體方法見【代碼塊5】)根據(jù)【代碼塊3】我們可以知道如果這個(gè)組件是全局注冊(cè)的組件,那么我們就可以得到這個(gè)構(gòu)造函數(shù),并進(jìn)入這個(gè)else if判斷,通過(guò)createComponent()得到vnode。

5.上面四步已經(jīng)實(shí)現(xiàn)了整個(gè)流程,現(xiàn)在補(bǔ)充看一下resolveAsset()

//【代碼塊5】
//代碼所在文件:src/core/utils/options.js
export function resolveAsset(options, type, id, warnMissing){
   //options即上面調(diào)用的時(shí)候傳入的context.$options, 
   //由【代碼塊3】,vm.$options是由我們自定義的options以及Vue上的options合并而來(lái)的
   //type現(xiàn)在是components
    
   const assets = options[type]
   // check local registration variations first
   if (hasOwn(assets, id)) return assets[id]
   const camelizedId = camelize(id)
   if (hasOwn(assets, camelizedId)) return assets[camelizedId]
   const PascalCaseId = capitalize(camelizedId)
   if (hasOwn(assets, PascalCaseId)) return assets[PascalCaseId]
   // fallback to prototype chain
   const res = assets[id] || assets[camelizedId] || assets[PascalCaseId]
   if (process.env.NODE_ENV !== 'production' && warnMissing && !res) {
    warn(
     'Failed to resolve ' + type.slice(0, -1) + ': ' + id,
     options
    )
   }
   return res
 }

先通過(guò) const assets = options[type] 拿到 assets,然后再嘗試拿 assets[id],這里有個(gè)順序,先直接使用 id 拿,如果不存在,則把 id 變成駝峰的形式再拿,如果仍然不存在則在駝峰的基礎(chǔ)上把首字母再變成大寫的形式再拿,如果仍然拿不到則報(bào)錯(cuò)。這樣說(shuō)明了我們?cè)谑褂?Vue.component(id, definition) 全局注冊(cè)組件的時(shí)候,id 可以是連字符、駝峰或首字母大寫的形式。

三、局部組件的注冊(cè)

1.extend()

組件在執(zhí)行render()的時(shí)候,會(huì)執(zhí)行createComponent函數(shù),在這個(gè)函數(shù)里面會(huì)執(zhí)行extend()函數(shù)生成一個(gè)構(gòu)造函數(shù),也是在這個(gè)extend()函數(shù)中,執(zhí)行了一個(gè)options的合并

//【代碼塊5】
//代碼所在文件:src/core/global-api/extend.js
Vue.entend = function(extendOptions){
  //...
  Sub.options = mergeOptions(
     Super.options, //Vue的options
     extendOptions //定義組件的那個(gè)對(duì)象
  )
  //...
}

可以看出這里是將自己傳入的options(即定義組件的那個(gè)對(duì)象)與Vue.options合并,然后放到Sub.options上,同時(shí),因?yàn)镾ub.options上面合并了Vue的options,所以組件里面也可以拿到全局注冊(cè)的組件。

2.組件初始化

//【代碼塊6(同代碼塊3)】
//代碼所在文件:src/core/instance/init.js
Vue.prototype._init = function(options){
  //..  
  if(options && options._isComponent){
    initInternalComponent(vm, options)
  }else{
    vm.$options = mergeOptions(
      resolveConstructorOptions(vm.constructor),
      options||{},
      vm
    )
  }
}

組件初始化的過(guò)程中會(huì)進(jìn)入if判斷語(yǔ)句,執(zhí)行initInternalComponent()

3.initInternalComponent()

//【代碼塊7】
//代碼所在文件:src/core/instance/init.js
export function initInternalComponent (vm: Component, options: InternalComponentOptions) {
 const opts = vm.$options = Object.create(vm.constructor.options) 
 //vm.constructor即為Sub,在代碼塊5中,我們已經(jīng)將局部組件放在了Sub.options上
 //所以這里將局部組件的構(gòu)造函數(shù)放在了vm.$options上
 //這樣在執(zhí)行【代碼塊4】的時(shí)候同樣也能通過(guò)resolveAsset得到局部注冊(cè)組件的構(gòu)造函數(shù)
 const parentVnode = options._parentVnode
 opts.parent = options.parent
 opts._parentVnode = parentVnode

 //將componentOptions里面的別的屬性賦值給opts
 const vnodeComponentOptions = parentVnode.componentOptions
 opts.propsData = vnodeComponentOptions.propsData
 opts._parentListeners = vnodeComponentOptions.listeners
 opts._renderChildren = vnodeComponentOptions.children
 opts._componentTag = vnodeComponentOptions.tag

 if (options.render) {
  opts.render = options.render
  opts.staticRenderFns = options.staticRenderFns
 }
}

四、總結(jié)

由于全局注冊(cè)的組件是將組件的構(gòu)造函數(shù)擴(kuò)展到了Vue.options.components上,而組件在初始化的時(shí)候都會(huì)將自身options與Vue.options合并,擴(kuò)展到當(dāng)前組件的vm.$options.components下,所以全局組件能在任意組件被使用。而局部注冊(cè)的組件是將組件的構(gòu)造函數(shù)擴(kuò)展到了當(dāng)前組件的vm.$options.components下,所以只能在當(dāng)前組件使用。

以上就是詳解vue 組件注冊(cè)的詳細(xì)內(nèi)容,更多關(guān)于vue 組件注冊(cè)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue實(shí)現(xiàn)可拖拽div大小的方法

    vue實(shí)現(xiàn)可拖拽div大小的方法

    這篇文章主要介紹了vue實(shí)現(xiàn)可拖拽div大小的方法,可封裝為全局方法在項(xiàng)目中所需要地方直接調(diào)用(mixins),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • vue和react中關(guān)于插槽詳解

    vue和react中關(guān)于插槽詳解

    這篇文章主要介紹了vue和react中關(guān)于插槽詳解,slot插槽是Vue對(duì)組件嵌套這種擴(kuò)展機(jī)制的稱謂,在react可以也這樣稱呼,但是并不很常見。不過(guò)叫slot確實(shí)很形象
    2022-08-08
  • 使用vue.js?為基礎(chǔ)的仿QQ聊天室

    使用vue.js?為基礎(chǔ)的仿QQ聊天室

    這篇文章主要為大家介紹了基于vue.js的QQ聊天室,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-12-12
  • vue3.0關(guān)閉eslint校驗(yàn)的3種方法詳解

    vue3.0關(guān)閉eslint校驗(yàn)的3種方法詳解

    這篇文章主要給大家介紹了關(guān)于vue3.0關(guān)閉eslint校驗(yàn)的3種方法,在實(shí)際開發(fā)過(guò)程中,eslint的作用不可估量,文中將關(guān)閉的方法介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • Vue?仿QQ左滑刪除組件功能

    Vue?仿QQ左滑刪除組件功能

    前幾天朋友在做vue項(xiàng)目開發(fā)時(shí),有人反映?IOS?上面的滑動(dòng)點(diǎn)擊有點(diǎn)問(wèn)題,讓我們來(lái)幫忙解決,于是我就重寫了代碼,下面把vue仿qq左滑刪除組件功能分享到腳本之家平臺(tái),需要的朋友參考下吧
    2018-03-03
  • 關(guān)于vue-color-顏色選擇器插件

    關(guān)于vue-color-顏色選擇器插件

    這篇文章主要介紹了關(guān)于vue-color-顏色選擇器插件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Vue2 模板template的四種寫法總結(jié)

    Vue2 模板template的四種寫法總結(jié)

    下面小編就為大家分享一篇Vue2 模板template的四種寫法總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • 在Vue中使用antv的示例代碼

    在Vue中使用antv的示例代碼

    這篇文章主要介紹了在Vue中使用antv的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 解析vue.js中常用v-指令

    解析vue.js中常用v-指令

    本文以click為例給大家介紹vue.js中常用v-指令,可以用 v-on 指令監(jiān)聽 DOM 事件,并在觸發(fā)時(shí)運(yùn)行一些 JavaScript代碼,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2021-10-10
  • useEffect理解React、Vue設(shè)計(jì)理念的不同

    useEffect理解React、Vue設(shè)計(jì)理念的不同

    這篇文章主要為大家介紹了useEffect理解React、Vue設(shè)計(jì)理念的不同詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09

最新評(píng)論

峨眉山市| 通江县| 寻乌县| 灌云县| 武陟县| 定西市| 金湖县| 宁安市| 甘南县| 临猗县| 金山区| 全南县| 高淳县| 双江| 阿鲁科尔沁旗| 兴海县| 额济纳旗| 乌拉特前旗| 黄浦区| 罗山县| 沁阳市| 蓬莱市| 塘沽区| 日土县| 台江县| 望谟县| 齐河县| 房产| 永平县| 松溪县| 礼泉县| 上思县| 绥滨县| 宁南县| 华安县| 阜新| 甘洛县| 铁力市| 江津市| 河西区| 望城县|