Compare commits

...

6 Commits

7 changed files with 6245 additions and 5120 deletions

View File

@ -1,3 +1,7 @@
## 6.7.0
* Added supports for native DOM events binding with the `native:` prefix.
## 6.6.10
* Fixed that `autoresize` doesn't work when reducing the height or the root element.

138
README.md
View File

@ -238,7 +238,7 @@ Drop `<script>` inside your HTML file and access the component via `window.VueEC
```html
<script src="https://cdn.jsdelivr.net/npm/vue@3.4.23"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.6.10"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.7.0"></script>
```
<!-- vue3Scripts:end -->
@ -258,7 +258,7 @@ app.component('v-chart', VueECharts)
```html
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.6.10"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.7.0"></script>
```
<!-- vue2Scripts:end -->
@ -319,6 +319,78 @@ See more examples [here](https://github.com/ecomfe/vue-echarts/tree/main/src/dem
For performance critical scenarios (having a large dataset) we'd better bypass Vue's reactivity system for `option` prop. By specifying `manual-update` prop with `true` and not providing `option` prop, the dataset won't be watched any more. After doing so, you need to retrieve the component instance with `ref` and manually call `setOption` method to update the chart.
### Events
You can bind events with Vue's `v-on` directive.
```vue
<template>
<v-chart :option="option" @highlight="handleHighlight" />
</template>
```
> **Note**
>
> Only the `.once` event modifier is supported as other modifiers are tightly coupled with the DOM event system.
Vue-ECharts support the following events:
- `highlight` [](https://echarts.apache.org/en/api.html#events.highlight)
- `downplay` [](https://echarts.apache.org/en/api.html#events.downplay)
- `selectchanged` [](https://echarts.apache.org/en/api.html#events.selectchanged)
- `legendselectchanged` [](https://echarts.apache.org/en/api.html#events.legendselectchanged)
- `legendselected` [](https://echarts.apache.org/en/api.html#events.legendselected)
- `legendunselected` [](https://echarts.apache.org/en/api.html#events.legendunselected)
- `legendselectall` [](https://echarts.apache.org/en/api.html#events.legendselectall)
- `legendinverseselect` [](https://echarts.apache.org/en/api.html#events.legendinverseselect)
- `legendscroll` [](https://echarts.apache.org/en/api.html#events.legendscroll)
- `datazoom` [](https://echarts.apache.org/en/api.html#events.datazoom)
- `datarangeselected` [](https://echarts.apache.org/en/api.html#events.datarangeselected)
- `timelinechanged` [](https://echarts.apache.org/en/api.html#events.timelinechanged)
- `timelineplaychanged` [](https://echarts.apache.org/en/api.html#events.timelineplaychanged)
- `restore` [](https://echarts.apache.org/en/api.html#events.restore)
- `dataviewchanged` [](https://echarts.apache.org/en/api.html#events.dataviewchanged)
- `magictypechanged` [](https://echarts.apache.org/en/api.html#events.magictypechanged)
- `geoselectchanged` [](https://echarts.apache.org/en/api.html#events.geoselectchanged)
- `geoselected` [](https://echarts.apache.org/en/api.html#events.geoselected)
- `geounselected` [](https://echarts.apache.org/en/api.html#events.geounselected)
- `axisareaselected` [](https://echarts.apache.org/en/api.html#events.axisareaselected)
- `brush` [](https://echarts.apache.org/en/api.html#events.brush)
- `brushEnd` [](https://echarts.apache.org/en/api.html#events.brushEnd)
- `brushselected` [](https://echarts.apache.org/en/api.html#events.brushselected)
- `globalcursortaken` [](https://echarts.apache.org/en/api.html#events.globalcursortaken)
- `rendered` [](https://echarts.apache.org/en/api.html#events.rendered)
- `finished` [](https://echarts.apache.org/en/api.html#events.finished)
- Mouse events
- `click` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.click)
- `dblclick` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.dblclick)
- `mouseover` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.mouseover)
- `mouseout` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.mouseout)
- `mousemove` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.mousemove)
- `mousedown` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.mousedown)
- `mouseup` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.mouseup)
- `globalout` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.globalout)
- `contextmenu` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.contextmenu)
- ZRender events
- `zr:click`
- `zr:mousedown`
- `zr:mouseup`
- `zr:mousewheel`
- `zr:dblclick`
- `zr:contextmenu`
See supported events [here →](https://echarts.apache.org/en/api.html#events)
#### Native DOM Events
As Vue-ECharts binds events to the ECharts instance by default, there is some caveat when using native DOM events. You need to prefix the event name with `native:` to bind native DOM events (or you can use the `.native` modifier in Vue 2, which is dropped in Vue 3).
```vue
<template>
<v-chart @native:click="handleClick" />
</template>
```
### Provide / Inject
Vue-ECharts provides provide/inject API for `theme`, `init-options`, `update-options` and `loading-options` to help configuring contextual options. eg. for `init-options` you can use the provide API like this:
@ -402,68 +474,6 @@ import { THEME_KEY } from 'vue-echarts'
Static methods can be accessed from [`echarts` itself](https://echarts.apache.org/en/api.html#echarts).
### Events
You can bind events with Vue's `v-on` directive.
```vue
<template>
<v-chart :option="option" @highlight="handleHighlight" />
</template>
```
> **Note**
>
> Only the `.once` event modifier is supported as other modifiers are tightly coupled with the DOM event system.
Vue-ECharts support the following events:
- `highlight` [](https://echarts.apache.org/en/api.html#events.highlight)
- `downplay` [](https://echarts.apache.org/en/api.html#events.downplay)
- `selectchanged` [](https://echarts.apache.org/en/api.html#events.selectchanged)
- `legendselectchanged` [](https://echarts.apache.org/en/api.html#events.legendselectchanged)
- `legendselected` [](https://echarts.apache.org/en/api.html#events.legendselected)
- `legendunselected` [](https://echarts.apache.org/en/api.html#events.legendunselected)
- `legendselectall` [](https://echarts.apache.org/en/api.html#events.legendselectall)
- `legendinverseselect` [](https://echarts.apache.org/en/api.html#events.legendinverseselect)
- `legendscroll` [](https://echarts.apache.org/en/api.html#events.legendscroll)
- `datazoom` [](https://echarts.apache.org/en/api.html#events.datazoom)
- `datarangeselected` [](https://echarts.apache.org/en/api.html#events.datarangeselected)
- `timelinechanged` [](https://echarts.apache.org/en/api.html#events.timelinechanged)
- `timelineplaychanged` [](https://echarts.apache.org/en/api.html#events.timelineplaychanged)
- `restore` [](https://echarts.apache.org/en/api.html#events.restore)
- `dataviewchanged` [](https://echarts.apache.org/en/api.html#events.dataviewchanged)
- `magictypechanged` [](https://echarts.apache.org/en/api.html#events.magictypechanged)
- `geoselectchanged` [](https://echarts.apache.org/en/api.html#events.geoselectchanged)
- `geoselected` [](https://echarts.apache.org/en/api.html#events.geoselected)
- `geounselected` [](https://echarts.apache.org/en/api.html#events.geounselected)
- `axisareaselected` [](https://echarts.apache.org/en/api.html#events.axisareaselected)
- `brush` [](https://echarts.apache.org/en/api.html#events.brush)
- `brushEnd` [](https://echarts.apache.org/en/api.html#events.brushEnd)
- `brushselected` [](https://echarts.apache.org/en/api.html#events.brushselected)
- `globalcursortaken` [](https://echarts.apache.org/en/api.html#events.globalcursortaken)
- `rendered` [](https://echarts.apache.org/en/api.html#events.rendered)
- `finished` [](https://echarts.apache.org/en/api.html#events.finished)
- Mouse events
- `click` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.click)
- `dblclick` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.dblclick)
- `mouseover` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.mouseover)
- `mouseout` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.mouseout)
- `mousemove` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.mousemove)
- `mousedown` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.mousedown)
- `mouseup` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.mouseup)
- `globalout` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.globalout)
- `contextmenu` [](https://echarts.apache.org/en/api.html#events.Mouse%20events.contextmenu)
- ZRender events
- `zr:click`
- `zr:mousedown`
- `zr:mouseup`
- `zr:mousewheel`
- `zr:dblclick`
- `zr:contextmenu`
See supported events [here →](https://echarts.apache.org/en/api.html#events)
## CSP: `style-src` or `style-src-elem`
If you are applying a CSP to prevent inline `<style>` injection, you need to use files from `dist/csp` directory and include `dist/csp/style.css` into your app manually.

View File

@ -238,7 +238,7 @@ import "echarts";
```html
<script src="https://cdn.jsdelivr.net/npm/vue@3.4.23"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.6.10"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.7.0"></script>
```
<!-- vue3Scripts:end -->
@ -258,7 +258,7 @@ app.component('v-chart', VueECharts)
```html
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.6.10"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.7.0"></script>
```
<!-- vue2Scripts:end -->
@ -381,6 +381,16 @@ Vue-ECharts 支持如下事件:
请参考支持的事件列表。[前往 →](https://echarts.apache.org/zh/api.html#events)
#### 原生 DOM 事件
由于 Vue-ECharts 默认将事件绑定到 ECharts 实例,因此在使用原生 DOM 事件时需要做一些特殊处理。你需要在事件名称前加上 `native:` 前缀来绑定原生 DOM 事件(可以在 Vue 2 中也可以使用 `.native` 修饰符,但这在 Vue 3 中已被废弃)。
```vue
<template>
<v-chart @native:click="handleClick" />
</template>
```
### Provide / Inject
Vue-ECharts 为 `theme``init-options``update-options``loading-options` 提供了 provide/inject API以通过上下文配置选项。例如可以通过如下方式来使用 provide API 为 `init-options` 提供上下文配置:
@ -464,6 +474,8 @@ import { THEME_KEY } from 'vue-echarts'
静态方法请直接通过 [`echarts` 本身](https://echarts.apache.org/zh/api.html#echarts)进行调用。
## CSP: `style-src` 或 `style-src-elem`
如果你正在应用 CSP 来防止内联 `<style>` 注入,则需要使用 `dist/csp` 目录中的文件,并手动引入 `dist/csp/style.css`

View File

@ -1,6 +1,6 @@
{
"name": "vue-echarts",
"version": "6.6.10",
"version": "6.7.0",
"description": "Vue.js component for Apache ECharts™.",
"author": "GU Yiling <justice360@gmail.com>",
"scripts": {
@ -26,35 +26,35 @@
"vue-demi": "^0.13.11"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/core": "^7.24.4",
"@highlightjs/vue-plugin": "^2.1.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-replace": "^5.0.5",
"@rollup/plugin-terser": "^0.4.4",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0",
"@vercel/analytics": "^1.1.1",
"@vercel/analytics": "^1.2.2",
"@vue/cli-plugin-babel": "^5.0.8",
"@vue/cli-plugin-eslint": "^5.0.8",
"@vue/cli-plugin-typescript": "^5.0.8",
"@vue/cli-service": "^5.0.8",
"@vue/compiler-sfc": "^3.3.7",
"@vue/compiler-sfc": "^3.4.23",
"@vue/composition-api": "^1.7.2",
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/eslint-config-typescript": "^10.0.0",
"@vueuse/core": "^10.5.0",
"@vueuse/core": "^10.9.0",
"comment-mark": "^1.1.1",
"core-js": "^3.33.2",
"echarts": "^5.4.3",
"core-js": "^3.37.0",
"echarts": "^5.5.0",
"echarts-gl": "^2.0.9",
"echarts-liquidfill": "^3.1.0",
"esbuild-wasm": "^0.19.2",
"esbuild-wasm": "^0.19.12",
"eslint": "^7.32.0",
"eslint-plugin-prettier": "^3.4.1",
"eslint-plugin-vue": "^8.7.1",
"highlight.js": "^11.9.0",
"pinia": "^2.1.7",
"postcss": "^8.4.31",
"postcss": "^8.4.38",
"postcss-loader": "^5.3.0",
"postcss-nested": "^5.0.6",
"prettier": "^2.8.8",
@ -67,9 +67,9 @@
"rollup-plugin-ts": "^2.0.7",
"tslib": "^2.6.2",
"typescript": "4.6.4",
"vue": "^3.3.7",
"vue2": "npm:vue@^2.7.15",
"webpack": "^5.89.0"
"vue": "^3.4.23",
"vue2": "npm:vue@^2.7.16",
"webpack": "^5.91.0"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.5",

10930
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@ import {
useLoading,
loadingProps
} from "./composables";
import { omitOn, unwrapInjected } from "./utils";
import { isOn, omitOn, unwrapInjected } from "./utils";
import { register, TAG_NAME, type EChartsElement } from "./wc";
import "./style.css";
@ -55,6 +55,8 @@ export const UPDATE_OPTIONS_KEY =
"ecUpdateOptions" as unknown as InjectionKey<UpdateOptionsInjection>;
export { LOADING_OPTIONS_KEY } from "./composables";
const NATIVE_EVENT_RE = /(^&?~?!?)native:/;
export default defineComponent({
name: "echarts",
props: {
@ -95,6 +97,7 @@ export default defineComponent({
() => props.updateOptions || unwrapInjected(defaultUpdateOptions, {})
);
const nonEventAttrs = computed(() => omitOn(attrs));
const nativeListeners: Record<string, unknown> = {};
// @ts-expect-error listeners for Vue 2 compatibility
const listeners = getCurrentInstance().proxy.$listeners;
@ -114,17 +117,33 @@ export default defineComponent({
instance.group = props.group;
}
let realListeners = listeners;
if (!realListeners) {
realListeners = {};
const realListeners: Record<string, any> = {};
if (!listeners) {
// This is for Vue 3.
// We are converting all `on<Event>` props to event listeners compatible with Vue 2
// and collect them into `realListeners` so that we can bind them to the chart instance
// later in the same way.
// For `onNative:<event>` props, we just strip the `Native:` part and collect them into
// `nativeListeners` so that we can bind them to the root element directly.
Object.keys(attrs)
.filter(key => key.indexOf("on") === 0 && key.length > 2)
.filter(key => isOn(key))
.forEach(key => {
// onClick -> c + lick
// onZr:click -> z + r:click
let event = key.charAt(2).toLowerCase() + key.slice(3);
// Collect native DOM events
if (event.indexOf("native:") === 0) {
// native:click -> onClick
const nativeKey = `on${event
.charAt(7)
.toUpperCase()}${event.slice(8)}`;
nativeListeners[nativeKey] = attrs[key];
return;
}
// clickOnce -> ~click
// zr:clickOnce -> ~zr:click
if (event.substring(event.length - 4) === "Once") {
@ -133,6 +152,23 @@ export default defineComponent({
realListeners[event] = attrs[key];
});
} else {
// This is for Vue 2.
// We just need to distinguish normal events and `native:<event>` events and
// collect them into `realListeners` and `nativeListeners` respectively.
// For `native:<event>` events, we just strip the `native:` part and collect them
// into `nativeListeners` so that we can bind them to the root element directly.
// native:click -> click
// ~native:click -> ~click
// &~!native:click -> &~!click
Object.keys(listeners).forEach(key => {
if (NATIVE_EVENT_RE.test(key)) {
nativeListeners[key.replace(NATIVE_EVENT_RE, "$1")] =
listeners[key];
} else {
realListeners[key] = listeners[key];
}
});
}
Object.keys(realListeners).forEach(key => {
@ -296,6 +332,7 @@ export default defineComponent({
inner,
setOption,
nonEventAttrs,
nativeListeners,
...publicApi
};
},
@ -303,7 +340,9 @@ export default defineComponent({
// Vue 3 and Vue 2 have different vnode props format:
// See https://v3-migration.vuejs.org/breaking-changes/render-function-api.html#vnode-props-format
const attrs = (
Vue2 ? { attrs: this.nonEventAttrs } : { ...this.nonEventAttrs }
Vue2
? { attrs: this.nonEventAttrs, on: this.nativeListeners }
: { ...this.nonEventAttrs, ...this.nativeListeners }
) as any;
attrs.ref = "root";
attrs.class = attrs.class ? ["echarts"].concat(attrs.class) : "echarts";

View File

@ -1,4 +1,4 @@
import { unref } from "vue-demi";
import { unref, isRef } from "vue-demi";
import type { Injection } from "./types";
type Attrs = {
@ -26,7 +26,7 @@ export function unwrapInjected<T, V>(
injection: Injection<T>,
defaultValue: V
): T | V {
const value = unref(injection);
const value = isRef(injection) ? unref(injection) : injection;
if (value && typeof value === "object" && "value" in value) {
return value.value || defaultValue;