vue2升级vue3: TSX Vue 3 Composition API Refs
在vue2时代,$refs 直接操作子组件
1 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <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
1 | const el = ref<HTMLInputElement | null >( null ) |
普通元素
Typing Component Template Refs
1 2 3 4 5 6 7 | 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> 组件,是无法获取内容的,具体参看:
Refs 获取子元素,并操作子元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了