欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue2源碼解析之自定義指令

 更新時(shí)間:2023年05月25日 16:51:58   作者:1undefined2  
自定義指令,其實(shí)就是在vue提供的鉤子中寫代碼,這篇文章將從源碼的角度,帶大家深入了解一下Vue2種自定義指令的實(shí)現(xiàn)與使用,需要的可以參考一下

基本使用

自定義指令,其實(shí)就是在vue提供的鉤子中寫代碼,而這個(gè)鉤子的執(zhí)行是在dom渲染的不同階段執(zhí)行不同的鉤子;

自定義指令的兩種方式

// 全局
// 注冊一個(gè)全局自定義指令 `v-focus`  
Vue.directive('focus', {  
    // 當(dāng)被綁定的元素插入到 DOM 中時(shí)……  
    inserted: function (el) {  
        // 聚焦元素  
        el.focus()  
    }  
})
// 組件內(nèi)
directives: {  
    focus: {  
        // 指令的定義  
        inserted: function (el) {  
            el.focus()  
        }  
    }  
}
<input v-focus>

自定義指令中可以使用的鉤子函數(shù):

一個(gè)指令定義對象可以提供如下幾個(gè)鉤子函數(shù) (均為可選):

`bind`:只調(diào)用一次,指令第一次綁定到元素時(shí)調(diào)用。在這里可以進(jìn)行一次性的初始化設(shè)置。

`inserted`:被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用 (僅保證父節(jié)點(diǎn)存在,但不一定已被插入文檔中)。

`update`:所在組件的 VNode 更新時(shí)調(diào)用,**但是可能發(fā)生在其子 VNode 更新之前**。

指令的值可能發(fā)生了改變,也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板

更新 (詳細(xì)的鉤子函數(shù)參數(shù)見下)。

`componentUpdated`:指令所在組件的 VNode **及其子 VNode** 全部更新后調(diào)用。

`unbind`:只調(diào)用一次,指令與元素解綁時(shí)調(diào)用。

鉤子函數(shù)的參數(shù):

`el`:指令所綁定的元素,可以用來直接操作 DOM。
`binding`:一個(gè)對象,包含以下 property:
    `name`:指令名,不包括 `v-` 前綴
    `value`:指令的綁定值,例如:`v-my-directive="1 + 1"` 中,綁定值為 `2`.
    `oldValue`:指令綁定的前一個(gè)值,僅在 `update` 和 `componentUpdated` 鉤子中可用。
    無論值是否改變都可用。
    `expression`:字符串形式的指令表達(dá)式。例如 `v-my-directive="1 + 1"` 中,
    表達(dá)式為 `"1 + 1"`。
    `arg`:傳給指令的參數(shù),可選。例如 `v-my-directive:foo` 中,參數(shù)為 `"foo"`。
    `modifiers`:一個(gè)包含修飾符的對象。例如:`v-my-directive.foo.bar` 中,修飾符對象為 `{ foo: true, bar: true }`。
`vnode`:Vue 編譯生成的虛擬節(jié)點(diǎn)。
`oldVnode`:上一個(gè)虛擬節(jié)點(diǎn),僅在 `update` 和 `componentUpdated` 鉤子中可用。

eg:

<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {  
    bind: function (el, binding, vnode) {  
        var s = JSON.stringify  
        el.innerHTML =  
            'name: ' + s(binding.name) + '<br>' +  
            'value: ' + s(binding.value) + '<br>' +  
            'expression: ' + s(binding.expression) + '<br>' +  
            'argument: ' + s(binding.arg) + '<br>' +  
            'modifiers: ' + s(binding.modifiers) + '<br>' +  
            'vnode keys: ' + Object.keys(vnode).join(', ')  
    }  
})  
new Vue({  
    el: '#hook-arguments-example',  
    data: {  
        message: 'hello!'  
    }  
})

動(dòng)態(tài)指令:

指令的參數(shù)可以是動(dòng)態(tài)的。例如,在 v-mydirective:[argument]="value" 中,argument 參數(shù)可以根據(jù)組件實(shí)例數(shù)據(jù)進(jìn)行更新!這使得自定義指令可以在應(yīng)用中被靈活使用;

