Skip to content

feat: renderWatch / renderEffect #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jan 6, 2024
Merged

feat: renderWatch / renderEffect #86

merged 11 commits into from
Jan 6, 2024

Conversation

LittleSound
Copy link
Member

@LittleSound LittleSound commented Jan 3, 2024

The origin of this API

The introduction of a specific Render Watch API is primarily due to these reasons:

  1. The Flush mode of the Watch API doesn't satisfy the requirements for rendering scenarios. Initially, in PR feat(runtime-vapor): watchEffect/watch and onEffectCleanup #69, we used a method that determined if watchEffect was within the render function and treated it uniquely. However, after discussions with Evan You, he proposed using an independent Render Watch API to accomplish this feature.

  2. Implementation of Life Cycle Hooks in Vapor mode: The BeforeUpdate and Updated hooks are intimately connected to re-runs of the render function. But in Vapor mode, the render function only runs once during a component's lifecycle. Updating content is divided among each effect; thus implementing BeforeUpdate and Updated hooks requires emitting events when an effect related to rendering is activated. Introducing a separate Render Watch API facilitates internal implementation of these hooks.

  3. The Render Watch API is exclusively used within the render function and generated by the Compiler - unlike the regular Watch API which needs consideration for Developer Experience (DX). By isolating it into its own standalone API simplifies most implementations while adding features specifically tailored for rendering scenarios.

Some envisioned use cases

// in the generated code
function render() => {
  const t0 = template('<div></div>')
  // ...
  // <button @[eventName]="handler">Button</button>
  renderEffect(() => {
    on(el1, eventName.value, handler)
  })
  // ...
  // <div v-if="expression">{{bar}}</div>
  renderWatch(() => /* vIfExpression */, (bool) => {
    // The code here should be encapsulated into a function.
    if (bool) {
      const scope = new EffectScope()
      onEffectCleanup(scope.stop.bind(scope))
      scope.run(() => {
        const t1 = template("<div></div>")
        // ...
        renderEffect(() => {
          setText(n1, undefined, bar.value)
        })
      })
    }
  })
  return t0()
}

// in runtime-vapor pkg
function on(el, event, handler) {
  el.addEventListener(event, handler)
  if (getCurrentEffect()) {
    onEffectCleanup(() => {
      el.removeEventListener(event, handler)
    })
  }
}

@LittleSound LittleSound changed the title feat: renderWatch feat: renderWatch / renderEffect Jan 3, 2024
Copy link

github-actions bot commented Jan 3, 2024

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 90.2 kB 34.3 kB 30.9 kB
runtime-vapor.global.prod.js 24.1 kB (+780 B) 9.14 kB (+273 B) 8.43 kB (+248 B)
vue-vapor.global.prod.js 59 kB (+783 B) 20.2 kB (+299 B) 18.3 kB (+218 B)
vue.global.prod.js 147 kB 53.5 kB 47.8 kB

Usages

Name Size Gzip Brotli
createApp 50.7 kB 19.8 kB 18 kB
createSSRApp 54 kB 21.1 kB 19.2 kB
defineCustomElement 52.9 kB 20.5 kB 18.7 kB
vapor 24 kB (+806 B) 9.17 kB (+290 B) 8.44 kB (+257 B)
overall 64.1 kB 24.7 kB 22.5 kB

@LittleSound LittleSound marked this pull request as ready for review January 4, 2024 15:42
@sxzz sxzz merged commit fb4d9a1 into main Jan 6, 2024
@sxzz sxzz deleted the feat/vapor-renderWatch branch January 6, 2024 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants