绑定组件的事件

绑定组件的事件

先看下平时使用的事件绑定方式:

javascript
const Child = {
  setup(props, { emit }) {
    return () => {
      return h(
        'button',
        {
          onClick() {
            // 💡 触发父组件传递的事件
            emit('foo', 1, 2, 3)
          }
        },
        '我是子组件的按钮'
      )
    }
  }
}
const Comp = {
  setup() {
    return () => {
      return h('div', [
        h(Child, {
          // 💡 传递事件
          onFoo(a, b, c) {
            console.log('我是父组件传递的事件', a, b, c)
          }
        })
      ])
    }
  }
}

这种情况下,我们需要在 Child,组件中触发 Comp 组件传递的事件,此时我们应该怎么做?我们想想一下, 在 Comp 组件中,我们是通过 h(Child, { onFoo: () => {} }) 的方式传递事件的,那么在 Child 组件 中,我们应该怎么获取到这个事件呢?首先我们能确定的是,这个 onFooChild 这个组件对应的 vnode.props 中肯定是存在的,所以我们只需要通过 vnode.props.onFoo 的方式就可以获取到这个事件了:

javascript
/**
 * 处理组件传递的事件
 */
function emit(instance, event, ...args) {
  /**
   * 把这个事件名转换一下
   * foo => onFoo
   * bar => onBar
   */
  const eventName = `on${event[0].toUpperCase() + event.slice(1)}`
  // 拿到事件处理函数
  const handler = instance.vnode.props[eventName]
  // 如果是一个函数,就调用它
  if (isFunction(handler)) {
    handler(...args)
  }
}

没错,就是这么简单,我们只需要在 emit 函数中将事件名转换一下,然后通过 instance.vnode.props 获取 到事件处理函数,最后调用它就可以了。这样我们就实现了组件之间的事件传递,最后我们在 setupContext 中 设置一下 emit:

javascript
/**
 * 创建 setupContext
 */
function createSetupContext(instance) {
  return {
    // setup(props,{ attrs })
    get attrs() {
      return instance.attrs
    },
    // setup(props,{ emit })
    emit(event, ...args) {
      emit(instance, event, ...args)
    }
  }
}
组件的属性更新
组件的插槽
欢迎来到前端练习生ZM的小站