踩坑记27 vue3 @click 绑定多个事件 | props传输函数死循环 改用emits | ref数组 | template中不能直接使用console.log()

本文总结了Vue.js开发中的四个常见问题及其解决方案:1) @click事件绑定多个函数,逗号分隔即可;2) 使用props传递函数可能导致死循环,改用emit事件解决;3) 在模板中直接使用ref数组可能为空,需用reactive增加响应性;4) Vue模板内不能直接使用console.log,需自定义函数实现。通过这些技巧,可以避免Vue开发中的常见陷阱。

2021.9.22

坑81(vue、@click、绑定多个事件):@click 绑定多个事件,中间逗号隔开即可,参数各自传输。代码如下:

@click='function1,function2(para)'

参考:vue中@click绑定多个事件_YanHSama的博客-CSDN博客_@click绑定多个事件

坑82(vue、props、emits、触发函数):问题场景是父组件使用props传输函数到子组件运行,会死循环(原因不明)。

以add函数为例,主要代码是父组件中以属性式绑定函数 :addFunction='handleTotalAdd(data)' ,子组件中声明props: { addFunction: Function, } ,并在相应组件上绑定事件 @click='addFunction' 调用。具体代码如下:

// 有问题的代码,无点击就会一直触发函数,卡死

// 父组件

<TotalOperateBox 

    :addFunction='handleTotalAdd(data)'

    :removeFunction='handleTotalRemove(selectItems)'/>

// 子组件

<el-button @click='addFunction' >添加</el-button>

<el-popover placement='top' trigger='click' ref='popoverRef'>

    <div >确认批量删除?</div>

    <div >

        <el-button @click='popoverRef.hide()' >取消</el-button>

        <el-button @click='popoverRef.hide();removeFunction' >确认</el-button>

    </div>

    <template #reference>

        <el-button >删除</el-button>

    </template>

</el-popover>

...

    props:{

        selectLength:{

            type: Number,

            default: 0,

        },

        addFunction: Function,

        removeFunction: Function,

    },

解决方案:改用emit事件,可以正常触发。

以add函数为例,主要代码是父组件中以事件形式绑定函数 @totalAdd='handleTotalAdd(data)' ,子组件中声明emits: [ "totalAdd", ] ,并在相应组件上绑定事件 @click='$emit("totalAdd")' 触发。具体代码如下:

// 父组件

<TotalOperateBox 

    @totalAdd='handleTotalAdd(data)'

    @totalRemove='handleTotalRemove(selectItems)'/>



// 子组件

<el-button @click='$emit("totalAdd")' >添加</el-button>

<el-popover placement='top' trigger='click' ref='popoverRef'>

    <div >确认批量删除?</div>

    <div >

        <el-button @click='popoverRef.hide()' >取消</el-button>

        <el-button @click='popoverRef.hide();$emit("totalRemove")' >确认</el-button>

    </div>

    <template #reference>

        <el-button >删除</el-button>

    </template>

</el-popover>

...

    emits:[

        "totalAdd",

        "totalRemove",

    ],

参考:文档 emits 选项 | Vue.js (vuejs.org)

Vue 中,如何将函数作为 props 传递给组件_粉丝们务必加入微信粉丝群-CSDN博客

坑83(vue3、ref数组、reactive、响应性):之前根据 v-for 中的 Ref 数组 | Vue.js (vuejs.org) 直接采用数组存放元素对应ref数组。但在template中直接调用ref数组removePopoverRefs时,取到的是空数组,要进行相关操作必须写在script的函数中。错误代码如下:

<el-button @click='colseRemovePopover($index)'>取消</el-button>

<el-button @click='colseRemovePopover($index);handleRemove(row)' >确认</el-button>

...

let removePopoverRefs=[]

// 省略set、update函数,参考文档即可

const colseRemovePopover=(index)=>{

    // 在template中直接用下句回报错,因为取到的removePopoverRefs为空

    removePopoverRefs[index].hide()

}

优化方法:将removePopoverRefs写到state中,用reactive添加响应性

// 此时可以直接调用

<el-button @click='removePopoverRefs[$index].hide()' >取消</el-button>

<el-button @click='removePopoverRefs[$index].hide();handleRemove(row)' >确认</el-button>



const state=reactive({

    removePopoverRefs: [],

})

// 省略set、update函数,参考文档即可(与之前略有不同,removePopoverRefs需改为state.removePopoverRefs)

坑84(vue、template、console.log):template中无法直接用console.log()打印。