源碼解析

模板解析階段

編譯模板解析每個(gè)標(biāo)簽,會(huì)把標(biāo)簽上的屬性解析到一個(gè)對象的attrs屬性上,解析到閉合標(biāo)簽之后,會(huì)調(diào)用閉合標(biāo)簽的回調(diào)方法,方法中會(huì)針對屬性進(jìn)行處理,先處理v-bind,v-on,再處理自定義指令,會(huì)把自定義指令處理之后放在抽象語法樹的directives屬性上;

抽象語法樹生成render函數(shù)階段

解析抽象語法樹生成render函數(shù),directives指令會(huì)被作為render函數(shù)的屬性參數(shù);

render函數(shù)生成虛擬dom階段

執(zhí)行render函數(shù),把自定義指令屬性掛載到虛擬節(jié)點(diǎn)的data下的directives上

生成真實(shí)dom階段

creatElem創(chuàng)建真實(shí)dom的函數(shù)內(nèi)部在創(chuàng)建完真實(shí)dom之后,會(huì)去調(diào)用invokeCreateHooks方法執(zhí)行create相關(guān)的鉤子函數(shù),create函數(shù)內(nèi)部就會(huì)執(zhí)行_update方法;下面進(jìn)行解析_update方法;

// 源碼位置: src/core/vdom/modules/directives.js
export default {
  create: updateDirectives,
  update: updateDirectives,
  destroy: function unbindDirectives (vnode: VNodeWithData) {
    updateDirectives(vnode, emptyNode)
  }
}
function updateDirectives (oldVnode: VNodeWithData, vnode: VNodeWithData) {
  if (oldVnode.data.directives || vnode.data.directives) {
    _update(oldVnode, vnode)
  }
}
function _update (oldVnode, vnode) {
  // 舊節(jié)點(diǎn)不存在就表示是新創(chuàng)建的
  const isCreate = oldVnode === emptyNode
  // 新節(jié)點(diǎn)不存在表示是需要?jiǎng)h除的
  const isDestroy = vnode === emptyNode
  // 舊節(jié)點(diǎn)中的指令集合
  const oldDirs = normalizeDirectives(oldVnode.data.directives, oldVnode.context)
  // 新節(jié)點(diǎn)中的指令集合
  const newDirs = normalizeDirectives(vnode.data.directives, vnode.context)
  // 保存需要執(zhí)行inserted鉤子的指令
  const dirsWithInsert = []
  // 保存需要執(zhí)行update鉤子的指令
  const dirsWithPostpatch = []
  let key, oldDir, dir
  // 遍歷新節(jié)點(diǎn)的指令
  for (key in newDirs) {
    // 獲取到舊節(jié)點(diǎn)中對應(yīng)的指令
    oldDir = oldDirs[key]
    dir = newDirs[key]
    // 如果舊節(jié)點(diǎn)中的指令不存在 表示是新添加的,通過bind進(jìn)行綁定
    if (!oldDir) {
      // new directive, bind
      callHook(dir, 'bind', vnode, oldVnode)
      // 如有inserted就進(jìn)行添加
      if (dir.def && dir.def.inserted) {
        dirsWithInsert.push(dir)
      }
    } else { // 如果舊節(jié)點(diǎn)中的指令存在 表示是需要更新的,執(zhí)行update
      // existing directive, update
      dir.oldValue = oldDir.value
      dir.oldArg = oldDir.arg
      callHook(dir, 'update', vnode, oldVnode)
      if (dir.def && dir.def.componentUpdated) {
        dirsWithPostpatch.push(dir)
      }
    }
  }
  // 如果dirsWithInsert有值
  if (dirsWithInsert.length) {
    // 創(chuàng)建一個(gè)函數(shù),函數(shù)內(nèi)部遍歷dirsWithInsert并且執(zhí)行inserted鉤子
    const callInsert = () => {
      for (let i = 0; i < dirsWithInsert.length; i++) {
        callHook(dirsWithInsert[i], 'inserted', vnode, oldVnode)
      }
    }
    // 如果是新建的,就和insert鉤子進(jìn)行合并執(zhí)行
    if (isCreate) {
      mergeVNodeHook(vnode, 'insert', callInsert)
    } else {
      // 否則執(zhí)行指令中的inserted鉤子
      callInsert()
    }
  }
  // dirsWithPostpatch有值 就合并componentUpdated和postpatch鉤子在dom更新的時(shí)候執(zhí)行
  if (dirsWithPostpatch.length) {
    mergeVNodeHook(vnode, 'postpatch', () => {
      for (let i = 0; i < dirsWithPostpatch.length; i++) {
        callHook(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode)
      }
    })
  }
  // 如果不是新建的
  if (!isCreate) {
    // 遍歷舊節(jié)點(diǎn)中的指令
    for (key in oldDirs) {
      // 如果新節(jié)點(diǎn)中不存在此指令,表示是要解綁的,調(diào)用unbind鉤子
      if (!newDirs[key]) {
        // no longer present, unbind
        callHook(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy)
      }
    }
  }
}

