Vue.js component for Apache ECharts™ providing declarative data visualization with Vue 2.7+ and Vue 3.1+ support
—
Vue injection keys for providing themes and configuration options to child components. Enables consistent theming and configuration across component hierarchies.
Provides chart theme to child components, allowing consistent theming across multiple charts.
/**
* Injection key for chart theme
* Use with Vue's provide/inject to share themes across components
*/
declare const THEME_KEY: InjectionKey<ThemeInjection>;
type ThemeInjection = Injection<Theme>;
type Theme = NonNullable<Parameters<typeof init>[1]>;
type Injection<T> = T | null | Ref<T | null> | { value: T | null };Usage Examples:
<!-- Parent component providing theme -->
<template>
<div class="dashboard">
<v-chart :option="chart1Option" />
<v-chart :option="chart2Option" />
</div>
</template>
<script setup>
import { provide } from "vue";
import { THEME_KEY } from "vue-echarts";
// Provide theme to all child charts
provide(THEME_KEY, "dark");
// Or provide reactive theme
const currentTheme = ref("light");
provide(THEME_KEY, currentTheme);
// Or provide theme object
const customTheme = {
backgroundColor: "#1e1e1e",
textStyle: { color: "#fff" }
};
provide(THEME_KEY, customTheme);
</script><!-- Child component consuming theme -->
<template>
<v-chart :option="option" />
<!-- Theme will be automatically applied -->
</template>
<script setup>
import { inject } from "vue";
import { THEME_KEY } from "vue-echarts";
// Access injected theme if needed
const theme = inject(THEME_KEY, null);
console.log("Current theme:", theme);
</script>Provides ECharts initialization options to child components.
/**
* Injection key for ECharts initialization options
* Use with Vue's provide/inject to share init options
*/
declare const INIT_OPTIONS_KEY: InjectionKey<InitOptionsInjection>;
type InitOptionsInjection = Injection<InitOptions>;
type InitOptions = NonNullable<Parameters<typeof init>[2]>;Usage Examples:
<!-- Parent providing init options -->
<script setup>
import { provide } from "vue";
import { INIT_OPTIONS_KEY } from "vue-echarts";
const initOptions = {
renderer: "canvas",
devicePixelRatio: 2,
width: "auto",
height: "auto",
locale: "EN"
};
provide(INIT_OPTIONS_KEY, initOptions);
</script>Provides chart update options to child components.
/**
* Injection key for chart update options
* Controls how charts update when options change
*/
declare const UPDATE_OPTIONS_KEY: InjectionKey<UpdateOptionsInjection>;
type UpdateOptionsInjection = Injection<UpdateOptions>;
type UpdateOptions = SetOptionOpts;Usage Examples:
<!-- Parent providing update options -->
<script setup>
import { provide } from "vue";
import { UPDATE_OPTIONS_KEY } from "vue-echarts";
const updateOptions = {
notMerge: false,
replaceMerge: undefined,
lazyUpdate: false
};
provide(UPDATE_OPTIONS_KEY, updateOptions);
</script>Provides loading animation options to child components.
/**
* Injection key for loading animation options
* Configures loading state appearance across charts
*/
declare const LOADING_OPTIONS_KEY: InjectionKey<LoadingOptionsInjection>;
type LoadingOptionsInjection = Injection<LoadingOptions>;
interface LoadingOptions {
text?: string;
textColor?: string;
fontSize?: number | string;
fontWeight?: number | string;
fontStyle?: string;
fontFamily?: string;
maskColor?: string;
showSpinner?: boolean;
color?: string;
spinnerRadius?: number;
lineWidth?: number;
zlevel?: number;
}Usage Examples:
<!-- Parent providing loading options -->
<script setup>
import { provide } from "vue";
import { LOADING_OPTIONS_KEY } from "vue-echarts";
const loadingOptions = {
text: "Loading data...",
textColor: "#ffffff",
fontSize: 14,
maskColor: "rgba(0, 0, 0, 0.7)",
showSpinner: true,
color: "#409eff",
spinnerRadius: 10,
lineWidth: 2
};
provide(LOADING_OPTIONS_KEY, loadingOptions);
</script>Setting up all injection providers in a root component:
<!-- Root dashboard component -->
<template>
<div class="dashboard">
<theme-switcher @change="handleThemeChange" />
<chart-grid>
<v-chart v-for="chart in charts" :key="chart.id" :option="chart.option" />
</chart-grid>
</div>
</template>
<script setup>
import { provide, ref } from "vue";
import {
THEME_KEY,
INIT_OPTIONS_KEY,
UPDATE_OPTIONS_KEY,
LOADING_OPTIONS_KEY
} from "vue-echarts";
// Reactive theme
const currentTheme = ref("light");
// Static configuration
const initOptions = {
renderer: "canvas",
devicePixelRatio: window.devicePixelRatio || 1
};
const updateOptions = {
notMerge: false,
lazyUpdate: true
};
const loadingOptions = {
text: "Loading...",
showSpinner: true,
color: "#409eff"
};
// Provide all options
provide(THEME_KEY, currentTheme);
provide(INIT_OPTIONS_KEY, initOptions);
provide(UPDATE_OPTIONS_KEY, updateOptions);
provide(LOADING_OPTIONS_KEY, loadingOptions);
function handleThemeChange(theme) {
currentTheme.value = theme;
// All child charts will automatically update
}
</script>Child components can override parent injections:
<!-- Parent component -->
<script setup>
import { provide } from "vue";
import { THEME_KEY } from "vue-echarts";
provide(THEME_KEY, "dark"); // Default theme
</script>
<template>
<div>
<v-chart :option="chart1" /> <!-- Uses dark theme -->
<special-chart-section />
</div>
</template><!-- Child component overriding theme -->
<script setup>
import { provide } from "vue";
import { THEME_KEY } from "vue-echarts";
provide(THEME_KEY, "light"); // Override with light theme
</script>
<template>
<div class="special-section">
<v-chart :option="chart2" /> <!-- Uses light theme -->
<v-chart :option="chart3" /> <!-- Uses light theme -->
</div>
</template>Accessing injected values in custom components:
<script setup>
import { inject, computed } from "vue";
import { THEME_KEY, INIT_OPTIONS_KEY } from "vue-echarts";
// Inject with defaults
const theme = inject(THEME_KEY, "light");
const initOptions = inject(INIT_OPTIONS_KEY, {});
// Use in computed properties
const isDarkTheme = computed(() => {
const themeValue = unref(theme);
return themeValue === "dark" ||
(typeof themeValue === "object" && themeValue?.backgroundColor === "#1e1e1e");
});
// Apply conditional styling
const containerClass = computed(() => ({
"dark-container": isDarkTheme.value,
"light-container": !isDarkTheme.value
}));
</script>For Vue 2, when providing reactive values, wrap them in objects:
<!-- Vue 2 dynamic injection -->
<script>
export default {
data() {
return {
themeWrapper: { value: "light" },
initOptionsWrapper: {
value: {
renderer: "canvas",
devicePixelRatio: 2
}
}
};
},
provide() {
return {
[THEME_KEY]: this.themeWrapper,
[INIT_OPTIONS_KEY]: this.initOptionsWrapper
};
},
methods: {
switchTheme() {
this.themeWrapper.value = this.themeWrapper.value === "light" ? "dark" : "light";
}
}
};
</script>When providing complex objects, consider memoization to avoid unnecessary re-renders:
<script setup>
import { provide, computed, ref } from "vue";
import { INIT_OPTIONS_KEY, UPDATE_OPTIONS_KEY } from "vue-echarts";
const devicePixelRatio = ref(window.devicePixelRatio || 1);
const locale = ref("EN");
// Memoized init options
const initOptions = computed(() => ({
renderer: "canvas",
devicePixelRatio: devicePixelRatio.value,
locale: locale.value
}));
// Static update options (no need to compute)
const updateOptions = {
notMerge: false,
lazyUpdate: true,
silent: false
};
provide(INIT_OPTIONS_KEY, initOptions);
provide(UPDATE_OPTIONS_KEY, updateOptions);
// Update pixel ratio on window changes
window.addEventListener("resize", () => {
devicePixelRatio.value = window.devicePixelRatio || 1;
});
</script>Install with Tessl CLI
npx tessl i tessl/npm-vue-echarts