Vue ref 和 v-for 結合(ref 源碼解析)
前言
Vue 中組件的使用很方便,而且直接取組件實例的屬性方法等也很方便,其中通過 ref 是最普遍的。
平時使用中主要是對一個組件進行單獨設置 ref ,但是有些場景下可能是通過給定數據渲染的,這時會結合 v-for 一塊使用。那麼在使用的時候具體怎麼寫?為什麼這樣寫?下面就來探究下。
一、ref 和 v-for 結合
1、ref 簡單使用
// html <div ref="testRef"> </div> // js this.$refs.testRef.xxx
2、ref 結合 v-for 使用
<div :ref="'test'+t.code" v-for="t in classList" :key="t.code"></div>
在取值時怎麼取?通過 this.$refs[‘test’+t.code]?
這樣取會發現是一個數組,那就去數組中的第一使用(根據經驗驅使),結果這樣是對的。
this.$refs[`test${t.code}`][0]
用是用對了,那麼為什麼要這樣用呢?我想在 Vue 源碼中一定能夠找到答案的。在 Vue 源碼中的確找到了想要的。
二、Vue 中 ref 註冊解析
直接在 ./src 下搜索 ref,搜索到的挺多的,一個個文件打開看了看,鎖定了一個文件,這個文件就是 ref 的註冊程式碼。(路徑:src\core\vdom\modules\template-ref.ts)
這裡主要看下文件中的 registerRef 函數:
export function registerRef(vnode: VNodeWithData, isRemoval?: boolean) { const ref = vnode.data.ref if (!isDef(ref)) return const vm = vnode.context const refValue = vnode.componentInstance || vnode.elm const value = isRemoval ? null : refValue const $refsValue = isRemoval ? undefined : refValue if (isFunction(ref)) { invokeWithErrorHandling(ref, vm, [value], vm, `template ref function`) return } const isFor = vnode.data.refInFor const _isString = typeof ref === 'string' || typeof ref === 'number' const _isRef = isRef(ref) const refs = vm.$refs if (_isString || _isRef) { // 這裡就是 v-for 綁定時的處理 if (isFor) { const existing = _isString ? refs[ref] : ref.value if (isRemoval) { isArray(existing) && remove(existing, refValue) } else { if (!isArray(existing)) { if (_isString) { refs[ref] = [refValue] setSetupRef(vm, ref, refs[ref]) } else { ref.value = [refValue] } } else if (!existing.includes(refValue)) { existing.push(refValue) } } } else if (_isString) { if (isRemoval && refs[ref] !== refValue) { return } refs[ref] = $refsValue setSetupRef(vm, ref, value) } else if (_isRef) { if (isRemoval && ref.value !== refValue) { return } ref.value = value } else if (__DEV__) { warn(`Invalid template ref type: ${typeof ref}`) } } }
1、函數可以綁定 ref 的值,也可以刪除
2、根據傳入的 node 的 ref 綁定值的類型:string、number、ref、InFor 做不同的處理
3、如果是 InFor 綁定的 ref ,會存儲成數組的方式
所以,到此從源碼中找到 ref 在綁定時,如果是通過 v-for 綁定的,那麼 ref.value 就是數組,在取值時就要按照數組方式取值了。