指令的創(chuàng)建,更新和銷毀都是同一個(gè)函數(shù)updateDirectives,而updateDirectives函數(shù)內(nèi)部,判斷就節(jié)點(diǎn)上的指令或新節(jié)點(diǎn)上的指令存在就執(zhí)行_update方法;

export default {
  create: updateDirectives,
  update: updateDirectives,
  destroy: function unbindDirectives (vnode: VNodeWithData) {
    updateDirectives(vnode, emptyNode)
  }
}
function updateDirectives (oldVnode: VNodeWithData, vnode: VNodeWithData) {
  // 舊節(jié)點(diǎn)的指令或新節(jié)點(diǎn)的指令存在
  if (oldVnode.data.directives || vnode.data.directives) {
    _update(oldVnode, vnode)
  }
}

_update函數(shù)內(nèi)部首先聲明了6個(gè)變量;

// 舊節(jié)點(diǎn)不存在就表示是新創(chuàng)建的
const isCreate = oldVnode === emptyNode
// 新節(jié)點(diǎn)不存在表示是需要?jiǎng)h除的
const isDestroy = vnode === emptyNode
// 舊節(jié)點(diǎn)中的指令集合
const oldDirs = normalizeDirectives(oldVnode.data.directives, oldVnode.context)
// 新節(jié)點(diǎn)中的指令集合
const newDirs = normalizeDirectives(vnode.data.directives, vnode.context)
// 保存需要執(zhí)行inserted鉤子的指令
const dirsWithInsert = []
// 保存需要執(zhí)行update鉤子的指令
const dirsWithPostpatch = []

接著遍歷新節(jié)點(diǎn)中的指令,并且保存新舊節(jié)點(diǎn)中對應(yīng)的指令的值;

let key, oldDir, dir
  // 遍歷新節(jié)點(diǎn)的指令
  for (key in newDirs) {
    // 獲取到舊節(jié)點(diǎn)中對應(yīng)的指令
    oldDir = oldDirs[key]
    dir = newDirs[key]

如果舊節(jié)點(diǎn)中的此指令不存在,表示是新添加的,執(zhí)行bind鉤子進(jìn)行綁定,并且判斷是否傳遞了inserted鉤子,如果傳遞了就把當(dāng)前指令存到dirsWithInsert中;

// 如果舊節(jié)點(diǎn)中的指令不存在 表示是新添加的,通過bind進(jìn)行綁定
if (!oldDir) {
  // new directive, bind
  callHook(dir, 'bind', vnode, oldVnode)
  // 如有inserted就進(jìn)行添加
  if (dir.def && dir.def.inserted) {
    dirsWithInsert.push(dir)
  }
}

如果舊節(jié)點(diǎn)中的此指令存在,表示是需要更新,把舊指令的參數(shù)和值保存到新指令對象上,并且執(zhí)行update鉤子,判斷是否傳遞了componentUpdated鉤子,傳遞了就保存到dirsWithPostpatch中;

else { // 如果舊節(jié)點(diǎn)中的指令存在 表示是需要更新的,執(zhí)行update
  // existing directive, update
  dir.oldValue = oldDir.value
  dir.oldArg = oldDir.arg
  callHook(dir, 'update', vnode, oldVnode)
  if (dir.def && dir.def.componentUpdated) {
    dirsWithPostpatch.push(dir)
  }
}

如果dirsWithInsert有值,就創(chuàng)建一個(gè)函數(shù),函數(shù)內(nèi)部遍歷這個(gè)dirsWithInsert,通過callback調(diào)用每一個(gè)指令的inserted鉤子;判斷當(dāng)前節(jié)點(diǎn)是否是新建的,是新創(chuàng)建的就和insert鉤子進(jìn)行合并執(zhí)行,如果不是新創(chuàng)建的直接執(zhí)行inserted鉤子;(為什么需要合并鉤子?是因?yàn)閕nserted鉤子的執(zhí)行時(shí)機(jī)是dom已經(jīng)插入到頁面中,而新創(chuàng)建的節(jié)點(diǎn)被插入到頁面中就會(huì)執(zhí)行insert鉤子,因此把它們進(jìn)行合并,再插入的時(shí)候再去執(zhí)行)

