mixins
混合 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。
混合对象可以包含任意组件选项。
当组件使用混合对象时,所有混合对象的选项将被混入该组件本身的选项。
mixins理解
组件在引用之后相当于在父组件内开辟了一块单独的空间,来根据父组件props过来的值进行相应的操作,单本质上两者还是泾渭分明,相对独立。
而mixins则是在引入组件之后,则是将组件内部的内容如data等方法、method等属性与父组件相应内容进行合并。相当于在引入后,父组件的各种属性方法都被扩充了。
- 单纯组件引用:
父组件 + 子组件 >>> 父组件 + 子组件 - mixins:
父组件 + 子组件 >>> new父组件
有点像注册了一个vue的公共方法,可以绑定在多个组件或者多个Vue对象实例中使用。另一点,类似于在原型对象中注册方法,实例对象即组件或者Vue实例对象中,仍然可以定义相同函数名的方法进行覆盖,有点像子类和父类的感觉
实际应用
mixins封装的自适应工具resize
import { ECharts } from 'echarts'; import { Component, Vue } from 'vue-property-decorator'; @Component({ name: 'ResizeMixin' }) export default class extends Vue { protected chart!: ECharts | null; private sidebarElm?: Element; mounted() { this.initResizeEvent(); this.initSidebarResizeEvent(); } beforeDestroy() { this.destroyResizeEvent(); this.destroySidebarResizeEvent(); } activated() { this.initResizeEvent(); this.initSidebarResizeEvent(); } deactivated() { this.destroyResizeEvent(); this.destroySidebarResizeEvent(); } private chartResizeHandler() { if (this.chart) { this.chart.resize(); } } private sidebarResizeHandler(e: TransitionEvent) { if (e.propertyName === 'width') { this.chartResizeHandler(); } } private initResizeEvent() { if (this.chartResizeHandler) { window.addEventListener('resize', this.chartResizeHandler); } } private destroyResizeEvent() { if (this.chartResizeHandler) { window.removeEventListener('resize', this.chartResizeHandler); } } private initSidebarResizeEvent() { this.sidebarElm = document.getElementsByClassName('sidebar-container')[0]; if (this.sidebarElm) { this.sidebarElm.addEventListener('transitionend', this.sidebarResizeHandler as EventListener); } } private destroySidebarResizeEvent() { if (this.sidebarElm) { this.sidebarElm.removeEventListener( 'transitionend', this.sidebarResizeHandler as EventListener ); } } }
这个封装的工具监听了resize和transitionend的改变,当这他们改变时自动调用echarts的resize(改变图表尺寸,在容器大小发生改变时需要手动调用)方法重新渲染,页面销毁时移除监听事件。
页面中调用
<template> <div :class="className" :style="{ height: height, width }" /> </template> <script lang="ts"> import { Component, Prop, Watch } from 'vue-property-decorator'; import { mixins } from 'vue-class-component'; import ResizeMixin from '@/mixins/resize'; export interface ILineChartData { // } @Component({ name: 'LineChart' }) export default class extends mixins(ResizeMixin) { @Prop({ required: true }) private chartData; @Prop({ default: 'chart' }) private className!: string; @Prop({ default: '100%' }) private width!: string; @Prop({ default: '400px' }) private height!: string; @Watch('chartData', { deep: true }) private onChartDataChange(value: ILineChartData[]) { this.setOptions(value); } mounted() { this.$nextTick(() => { this.initChart(); }); } beforeDestroy() { if (!this.chart) { return; } this.chart.dispose(); // 销毁实例,实例销毁后无法再被使用。 this.chart = null; } private initChart() { this.chart = this.$echarts.init(this.$el as HTMLDivElement, 'macarons'); } private setOptions(chartData: ILineChartData[]) { if (this.chart) { let options = { // echarts配置 }; this.chart.setOption(options, true); } } } </script>
参考链接:https://www.jianshu.com/p/a72bf060eeaa