美文网首页
vue2升级vue3: TSX Vue 3 Compositio

vue2升级vue3: TSX Vue 3 Compositio

作者: zhoulujun | 来源:发表于2022-07-30 23:15 被阅读0次

在vue2时代,$refs 直接操作子组件

this.$refs.gridlayout.$children[index];

虽然不推荐这么做,但是确实非常好用。但是vue2快速迁移到vue3,之前的这个写法因为干进度,不想重构,直接搬迁,发现不行?

看了下官方的文档:https://v3.cn.vuejs.org/guide/migration/array-refs.html#%E8%BF%81%E7%A7%BB%E7%AD%96%E7%95%A5

<template>

    <div v-for="item in list" :ref="setItemRef"></div>

</template>

<script setup>

    let itemRefs = ref()

    const setItemRef = el => {

      if (el) {

        itemRefs.push(el)

      }

    }

    onBeforeUpdate(() => {

      itemRefs = []

    })

    onUpdated(() => {

      console.log(itemRefs)

    })

</script>

注意:

itemRefs 不必是数组:它也可以是一个对象,其 ref 可以通过迭代的 key 被设置

如有需要,itemRefs 也可以是响应式的,且可以被侦听。

在tsx 这个怎么弄呢?

TSX refs

网上的大部分教程都是 template 的

Typing Template Refs

const el = ref<HTMLInputElement | null>(null)

普通元素

Typing Component Template Refs

import MyModal from './MyModal.vue'

const modal = ref<InstanceType<typeof MyModal> | null>(null)

const openModal = () => {

  modal.value?.open()

}

对于子组件,其实和 let timer: ReturnType<typeof setTimeout> = null; 类似。

如果不进行类型声明,modal 方法无法调用。 需要是as  魔法了

还有一个需要特别注意,就是子组件内容是暴露出来的,如果是 <script setup> 组件,是无法获取内容的,具体参看:

vue2升级vue3:单文件组件概述 及 defineExpos/expose https://www.zhoulujun.cn/html/webfront/ECMAScript/vue3/8872.html

Refs 获取子元素,并操作子元素

import { defineComponent, nextTick, onBeforeUpdate, onMounted, onUnmounted, ref } from 'vue';

import ChartWrapper from '@/components/chart-wrapper';

import props from './props';

import { AddChartType, PanelModel, IGridPos } from '@/typings';

import { DashboardModule, sortGridPanels } from '@modules/dashboard';

import { getPluginTypes, handleInitChartPlugin, handleInitDataSource } from '@/utils/dashboard';

import Loading from '@/components/loading';

import { GRID_COL_NUM, GRID_ROW_HEIGHT, GRID_ROW_MARGIN, initPanel } from '@/constants';

import { debounce } from 'lodash';

import { deepClone } from '@/utils';

import AddPanel from '@dashboard/grid-panel/add-panel';

import TabPanel from '@dashboard/tab-panel/index';

import { GridItem, GridLayout } from 'v3-grid-layout';

import 'v3-grid-layout/dist/style.css';

import './index.scss';

import Row from './Row';

import EventBus from '@/utils/eventBus';