为什么需要?因为部分数据在template中调用获取时和script中获取的值有所不同。

<el-button @click='console.log(data)'>打印数据</el-button>  //报错

解决方案:自定义打印函数,设置打印按钮。

<el-button @click='printLog(data)'>打印数据</el-button>

...

const printLog=(data)=>{

    console.log(data)

}

坑85(vue、el-table、el-popover、ref):之前在el-table中,用ref数组控制每个el-popover的显示。现在进行封装,无需再使用ref数组。而在el-table之中调用该组件即可。

ref数组文档: v-for 中的 Ref 数组 | Vue.js (vuejs.org)

<template>

    <div class='operateBtn'>

        <el-popover trigger='click' ref='popoverRef'>

            <div>确认删除?</div>

            <div>

                <el-button @click='popoverRef.hide()'>取消</el-button>

                <el-button @click='popoverRef.hide(); $emit("remove")'>确认</el-button>

            </div>

            <template #reference>

                <div>删除</div>

            </template>

        </el-popover>

    </div>

</template>



<script>

import { ref } from 'vue'

export default {

    name:'OperateBox',

    emits:[

        "add",

        "edit",

        "remove",

    ],

    setup(props){

        let popoverRef=ref(null)



        return {

            popoverRef,

        }

    }

}

</script>

by 莫得感情踩坑机(限定)

