Skip to content

Commit

Permalink
feat: added run-time vue resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
privatenumber committed Nov 28, 2020
1 parent b62ce67 commit 9fe263d
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 14 deletions.
45 changes: 38 additions & 7 deletions src/to-vue-2.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import Vue from 'vue';
import frag from 'vue-frag';
import {createApp, h} from 'vue3';
import {vue3ProxyNode} from './utils';

let Vue2;
try {
Vue2 = require('vue');
} catch {}

let Vue3;
try {
Vue3 = require('vue3');
} catch {}

const camelizeRE = /-(\w)/g;

function normalizeEventName(eventName) {
Expand Down Expand Up @@ -53,7 +61,7 @@ const renderVue2Vnode = /* Vue 3 component */ {

mounted() {
const vm = this;
this.vue2App = (new Vue({
this.vue2App = (new Vue2({
beforeCreate() {
this.$parent = vm.parent;
},
Expand Down Expand Up @@ -82,14 +90,14 @@ const renderVue2Vnode = /* Vue 3 component */ {
this.vue2App.$forceUpdate();
}

return h('div');
return Vue3.h('div');
},
};

function interopSlots(ctx) {
const scopedSlots = {};
for (const slotName in ctx.$scopedSlots) {
scopedSlots[slotName] = () => h(renderVue2Vnode, {
scopedSlots[slotName] = () => Vue3.h(renderVue2Vnode, {
parent: ctx,
vnode: ctx.$scopedSlots[slotName],
});
Expand Down Expand Up @@ -127,8 +135,8 @@ const vue2WrapperBase = {
// Delay until mounted for SSR
mounted() {
const vm = this;
this.v3app = createApp({
render: () => h(
this.v3app = Vue3.createApp({
render: () => Vue3.h(
this.$options.component,
mergeAttrsListeners(this),
interopSlots(this),
Expand Down Expand Up @@ -171,9 +179,32 @@ const vue2WrapperBase = {
};

const toVue2 = vue3Component => {
if (!Vue2 && !Vue3) {
throw new Error('Vue 2 & 3 were not resolved with bare specifiers "vue" & "vue3". Register them with toVue3.register(Vue2, Vue3)');
}

if (!Vue2) {
throw new Error('Vue 2 was not resolved with bare specifier "vue". Register it with toVue3.register(Vue)');
}

if (!Vue3) {
throw new Error('Vue 3 was not resolved with bare specifier "vue3". Register it with toVue3.register(Vue3) or toVue3.register({ createApp, h })');
}

const vue2Wrapper = Object.create(vue2WrapperBase);
vue2Wrapper.component = vue3Component;
return vue2Wrapper;
};

toVue2.register = function () {
for (let i = 0; i < arguments.length; i += 1) { // eslint-disable-line unicorn/no-for-loop
const Vue = arguments[i];
if (typeof Vue === 'function' && Vue.version && Vue.version.startsWith('2')) {
Vue2 = Vue;
} else if (Vue.createApp && Vue.h) {
Vue3 = Vue;
}
}
};

export default toVue2;
41 changes: 36 additions & 5 deletions src/to-vue-3.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import Vue from 'vue';
import {createApp, h} from 'vue3';
import {vue3ProxyNode} from './utils';

let Vue2;
try {
// Vue2 = require('vue');
} catch {}

let Vue3;
try {
// Vue3 = require('vue3');
} catch {}

const hyphenateRE = /\B([A-Z])/g;
const hyphenate = string => string.replace(hyphenateRE, '-$1').toLowerCase();

Expand Down Expand Up @@ -54,7 +62,7 @@ const renderVue3Vnode = {
props: ['parent', 'vnode'],

mounted() {
this.vue3App = createApp({
this.vue3App = Vue3.createApp({
render: () => this.vnode(),
});

Expand Down Expand Up @@ -112,7 +120,7 @@ const vue3WrapperBase = {
const vm = this;
const mountElement = this.$el;

this.v2 = new Vue({
this.v2 = new Vue2({
provide() {
return new Proxy(vm._.provides, {
getOwnPropertyDescriptor(target, key) {
Expand Down Expand Up @@ -170,7 +178,7 @@ const vue3WrapperBase = {
this.v2.$forceUpdate();
}

return h('div');
return Vue3.h('div');
},
};

Expand All @@ -181,6 +189,18 @@ const getProvidedMixin = {
};

const toVue3 = vue2Component => {
if (!Vue2 && !Vue3) {
throw new Error('Vue 2 & 3 were not resolved with bare specifiers "vue" & "vue3". Register them with toVue3.register(Vue2, Vue3)');
}

if (!Vue2) {
throw new Error('Vue 2 was not resolved with bare specifier "vue". Register it with toVue3.register(Vue)');
}

if (!Vue3) {
throw new Error('Vue 3 was not resolved with bare specifier "vue3". Register it with toVue3.register(Vue3) or toVue3.register({ createApp, h })');
}

const component = Object.create(vue2Component);
component.mixins = [getProvidedMixin].concat(vue2Component.mixins || []);

Expand All @@ -190,4 +210,15 @@ const toVue3 = vue2Component => {
return vue3Wrapper;
};

toVue3.register = function () {
for (let i = 0; i < arguments.length; i += 1) { // eslint-disable-line unicorn/no-for-loop
const Vue = arguments[i];
if (typeof Vue === 'function' && Vue.version && Vue.version.startsWith('2')) {
Vue2 = Vue;
} else if (Vue.createApp && Vue.h) {
Vue3 = Vue;
}
}
};

export default toVue3;
6 changes: 5 additions & 1 deletion test/to-vue-2.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const {default: toVue2} = require('vue-2-3/to-vue-2');
const {createApp, provide, inject, nextTick} = require('vue3');
const Vue = require('vue');
const Vue3 = require('vue3');
const {mount} = require('@vue/test-utils');
const {createApp, provide, inject, nextTick} = Vue3;

toVue2.register(Vue, Vue3);

describe('Error handling', () => {
test('throw error when used in vue 3 app', () => {
Expand Down
6 changes: 5 additions & 1 deletion test/to-vue-3.spec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
const {default: toVue3} = require('vue-2-3/to-vue-3');
const {createApp, nextTick} = require('vue3');
const Vue3 = require('vue3');
const outdent = require('outdent');
const Vue = require('vue');

const {createApp, nextTick} = Vue3;

toVue3.register(Vue, Vue3);

let mountTarget;
let app;
beforeEach(() => {
Expand Down

0 comments on commit 9fe263d

Please sign in to comment.