• Vue ref 和 v-for 结合(ref 源码解析)


    前言

    Vue 中组件的使用很方便,而且直接取组件实例的属性方法等也很方便,其中通过 ref 是最普遍的。

    平时使用中主要是对一个组件进行单独设置 ref ,但是有些场景下可能是通过给定数据渲染的,这时会结合  v-for 一块使用。那么在使用的时候具体怎么写?为什么这样写?下面就来探究下。

    一、ref 和 v-for 结合

    1、ref 简单使用

    复制代码
    // html
    
    // js this.$refs.testRef.xxx
    复制代码

    2、ref 结合 v-for 使用

    for="t in classList" :key="t.code">

    在取值时怎么取?通过 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 就是数组,在取值时就要按照数组方式取值了。

  • 相关阅读:
    《算法导论》第11章-散列表 11.1-直接寻址表 11.2 散列表
    FileSaver+html2canvas js页面生成图片并下载保存
    比特币中的符文是什么?
    提高企业竞争力的秘密武器—奇高智能呼叫中心系统
    基于SSM的家庭理财系统的设计与实现
    二十三种设计模式之工厂模式(含Java工厂模式的实现)
    Vue3 企业级优雅实战 - 组件库框架 - 1 搭建 pnpm monorepo
    如何使用Python和Matplotlib创建双Y轴动态风格折线图 | 数据可视化教程
    【计算机网络微课堂】5.6 TCP超时重传时间的选择
    基于可信执行环境的机密计算框架设计及安全性分析
  • 原文地址:https://www.cnblogs.com/zhurong/p/16846672.html