How to Build a Mini TinyVue Component Library for Vue 2 & 3

Learn how to create a mini version of the TinyVue component library that works across Vue 2.6, Vue 2.7, and Vue 3 by using a single source code strategy, adaptive layers, renderless logic, and unified APIs, with practical code examples and migration solutions.

Huawei Cloud Developer Alliance
Huawei Cloud Developer Alliance
Huawei Cloud Developer Alliance
How to Build a Mini TinyVue Component Library for Vue 2 & 3

Why implement a component library across frameworks?

Vue has two major branches, Vue 2 and Vue 3, which are not compatible. Vue 2.7 serves as a bridge between 2.6 and Vue 3. Migrating projects incurs cost and risk, and existing component libraries provide separate versions for each framework.

TinyVue aims to support Vue 2.6, Vue 2.7, and Vue 3 with a single‑source‑code strategy and intelligent compilation, reducing maintenance cost and migration risk.

Key Technical Analysis

Using a button component as an example, the template integrates an adapter layer, renderless logic, and theme styles. All logic is extracted to a renderless function.

Flow: the Vue file imports the setup function and the renderless function from the adapter layer; the setup function constructs an object that smooths framework differences and passes it to renderless; renderless creates state and API, returns them to the adapter, which binds state to template data and API to events.

How to Resolve Framework Differences

1. Differences between frameworks

Template syntax differences

Lifecycle name changes

Removal of event modifiers, filters, message subscriptions

v-model syntax sugar differences

Directive and animation component differences

2. Internal runtime differences

Component instance differences

VNode structure differences

Removal of $children, $scopedSlots, etc.

Solution for reactive function imports

Expose a hooks variable in the adapter layer to unify reactive function access.

import { reactive, ref, watch, ... } from '@vue/composition-api' // Vue 2.6
import { reactive, ref, watch, ... } from 'vue' // Vue 3
// adapter/index.js
export { hooks }

Solution for VNode and h function differences

Provide a unified h function in the adapter layer.

// adapter/vue2/index.js
import * as hooks from '@vue/composition-api'
const h = hooks.h

// adapter/vue3/index.js
const h = (component, propsData, childData) => {
  // omitted code
  let props = {}
  let children = childData
  if (propsData && typeof propsData === 'object' && !Array.isArray(propsData)) {
    props = parseProps(propsData)
    propsData.scopedSlots && (children = propsData.scopedSlots)
  } else if (typeof propsData === 'string' || Array.isArray(propsData)) {
    childData = propsData
  }
  return hooks.h(component, props, children)
}

// adapter/index.js
export { h }

Solution for v-model differences

Define a model option in Vue 2 to customize the bound prop and event.

defineComponent({
  model: {
    prop: 'modelValue',
    event: 'update:modelValue'
  },
  props: {
    modelValue: String
  }
})

Solution for slots differences

Unify slot access by exposing $slots that works for both frameworks.

// adapter/vue2/index.js
Object.defineProperties(vm, {
  $slots: { get: () => instance.proxy.$scopedSlots },
  $scopedSlots: { get: () => instance.proxy.$scopedSlots }
})

// adapter/vue3/index.js
Object.defineProperties(vm, {
  $slots: { get: () => instance.slots },
  $scopedSlots: { get: () => instance.slots }
})

Solution for directive lifecycle differences

Implement directive objects that support both Vue 2 and Vue 3 lifecycle names, keeping the parameters unchanged.

Solution for animation class differences

Define animation class names that work for both Vue 2 and Vue 3 transition components.

.fade-in-linear-enter,
.fade-in-linear-enter-from,
.fade-in-linear-leave-to {
  opacity: 0;
}

Overall, the team adopted two core principles: “seek commonality, eliminate differences” by using syntax supported by both frameworks, and “compatibility and inclusion” by building an adapter layer that hides framework differences, allowing developers to focus on business logic.

VueComponent LibraryAdapter Patterncross‑frameworkRenderless
Huawei Cloud Developer Alliance
Written by

Huawei Cloud Developer Alliance

The Huawei Cloud Developer Alliance creates a tech sharing platform for developers and partners, gathering Huawei Cloud product knowledge, event updates, expert talks, and more. Together we continuously innovate to build the cloud foundation of an intelligent world.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.