functional.ts 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import Vue, { RenderContext, VNodeData } from 'vue';
  2. type ObjectIndex = {
  3. [key: string]: any;
  4. };
  5. type Context = RenderContext & { data: VNodeData & ObjectIndex };
  6. type InheritContext = Partial<VNodeData> & ObjectIndex;
  7. const inheritKey = [
  8. 'ref',
  9. 'style',
  10. 'class',
  11. 'attrs',
  12. 'nativeOn',
  13. 'directives',
  14. 'staticClass',
  15. 'staticStyle'
  16. ];
  17. const mapInheritKey: ObjectIndex = { nativeOn: 'on' };
  18. // inherit partial context, map nativeOn to on
  19. export function inherit(
  20. context: Context,
  21. inheritListeners?: boolean
  22. ): InheritContext {
  23. const result = inheritKey.reduce(
  24. (obj, key) => {
  25. if (context.data[key]) {
  26. obj[mapInheritKey[key] || key] = context.data[key];
  27. }
  28. return obj;
  29. },
  30. {} as InheritContext
  31. );
  32. if (inheritListeners) {
  33. result.on = result.on || {};
  34. Object.assign(result.on, context.data.on);
  35. }
  36. return result;
  37. }
  38. // emit event
  39. export function emit(context: Context, eventName: string, ...args: any[]) {
  40. const listeners = context.listeners[eventName];
  41. if (listeners) {
  42. if (Array.isArray(listeners)) {
  43. listeners.forEach(listener => {
  44. listener(...args);
  45. });
  46. } else {
  47. listeners(...args);
  48. }
  49. }
  50. }
  51. // mount functional component
  52. export function mount(Component: any, data?: VNodeData) {
  53. const instance = new Vue({
  54. el: document.createElement('div'),
  55. props: Component.props,
  56. render(h) {
  57. return h(Component, {
  58. props: this.$props,
  59. ...data
  60. });
  61. }
  62. });
  63. document.body.appendChild(instance.$el);
  64. return instance;
  65. }