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

深刻ref工作原理

//文件 ./src/directives/ref.tsexport 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.tsexport 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