Published on

基础图形

Authors
  • avatar
    Name
    李丹秋
    Twitter

demo code

<script lang="ts">
  import Counter from './Counter.svelte'
  let count = $state(0)
  function addCount() {
    count += 1;
  }
</script>

<main>
  <h1>Vite + Svelte</h1>
  <button onclick={addCount}>add</button>
  <div class="card">
    <Counter />
  </div>
  <p>parent count:{count}</p>
</main>

<style>
  p{
    color:red;
  }
</style>

<script lang="ts">
  let count: number = $state(0)
  const increment = () => {
    count += 1
  }
</script>

<button onclick={increment}>
  count is {count}
</button>

编译后代码

import 'svelte/internal/disclose-version'
import * as $ from 'svelte/internal/client'
import Counter from './Counter.svelte'

function addCount(_, count) {
  $.set(count, $.get(count) + 1)
}

var root = $.from_html(
  `<main><h1>Vite + Svelte</h1> <button>add</button> <div class="card"><!></div> <p class="svelte-b8fwxh"> </p></main>`
)

export default function App($$anchor) {
  let count = $.state(0)
  var main = root()
  var button = $.sibling($.child(main), 2)

  button.__click = [addCount, count]

  var div = $.sibling(button, 2)
  var node = $.child(div)

  Counter(node, {})
  $.reset(div)

  var p = $.sibling(div, 2)
  var text = $.child(p)

  $.reset(p)
  $.reset(main)
  $.template_effect(() => $.set_text(text, `parent count:${$.get(count) ?? ''}`))
  $.append($$anchor, main)
}

$.delegate(['click'])

parse后变化

svelte的自定义组件,编译后,会变成< ! >这样的标识符。

import 'svelte/internal/disclose-version'
import * as $ from 'svelte/internal/client'

const increment = (_, count) => {
  $.set(count, $.get(count) + 1)
}

var root = $.from_html(`<button> </button>`)

export default function Counter($$anchor) {
  let count = $.state(0)
  var button = root()

  button.__click = [increment, count]

  var text = $.child(button)

  $.reset(button)
  $.template_effect(() => $.set_text(text, `count is ${$.get(count) ?? ''}`))
  $.append($$anchor, button)
}

$.delegate(['click'])

delegate

export function delegate(events) {
  for (var i = 0; i < events.length; i++) {
    all_registered_events.add(events[i])
  }

  for (var fn of root_event_handles) {
    fn(events)
  }
}

svelte编译完成后,在运行阶段,首先需要将事件注册到全局变量中。

event_handle(array_from(all_registered_events))
root_event_handles.add(event_handle)

var event_handle = (events) => {
  for (var i = 0; i < events.length; i++) {
    var event_name = events[i]

    if (registered_events.has(event_name)) continue
    registered_events.add(event_name)

    var passive = is_passive_event(event_name)

    target.addEventListener(event_name, handle_event_propagation, { passive })

    var n = document_listeners.get(event_name)

    if (n === undefined) {
      document.addEventListener(event_name, handle_event_propagation, { passive })
      document_listeners.set(event_name, 1)
    } else {
      document_listeners.set(event_name, n + 1)
    }
  }
}

然后后续执行mount的时候,使用event_handle函数,将所有的事件挂载到document和target上。 这种双重监听策略是 Svelte 事件委托系统的核心设计,确保了无论 DOM 结构如何变化,事件都能被可靠地捕获和处理。这对于支持复杂的 UI 模式(如门户、动态组件等)至关重要。