// 如果dirsWithInsert有值
if (dirsWithInsert.length) {
    // 創(chuàng)建一個(gè)函數(shù),函數(shù)內(nèi)部遍歷dirsWithInsert并且執(zhí)行inserted鉤子
    const callInsert = () => {
      for (let i = 0; i < dirsWithInsert.length; i++) {
        callHook(dirsWithInsert[i], 'inserted', vnode, oldVnode)
      }
    }
    // 如果是新建的,就和insert鉤子進(jìn)行合并執(zhí)行
    if (isCreate) {
      mergeVNodeHook(vnode, 'insert', callInsert)
    } else {
      // 否則執(zhí)行指令中的inserted鉤子
      callInsert()
    }
}

如果dirsWithPostpatch有值,就進(jìn)行遍歷執(zhí)行componentUpdated鉤子;

// dirsWithPostpatch有值 就合并componentUpdated和postpatch鉤子在dom更新的時(shí)候執(zhí)行
if (dirsWithPostpatch.length) {
    mergeVNodeHook(vnode, 'postpatch', () => {
      for (let i = 0; i < dirsWithPostpatch.length; i++) {
        callHook(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode)
      }
    })
}

如果不是新創(chuàng)建的,就遍歷舊節(jié)點(diǎn)的指令,判斷新節(jié)點(diǎn)上是否有此指令,沒有就表示需要解綁,那么就執(zhí)行unbind鉤子;

// 如果不是新建的
if (!isCreate) {
    // 遍歷舊節(jié)點(diǎn)中的指令
    for (key in oldDirs) {
      // 如果新節(jié)點(diǎn)中不存在此指令,表示是要解綁的,調(diào)用unbind鉤子
      if (!newDirs[key]) {
        // no longer present, unbind
        callHook(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy)
      }
    }
}

normalizeDirectives函數(shù),把指令的值進(jìn)行格式化處理;

const emptyModifiers = Object.create(null)
/**
 * 獲取到鉤子的值,并且進(jìn)行統(tǒng)一的格式化操作
 * @param {*} dirs 
 * @param {*} vm 
 * @returns 
   格式化之后的結(jié)果
   {
 *  v-focus: {
 *    name: 'focus', // 指令名稱
 *    value: '', // 指令值
 *    arg: '', // 參數(shù)
 *    modifiers: {}, // 修飾符
 *    def: { inserted: fn } // 回調(diào)
 *  }
 * }
 */
function normalizeDirectives (
  dirs: ?Array<VNodeDirective>,
  vm: Component
): { [key: string]: VNodeDirective } {
  // 創(chuàng)建一個(gè)對象
  const res = Object.create(null)
  // 指令不存在直接返回
  if (!dirs) {
    // $flow-disable-line
    return res
  }
  let i, dir
  // 遍歷指令
  for (i = 0; i < dirs.length; i++) {
    dir = dirs[i]
    // 如果修飾符屬性不存在就創(chuàng)建一個(gè)空的對象
    if (!dir.modifiers) {
      // $flow-disable-line
      dir.modifiers = emptyModifiers
    }
    // 添加到對象上
    res[getRawDirName(dir)] = dir
    // 找出指令的值
    dir.def = resolveAsset(vm.$options, 'directives', dir.name, true)
  }
  // $flow-disable-line
  return res
}
function getRawDirName (dir: VNodeDirective): string {
  return dir.rawName || `${dir.name}.${Object.keys(dir.modifiers || {}).join('.')}`
}

callHook函數(shù),內(nèi)部直接執(zhí)行對應(yīng)的hook函數(shù);

function callHook (dir, hook, vnode, oldVnode, isDestroy) {
  const fn = dir.def && dir.def[hook]
  if (fn) {
    try {
      fn(vnode.elm, dir, vnode, oldVnode, isDestroy)
    } catch (e) {
      handleError(e, vnode.context, `directive ${dir.name} ${hook} hook`)
    }
  }
}

小結(jié):

  • _update函數(shù)內(nèi)部,主要通過新舊的判斷是新建還是刪除節(jié)點(diǎn),并且通過一個(gè)方法把指令進(jìn)行格式化處理得到新舊節(jié)點(diǎn)上的新舊指令;
  • 遍歷新指令集合如果舊指令集合中不存在此指令,表示新建,就執(zhí)行bind鉤子,并且把指令存儲(chǔ)到插入指令的數(shù)組中;如果舊指令集合中存在,表示更新,執(zhí)行update鉤子,并且把此指令存入到更新的數(shù)組中;
  • 接著判斷插入指令數(shù)組如果有值,如果當(dāng)前節(jié)點(diǎn)是新建的,那么就合并執(zhí)行insert和inserted鉤子;否則不是新建,直接執(zhí)行inserted鉤子
  • 判斷更新的數(shù)組有值,合并執(zhí)行postpatch和componentUpdated鉤子
  • 最后判斷如果不是新建的節(jié)點(diǎn),并且遍歷舊指令集合,如果在新指令中沒有找到此指令,表示是刪除的,執(zhí)行unbind鉤子;
  • 以上就完成了自定義指令中的各個(gè)鉤子的執(zhí)行,并且_update函數(shù)的執(zhí)行是在dom插入到文檔中之前執(zhí)行的,并且在子組件創(chuàng)建完成之后;

總結(jié)

自定義指令是在模板編譯節(jié)點(diǎn)進(jìn)行解析收集自定義指令屬性的,自定義指令在此階段都是作為屬性被添加到ast的directives上;在render函數(shù)生成虛擬節(jié)點(diǎn)的時(shí)候被作為虛擬節(jié)點(diǎn)的data下的directives屬性;在創(chuàng)建真實(shí)dom之后,就會(huì)執(zhí)行自定義指令的各個(gè)鉤子方法,通過新舊節(jié)點(diǎn)來判斷是新建的還是刪除的還是更新的(舊虛擬dom不存在表示新建,新虛擬dom不存在表示刪除),如果是新建的并且新的指令集合中存在,舊的指令集合中不存在的指令就執(zhí)行bind方法,表示新建并且把當(dāng)前指令添加到插入數(shù)組中;如果舊指令集合中存在此指令,表示更新,執(zhí)行update方法并且插入到更新數(shù)組中;如果插入數(shù)組有值,并且是新增的節(jié)點(diǎn)就合并執(zhí)行insert和inserted方法;如果不是新增就執(zhí)行inserted方法;如果更新數(shù)組有值,直接合并執(zhí)行postpatch和componentUpdated方法;最后遍歷舊指令集合如果舊的存在新的不存在那么表示刪除,直接調(diào)用unbind方法;(自定義指令其實(shí)就是在對應(yīng)的dom創(chuàng)建之后還未插入到文檔中之前,通過新舊虛擬節(jié)點(diǎn)和新舊指令判斷是新建的還是更新的還是刪除的,從而執(zhí)行不同的鉤子函數(shù))

