乐趣区

关于javascript:petitevue源码剖析ref的工作原理

ref外部的工作原理非常简略,其实就是将指令 ref:refv-bind:ref标识的元素实例存储到以后作用域的 $refs 对象中,那么咱们就能够通过 this.$refs 获取对应的元素实例。但因为作用域继承上有点小窍门,所以咱们能从 this.$refs 获取的元素实例还是须要留神一下。上面让我为你一一道来吧!

深刻 ref 工作原理

// 文件 ./src/directives/ref.ts

export const ref: Directive = ({
  el,
  ctx: {scope: { $refs}
  },
  get,
  effect
}) => {
  let prevRef: any
  effect(() => {
    // 获取指向元素的属性名称
    const ref = get()
    $refs[ref] = el
    // 因为属性名称是能够动静生成的(:ref="name"),若新旧对应的属性名称不同,则清理旧属性
    if (prevRef && ref != prevRef) {delete $refs[prevRef]
    }
    prevRef = ref
  })

  return () => {prevRef && delete $refs[prevRef]
  }
}

这段实现是不是长篇累牍呢?当初让咱们把眼光转向上下文对象 (Context) 的构建吧

// 文件 ./src/context.ts

export const createScopedContext = (ctx: Context, data = {}) => {
  onst parentScope = ctx.scope
  const mergedScope = Object.create(parentScope)
  Object.defineProperties(mergedScope, Object.getOwnPropertyDescriptors(data))
  // $refs 形成 $refs 对象的原型链
  mergedScope.$refs = Object.create(parentScope.$refs)
  // ......
}

$refs 形成 $refs 对象的原型链,那么咱们就能够这样援用元素实例

createApp({
  App: {
    $template: `
    <div ref="container">
      <div v-scope="Modal"></div>
    </div>
    `,
    Modal: {
      $template: `
      <button @click="handleHide">Hide</button>
      `,
      handleHide() {this.$refs.container.style.display = 'none'}
    }
  }
}).mount('[v-scope]')

总结

下一篇《petite-vue 源码分析 - 优化伎俩 template 详解》咱们将着手解决 petite-vue 在线模板和在线渲染造成用户体验待优化的问题,敬请期待。
尊重原创,转载请注明来自:https://www.cnblogs.com/fsjoh… 肥仔 John

退出移动版