前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >petite-vue源码剖析-ref的工作原理

petite-vue源码剖析-ref的工作原理

作者头像
^_^肥仔John
发布2022-05-09 16:08:44
3430
发布2022-05-09 16:08:44
举报

ref内部的工作原理十分简单,其实就是将指令ref、:ref或v-bind:ref标识的元素实例存储到当前作用域的refs对象中,那么我们就可以通过this. refs获取对应的元素实例。但由于作用域继承上有点小窍门,所以我们能从this.

深入ref工作原理

代码语言:javascript
复制
//文件 ./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)的构建吧

代码语言:javascript
复制
//文件 ./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对象的原型链,那么我们就可以这样引用元素实例

代码语言:javascript
复制
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://cloud.tencent.com/developer/article/1997346 肥仔John

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-03-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 深入ref工作原理
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档