到此這篇關(guān)于Vue2源碼解析之自定義指令的文章就介紹到這了,更多相關(guān)Vue2自定義指令內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決IOS端微信H5頁面軟鍵盤彈起后頁面下方留白的問題

    解決IOS端微信H5頁面軟鍵盤彈起后頁面下方留白的問題

    微信H5項(xiàng)目,ios端出現(xiàn)了軟鍵盤輸完隱藏后頁面不會(huì)回彈,下方會(huì)有一大塊留白。這篇文章主要介紹了決微信H5頁面軟鍵盤彈起后頁面下方留白的問題(iOS端) ,需要的朋友可以參考下
    2019-06-06
  • vue iview實(shí)現(xiàn)動(dòng)態(tài)新增和刪除

    vue iview實(shí)現(xiàn)動(dòng)態(tài)新增和刪除

    這篇文章主要為大家詳細(xì)介紹了vue iview實(shí)現(xiàn)動(dòng)態(tài)新增和刪除,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • webpack vue項(xiàng)目開發(fā)環(huán)境局域網(wǎng)訪問方法

    webpack vue項(xiàng)目開發(fā)環(huán)境局域網(wǎng)訪問方法

    下面小編就為大家分享一篇webpack vue項(xiàng)目開發(fā)環(huán)境局域網(wǎng)訪問方法,具有很好的參考價(jià)值,希望對大家有所幫助,一起跟隨小編過來看看吧
    2018-03-03
  • Vue使用vue-draggable 插件在不同列表之間拖拽功能

    Vue使用vue-draggable 插件在不同列表之間拖拽功能

    這篇文章主要介紹了使用vue-draggable 插件在不同列表之間拖拽,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Vue3播放m3u8視頻的兩種實(shí)現(xiàn)方式示例

    Vue3播放m3u8視頻的兩種實(shí)現(xiàn)方式示例

    這篇文章主要介紹了Vue3播放m3u8視頻的兩種實(shí)現(xiàn)方式,兩種視頻播放器組件分別是vue3-video-play和chimee-player,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-01-01
  • 十分鐘帶你快速上手Vue3過渡動(dòng)畫

    十分鐘帶你快速上手Vue3過渡動(dòng)畫

    在開發(fā)中我們想要給一個(gè)組件的顯示和消失添加某種過渡動(dòng)畫,可以很好的增加用戶體驗(yàn),下面這篇文章主要給大家介紹了關(guān)于如何快速上手Vue3過渡動(dòng)畫的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • vue-router 路由傳參問題(路由傳參方式)

    vue-router 路由傳參問題(路由傳參方式)

    路由傳參主要有兩種方式一種是路徑傳參一種是參數(shù)傳遞,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-11-11
  • vue之?dāng)?shù)據(jù)交互實(shí)例代碼

    vue之?dāng)?shù)據(jù)交互實(shí)例代碼

    本篇文章主要介紹了vue之?dāng)?shù)據(jù)交互實(shí)例代碼,vue中也存在像ajax和jsonp的數(shù)據(jù)交互,實(shí)現(xiàn)向服務(wù)器獲取數(shù)據(jù),有興趣的可以了解一下
    2017-06-06
  • 在Vue渲染模板時(shí)保留HTML注釋的方法

    在Vue渲染模板時(shí)保留HTML注釋的方法

    在使用 Vue.js 進(jìn)行開發(fā)時(shí),模板中的 HTML 注釋通常會(huì)被 Vue 的編譯器自動(dòng)移除,然而,在某些情況下,我們可能希望保留這些注釋,例如為了調(diào)試、文檔生成或其他特殊需求,本文將詳細(xì)介紹如何在 Vue 渲染模板時(shí)保留 HTML 注釋,并提供相關(guān)的代碼示例,需要的朋友可以參考下
    2025-03-03
  • vue 父組件通過$refs獲取子組件的值和方法詳解

    vue 父組件通過$refs獲取子組件的值和方法詳解

    今天小編就為大家分享一篇vue 父組件通過$refs獲取子組件的值和方法詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11

最新評(píng)論