export default defineComponent({

  name: 'GridPanelPlugin',

  props,

  emits: ['ready', 'delete', 'mounted'],

  setup(props, { emit }) {

    const layout = ref<IGridPos[]>([]);

    const gridLayout = ref<InstanceType<typeof GridLayout>>(null);

    const gridItem = ref<InstanceType<typeof GridItem>[]>([]);

    const dashboardPanel = ref<Element>(null);

    onBeforeUpdate(() => {

      gridItem.value = [];

    });

    function drag(e: DragEvent) {

      const parentRect = dashboardPanel.value.getBoundingClientRect();

      let mouseInGrid = false;

      if (

        ((mouseXY.x > parentRect.left) && (mouseXY.x < parentRect.right))

        && ((mouseXY.y > parentRect.top) && (mouseXY.y < parentRect.bottom))) {

        mouseInGrid = true;

      }

      if (mouseInGrid === true && (layout.value.findIndex(item => item.i === 'drop')) === -1) {

        layout.value.push({

          x: (layout.value.length * 2) % (GRID_COL_NUM || 12),

          y: layout.value.length + (GRID_COL_NUM || 12), // puts it at the bottom

          w: 1,

          h: 1,

          i: 'drop',

        });

      }

      const index = layout.value.findIndex(item => item.i === 'drop');

      if (index !== -1) {

        const el = gridItem.value[index];

        el.dragging.data = { top: mouseXY.y - parentRect.top, left: mouseXY.x - parentRect.left };

        const new_pos = el.calcXY(mouseXY.y - parentRect.top, mouseXY.x - parentRect.left);

        if (mouseInGrid === true) {

          gridLayout.value.dragEvent('dragstart', 'drop', new_pos.x, new_pos.y, 1, 1);

          DragPos.i = String(index);

          DragPos.x = layout.value[index].x;

          DragPos.y = layout.value[index].y;

        }

        if (mouseInGrid === false) {

          gridLayout.value.dragEvent('dragend', 'drop', new_pos.x, new_pos.y, 1, 1);

          layout.value = layout.value.filter(obj => obj.i !== 'drop');

        }

      }

    }

    function dragend(e: DragEvent) {

      // const parentRect = document.getElementById('dashboard-panel').getBoundingClientRect();

      const parentRect = dashboardPanel.value.getBoundingClientRect();

      let mouseInGrid = false;

      if (((mouseXY.x > parentRect.left) && (mouseXY.x < parentRect.right))

        && ((mouseXY.y > parentRect.top) && (mouseXY.y < parentRect.bottom))) {

        mouseInGrid = true;

      }

      if (mouseInGrid === true) {

        gridLayout.value.dragEvent('dragend', 'drop', DragPos.x, DragPos.y, 1, 1);

        layout.value = layout.value.filter(obj => obj.i !== 'drop');

        // UNCOMMENT below if you want to add a grid-item

        this.layout.push({

            x: DragPos.x,

            y: DragPos.y,

            w: 1,

            h: 1,

            i: DragPos.i,

        });

        this.$refs.gridLayout.dragEvent('dragend', DragPos.i, DragPos.x,DragPos.y,1,1);

        try {

            this.$refs.gridLayout.$children[this.layout.length].$refs.item.style.display="block";

        } catch {

        }

      }

    }

    return {

      gridLayout,

      gridItem,

      dashboardPanel,

      layout,

      movedId,

      inited,

      isLayoutReady,

      isShowEditRowDialog,

      rowForm,

    };

  },

  render() {

    if (!this.inited) {

      return (<Loading/>);

    }

    return (

      <div

        ref='dashboardPanel'

        id='dashboard-panel'

        class={'dashboard-panel flex-1'}>

        <GridLayout

          ref='gridLayout'

          layout={this.layout}

          col-num={GRID_COL_NUM}

          row-height={GRID_ROW_HEIGHT}

          is-resizabl={this.editable}

          is-draggable={this.editable}

          vertical-compact={true}

          use-css-transforms={false}

          margin={GRID_ROW_MARGIN}

          on-layout-updated={this.handleLayoutUpdated}

          on-layout-ready={this.onLayoutReady}

        >

          {

            this.layout.map((item) => {

              return (

                <GridItem

                  ref={(el: any) => {

                    if (el) {

                      this.gridItem.push(el);

                    }

                  }}

                  {{...item}}

                 >

                  {chart}

                </GridItem>

              );

            })

          }

        </GridLayout>

      </div>

    );

  },

});

当然,这个代码是抽离出来的。

这个vue3-grid-layout,自己写了弄了一版,https://github.com/zhoulujun/vue3-grid-layout

转载本站文章《vue2升级vue3: TSX Vue 3 Composition API Refs》,

请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/vue3/8873.html

相关文章

网友评论

      本文标题:vue2升级vue3: TSX Vue 3 Compositio

      本文链接:https://www.haomeiwen.com/subject/ioihwrtx.html