<template> <div ref="wrapRef" :class="getWrapperClass"> <BasicForm ref="formRef" submitOnReset v-bind="getFormProps" v-if="getBindValues.useSearchForm" :tableAction="tableAction" @register="registerForm" @submit="handleSearchInfoChange" @advanced-change="redoHeight" @field-value-change="useDebounceFn(redoHeight, 300)()" class="search-form"> <template #[replaceFormSlotKey(item)]="data" v-for="item in getFormSlotKeys"> <slot :name="item" v-bind="data || {}"></slot> </template> </BasicForm> <Table ref="tableElRef" v-bind="getBindValues" class="ant-table-striped" :rowClassName="getCellStyle" v-show="getEmptyDataIsShowTable" @change="handleTableChange" @resizeColumn="handleResizeColumn"> <template #[item]="data" v-for="item in Object.keys($slots)" :key="item"> <slot :name="item" v-bind="data || {}"></slot> </template> <template #headerCell="{ column }"> <HeaderCell :column="getcolumn(column)" /> </template> <template #bodyCell="data"> <slot name="bodyCell" v-bind="data || {}"></slot> </template> </Table> </div> </template> <script lang="ts"> import type { BasicTableProps, TableActionType, SizeType, ColumnChangeParam } from &#39;./types/table&#39;; import { BasicForm, useForm } from &#39;@/components/Form&#39;; import { PageWrapperFixedHeightKey } from &#39;@/enums/pageEnum&#39;; import { InnerHandlers } from &#39;./types/table&#39;; import { defineComponent, ref, computed, unref, toRaw, inject, watchEffect, onMounted, reactive, watch } from &#39;vue&#39;; import { Table } from &#39;ant-design-vue&#39;; import HeaderCell from &#39;./components/HeaderCell.vue&#39;; import { usePagination } from &#39;./hooks/usePagination&#39;; import { useColumns } from &#39;./hooks/useColumns&#39;; import { useDataSource } from &#39;./hooks/useDataSource&#39;; import { useLoading } from &#39;./hooks/useLoading&#39;; import { useRowSelection } from &#39;./hooks/useRowSelection&#39;; import { useTableScroll } from &#39;./hooks/useTableScroll&#39;; import { useTableScrollTo } from &#39;./hooks/useScrollTo&#39;; import { useCustomRow } from &#39;./hooks/useCustomRow&#39;; import { useTableStyle } from &#39;./hooks/useTableStyle&#39;; import { useTableHeader } from &#39;./hooks/useTableHeader&#39;; import { useTableExpand } from &#39;./hooks/useTableExpand&#39;; import { createTableContext } from &#39;./hooks/useTableContext&#39;; import { useTableFooter } from &#39;./hooks/useTableFooter&#39;; import { useTableForm } from &#39;./hooks/useTableForm&#39;; import { useDesign } from &#39;@/hooks/web/useDesign&#39;; import { useDebounceFn } from &#39;@vueuse/core&#39;; import { omit } from &#39;lodash-es&#39;; import { basicProps } from &#39;./props&#39;; import { isFunction } from &#39;@/utils/is&#39;; import { warn } from &#39;@/utils/log&#39;; export default defineComponent({ name: &#39;BasicTable&#39;, components: { Table, BasicForm, HeaderCell, }, props: { ...basicProps, loading: { type: Boolean, default: false, // 默认值 }, dataSource: { type: Array, default: () => [], // 允许外部传入数据源,默认为空数组 }, pagination: { type: Object, default: () => ({}), // 默认值 }, }, emits: [ &#39;fetch-success&#39;, &#39;fetch-error&#39;, &#39;selection-change&#39;, &#39;register&#39;, &#39;row-click&#39;, &#39;row-dbClick&#39;, &#39;row-contextmenu&#39;, &#39;row-mouseenter&#39;, &#39;row-mouseleave&#39;, &#39;edit-end&#39;, &#39;edit-cancel&#39;, &#39;edit-row-end&#39;, &#39;edit-change&#39;, &#39;expanded-rows-change&#39;, &#39;change&#39;, &#39;columns-change&#39;, &#39;changeMenu&#39;, ], setup(props, { attrs, emit, slots, expose }) { const tableElRef = ref(null); const tableData = ref<Recordable[]>([]); const wrapRef = ref(null); const formRef = ref(null); const innerPropsRef = ref<Partial<BasicTableProps>>(); const { prefixCls } = useDesign(&#39;basic-table&#39;); const [registerForm, formActions] = useForm(); const getProps = computed(() => { return { ...props, ...unref(innerPropsRef) } as BasicTableProps; }); const isFixedHeightPage = inject(PageWrapperFixedHeightKey, false); watchEffect(() => { unref(isFixedHeightPage) && props.canResize && warn("&#39;canResize&#39; of BasicTable may not work in PageWrapper with &#39;fixedHeight&#39; (especially in hot updates)"); }); const { getLoading, setLoading } = useLoading(getProps); const { getPaginationInfo, getPagination, setPagination, setShowPagination, getShowPagination } = usePagination(getProps); const { getRowSelection, getRowSelectionRef, getSelectRows, setSelectedRows, clearSelectedRowKeys, getSelectRowKeys, deleteSelectRowByKey, setSelectedRowKeys, } = useRowSelection(getProps, tableData, emit); const { getExpandOption, expandAll, expandRows, collapseAll, getIsExpanded } = useTableExpand(getProps, tableData, emit); const { handleTableChange: onTableChange, getDataSourceRef, getDataSource, getRawDataSource, getFetchParams, setTableData, updateTableDataRecord, deleteTableDataRecord, insertTableDataRecord, findTableDataRecord, fetch, getRowKey, reload, getAutoCreateKey, updateTableData, } = useDataSource( getProps, { tableData, getPaginationInfo, setLoading, setPagination, getFieldsValue: formActions.getFieldsValue, clearSelectedRowKeys, expandAll, }, emit, ); const addFakeData = () => { if (props.dataSource.length === 0) { tableData.value = []; } else { tableData.value = props.dataSource; // 使用传入的数据源 } }; function handleTableChange(...args) { onTableChange.call(undefined, ...args); emit(&#39;change&#39;, ...args); // 解决通过useTable注册onChange时不起作用的问题 const { onChange } = unref(getProps); onChange && isFunction(onChange) && onChange.call(undefined, ...args); } const { getViewColumns, getColumns, setCacheColumnsByField, setCacheColumns, setColumns, getColumnsRef, getCacheColumns } = useColumns( getProps, getPaginationInfo, ); const { getScrollRef, redoHeight } = useTableScroll(getProps, tableElRef, getColumnsRef, getRowSelectionRef, getDataSourceRef, wrapRef, formRef); const { scrollTo } = useTableScrollTo(tableElRef, getDataSourceRef); const { customRow } = useCustomRow(getProps, { setSelectedRowKeys, getSelectRowKeys, clearSelectedRowKeys, getAutoCreateKey, emit, }); const { getRowClassName } = useTableStyle(getProps, prefixCls); const handlers: InnerHandlers = { onColumnsChange: (data: ColumnChangeParam[]) => { emit(&#39;columns-change&#39;, data); unref(getProps).onColumnsChange?.(data); }, }; const { getHeaderProps } = useTableHeader(getProps, slots, handlers); const { getFooterProps } = useTableFooter(getProps, getScrollRef, tableElRef, getDataSourceRef); const { getFormProps, replaceFormSlotKey, getFormSlotKeys, handleSearchInfoChange } = useTableForm(getProps, slots, fetch, getLoading); const getBindValues = computed(() => { const dataSource = unref(getDataSourceRef); let propsData: Recordable = { ...attrs, ...unref(getProps), customRow: unref(getProps).customRow || customRow, ...unref(getHeaderProps), scroll: unref(getScrollRef), loading: unref(getLoading), tableLayout: &#39;fixed&#39;, rowSelection: unref(getRowSelectionRef), rowKey: unref(getRowKey), columns: toRaw(unref(getViewColumns)), pagination: toRaw(unref(getPaginationInfo)), dataSource, footer: unref(getFooterProps), ...unref(getExpandOption), }; propsData = omit(propsData, [&#39;class&#39;, &#39;onChange&#39;]); return propsData; }); const getWrapperClass = computed(() => { const values = unref(getBindValues); return [ prefixCls, attrs.class, { [`${prefixCls}-form-container`]: values.useSearchForm, [`${prefixCls}--inset`]: values.inset, }, ]; }); const getEmptyDataIsShowTable = computed(() => { const { emptyDataIsShowTable, useSearchForm } = unref(getProps); if (emptyDataIsShowTable || !useSearchForm) { return true; } return !!unref(getDataSourceRef).length; }); function getcolumn(column: any) { // console.log(column); if (!column.hasOwnProperty(&#39;fixed&#39;) && column.hasOwnProperty(&#39;width&#39;) && (column.key != undefined || column.key != null)) { column.resizable = true; } return column; } function handleResizeColumn(w, col) { col.width = w; } function setProps(props: Partial<BasicTableProps>) { innerPropsRef.value = { ...unref(innerPropsRef), ...props }; } const tableAction: TableActionType = { reload, getSelectRows, setSelectedRows, clearSelectedRowKeys, getSelectRowKeys, deleteSelectRowByKey, setPagination, setTableData, updateTableDataRecord, deleteTableDataRecord, insertTableDataRecord, findTableDataRecord, redoHeight, setSelectedRowKeys, setColumns, setLoading, getDataSource, getRawDataSource, getFetchParams, setProps, getRowSelection, getPaginationRef: getPagination, getColumns, getCacheColumns, emit, updateTableData, setShowPagination, getShowPagination, setCacheColumnsByField, expandAll, expandRows, collapseAll, getIsExpanded, scrollTo, getSize: () => { return unref(getBindValues).size as SizeType; }, setCacheColumns, }; createTableContext({ ...tableAction, wrapRef, getBindValues }); expose(tableAction); emit(&#39;register&#39;, tableAction, formActions); function getFromvalue(value:any){ console.log(value) } onMounted(() => { addFakeData(); // 添加假数据 console.log(formRef.value) }); function getCellStyle(record, index) { return index % 2 === 0 ? &#39;ant-table-row-even&#39; : &#39;ant-table-row-odd&#39;; // 根据索引返回不同的类名 } return { getCellStyle, formRef, tableElRef, getBindValues, getLoading, registerForm, handleSearchInfoChange, getEmptyDataIsShowTable, handleTableChange, getRowClassName, wrapRef, tableAction, redoHeight, getFormProps: getFormProps as any, replaceFormSlotKey, getFormSlotKeys, getWrapperClass, columns: getViewColumns, useDebounceFn, getcolumn, handleResizeColumn, }; }, }); </script> <style lang="less"> .ant-table-tbody > tr.ant-table-row-even > td { background-color: #fafafa; } .ant-table-resize-handle { border-left: 1px solid #fafafa !important; // width: 1px !important; } .ant-table-tbody > tr.ant-table-row-odd > td { background-color: #fff; } @border-color: #cecece4d; @prefix-cls: ~&#39;@{namespace}-basic-table&#39;; [data-theme=&#39;dark&#39;] { .ant-table-tbody > tr:hover.ant-table-row-selected > td, .ant-table-tbody > tr.ant-table-row-selected td { background-color: #262626; } } .@{prefix-cls} { max-width: 100%; height: 100%; &-row__striped { td { background-color: @app-content-background; } } &-form-container { .ant-form { width: 100%; padding: 10px 10px 0; margin-bottom: 10px; background-color: @component-background; } } .ant-table-cell { .ant-tag { margin-right: 0; } } .ant-table-wrapper { height: 100%; background-color: @component-background; border-radius: 2px; .ant-table-title { min-height: 40px; padding: 0 !important; } .ant-table.ant-table-bordered .ant-table-title { border: none !important; } } .ant-table { width: 100%; overflow-x: hidden; &-title { display: flex; border-bottom: none; justify-content: space-between; align-items: center; } } .ant-table-pagination.ant-pagination { margin: 10px 0 0; padding: 0 10px 10px; } .ant-table-footer { padding: 0; .ant-table-wrapper { padding: 0; } table { border: none !important; } .ant-table-body { overflow-x: hidden !important; } td { padding: 12px 8px; } } &--inset { .ant-table-wrapper { padding: 0; } } } </style> console.log(formRef.value)获取是null
07-23
<template> <view class="kf_popup" :class="[{&#39;zero-bottom&#39;:position==&#39;bottom&#39;}]" v-if="showPrivacy"> <view class="kf_popup-container" :style="{&#39;--color&#39;:color,&#39;--bgcolor&#39;:bgcolor}"> <view class="delicon" @click="handleRefuse"> <image :src="imgURl1" mode="widthFix"></image> </view> <view class="title"> {{title}} </view> <button class="avatar" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"> <image v-show="avatarUrl" :src="avatarUrl" mode="widthFix"></image> <image v-show="!avatarUrl" :src="imgURl2" mode="widthFix"></image> </button> <view class="nickname"> <view class="text"> 昵称 </view> <view class="input"> <input placeholder="请输入昵称" type="nickname" @blur="nicknameonBlur" placeholder-style="color:rgba(163, 167, 179, 1)" /> </view> </view> <view class="phone"> <view class="text"> 手机 </view> <button class="input btn " open-type="getPhoneNumber" @getphonenumber="getPhone"> <!-- <view class="input "> --> <view class="i_left"> <text v-show="!phoneNumber" class="placeholder">绑定手机号</text> <text v-show="phoneNumber" class="">{{phoneNumber}}</text> </view> <image class="i_right" :src="imgURl3" mode=""></image> <!-- </view> --> </button> </view> <view class="footer"> <view class="btn disagree-btn" @click="handleRefuse">{{cancelText}} </view> <button id="agree-btn" class="btn agree-btn" @click="handleAgree"> {{confirmText}} </button> </view> </view> </view> </template>根据这个内容帮我改为vue3+ts的写法 使用uniapp语法
03-18
<template> <div id="area-selector"> <FilterBox v-model:visible="visible"> <DropDownSearch /> </FilterBox> <RegionalSearchBox v-model="visible" :areaType="areaType" :geographicalLevel="geographicalLevel" @onClick="onClick" @onConfirm="onConfirm" > <template v-if="multipleBtn" #[slotIndex]="data"> <MultipleChoiceOfRegions v-model:value="checkList" :arr="regionOptions" :disabled="!hasAssetSecurityPermission" /> </template> <template #footerLeft> <el-button class="cancel" @click.stop="onClick(&#39;全球&#39;, 0)"> {{ $t(&#39;全球&#39;) }} </el-button> </template> <template v-if="multipleBtn" #footerRight> <span class="multiple">{{ $t(&#39;选模式&#39;) }}</span> <el-switch v-model="isCanMultiple" style="margin-right: 10px" /> </template> </RegionalSearchBox> </div> </template> <script lang="ts" setup> import FilterBox from &#39;./components/FilterBox.vue&#39;; import DropDownSearch from &#39;./components/drop-down-search/DropDownSearch.vue&#39;; import RegionalSearchBox from &#39;@/views/DCPhysicalArchitecture/components/regional-search-box/RegionalSearchBox.vue&#39;; import MultipleChoiceOfRegions from &#39;./components/MultipleChoiceOfRegions.vue&#39;; import { useHeaderAreaSearchHooks } from &#39;./compoasble/HeaderAreaSearch&#39;; import { ref } from &#39;vue&#39;; const visible = ref(false); const { areaType, geographicalLevel, onConfirm, onClick, slotIndex, isCanMultiple, multipleBtn, checkList, regionOptions, hasAssetSecurityPermission, } = useHeaderAreaSearchHooks(); </script> <style lang="less" scoped> @import &#39;@/styles/commonCmptStyle.less&#39;; #getCommonPopperStyleId(drop-down); #area-selector { position: relative; :deep(.left-wrapper) { display: none; } #drop-down { left: 0px !important; } :deep(#filter-box) { z-index: 999; height: 26px !important; .text { white-space: nowrap; } .el-input { width: auto; } } .multiple { margin-right: 6px; font-family: Microsoft YaHei, Microsoft YaHei-Bold, serif; font-size: 14px; color: var(--color6); } } </style> 出现了问题,在大区点击选模式,要展开区域层级时候,区域里面的值都不出现了
10-28
<template> <div class="container"> <div class="content"> <el-tabs v-model="activeName"> <el-tab-pane :lazy="true" :label="t(&#39;资产安全&#39;)" name="assetSafety"> <AssetOverview :assetOverviewData="digitalSummary.top" /> <template v-if="warnFlag.get(&#39;assetSecurityWarnFlag&#39;)"> <RiskComp v-if="![&#39;dc&#39;, &#39;floor&#39;, &#39;room&#39;].includes(showLevel)" :data="digitalSummary.top || {}" @detail-show="sendToParent" /> <br /> <AssetTabCard v-if="![&#39;dc&#39;, &#39;floor&#39;, &#39;room&#39;].includes(showLevel)" :data="formattedData || {}" :productRole="propertyMetricsManagerStore" /> <FloorRoomCard v-if="showLevel === &#39;dc&#39;" :data="digitalSummary.top || {}" :showLevel="showLevel" /> <RoomCard v-if="showLevel === &#39;floor&#39;" :data="digitalSummary.top || {}" :showLevel="showLevel" /> </template> </el-tab-pane> </el-tabs> </div> <teleport to=".app-container-right"> <div v-if="showDetail && productRole.role[1] === &#39;amira.Infrastructure.assetSecurity&#39;" class="asset-security-detail-body" > <AssetSafetyDetail v-model:visible="showDetail" /> </div> </teleport> </div> </template> <script lang="ts" setup> import { computed, ref } from &#39;vue&#39;; import { useI18n } from &#39;vue-i18n&#39;; import RiskComp from &#39;@/views/DCPhysicalArchitecture/GlobalLayout/components/AsideLayout/components/AssetSafetyAside/components/RiskComp.vue&#39;; import AssetOverview from &#39;@/views/DCPhysicalArchitecture/GlobalLayout/components/AsideLayout/components/AssetSafetyAside/components/AssetOverview.vue&#39;; import AssetTabCard from &#39;./components/asset-tab-card/AssetTabCard.vue&#39;; import FloorRoomCard from &#39;./components/floor-room-card/FloorRoomCard.vue&#39;; import RoomCard from &#39;@/views/DCPhysicalArchitecture/GlobalLayout/components/AsideLayout/components/AssetSafetyAside/components/RoomCard.vue&#39;; import AssetSafetyDetail from &#39;./components/asset-safety-detail/AssetSafetyDetail.vue&#39;; import { useDigitalSummary } from &#39;@/application/core/infra-layout/composables/useDigitalSummary&#39;; import { useProductRole } from &#39;@/application/core/infra-layout/composables/useProductRole&#39;; import { usePropertyMetricsManager } from &#39;@/application/core/infra-layout/composables/usePropertyMetricsManager&#39;; import { warnFlagStore } from &#39;@/views/DCPhysicalArchitecture/components/user-settings/components/warnning-setting/store/WarnningWhetherOpen&#39;; import { useMapLevelDataManager } from &#39;@/application/core/infra-layout/composables/useMapLevelDataManager&#39;; const warnFlag = warnFlagStore(); const propertyMetricsManagerStore = usePropertyMetricsManager(); const mapLevelDataManager = useMapLevelDataManager(); const showLevel = computed(() => mapLevelDataManager.getMapLevel()); const digitalSummary = useDigitalSummary(); const productRole = useProductRole(); const showDetail = ref(false); // 资产安全展示明细 const formattedData = computed(() => ({ top: digitalSummary.top, list: digitalSummary.list, summary: digitalSummary.summary, })); const { t } = useI18n(); const activeName = ref<string>(&#39;assetSafety&#39;); const sendToParent = val => { console.lop(&#39;val&#39;, val); showDetail.value = val; }; </script> <style lang="less" scoped> .container { width: 100%; padding: 0 20px 20px 20px; overflow: hidden; } .dark { .content { :deep(.el-tabs__item.is-active) { color: #715afb; } :deep(.el-tabs__active-bar) { background-color: #715afb; } } } .asset-security-detail-body { background-color: #dfe1e6; position: absolute; top: 136px; height: calc(100% - 136px); width: calc(100% - 560px); z-index: 888; } </style> 这是父组件
最新发布
11-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值