前言:我想实现表格中点击详情弹窗出一个表格展示该行详细信息。想着这个弹窗里用子组件展示。分担父组件下,怕代码过多。(使用NModal组件弹窗展示)
等我一波百度,嗯,实现方法挺多嘛,什么refs什么的,看似条条大路通罗马,我一试,一试一条死路/(ㄒoㄒ)/~~,最后也没用到refs(我还是更倾向于用这个,毕竟vue2都是这样),一直说找不到$refs,我还去了解了底层**getCurrentInstance()
**逻辑,有些又说不提倡这种方式,这个方法能看到我定义的的ref方法名,但是里面是null,又或者我当时子组件不是用的而是用的
export default defineComponent下的setup(){}
,所以我不信邪,我子组件又改成了export default
还是不行。最后使用的defineProps
父组件:重点在
,import childDetail from './childDetail.vue'
,以及需要改变childRef值的方法detailsEvent()
。
<template>
<div class="content-box">
<n-form label-placement="left"
inline
label-width="120px">
<n-form-item label="UserName/Email">
<n-input v-model:value="usersListRef.name_email"
type="text"
@input="queryConditional"
:style="{ width: '420px' }"
placeholder="Please enter username or email (At least three letters)" />
</n-form-item>
<!-- <n-form-item label="Email">
<n-input v-model:value="usersListRef.email"
type="text"
:style="{ width: '280px' }"
placeholder="Please enter email" />
</n-form-item> -->
</n-form>
<n-space vertical :size="12" >
<n-data-table style="min-height:calc(100vh - 223px);"
:bordered="false"
:single-line="false"
:columns="columns"
:data="data"
:loading="loading"
:pagination="pagination"
striped
/>
</n-space>
</div>
<n-modal
v-model:show="showModal"
class="custom-card"
preset="card"
:style="bodyStyle"
title="Details"
size="huge"
:bordered="false"
:segmented="segmented"
>
<!-- <template #header-extra>
噢!
</template> -->
<child-detail :id="childRef"/>
<!-- <n-data-table
:bordered="false"
:single-line="false"
:columns="columns"
:data="data"
:loading="loading"
:max-height="300"
:pagination="pagination"
striped
/> -->
<!-- <template #footer>
尾部
</template> -->
</n-modal>
</template>
<script lang="ts">
import {NInput, NSpace,NButton, NForm, NFormItem, NDataTable, NModal} from 'naive-ui'
import {ref, defineComponent, Ref, getCurrentInstance, onMounted } from 'vue'
import { apiTokenRequest } from "@/stores/modules/apiEncapsulation"
import type { PaidlicenseResult } from "../../api/classes";
import type { DataTableColumns } from 'naive-ui'
import type { DataResult } from "../../api/classes";
import { h } from 'vue'
import { NTag, NAvatar } from 'naive-ui'
import { createDiscreteApi} from "naive-ui"
import childDetail from './childDetail.vue'
interface UsersListType {
username : string | null
email: string | null
name_email: string | null
pageSize: number
}
interface UsersListAll {
id: string
}
export default defineComponent({
components: {
NInput,
NSpace,
NButton,
NForm,
NFormItem,
NDataTable,
NModal,
PaidLicenseDetail
// NSwitch
},
setup(){
const childRef = ref("")
const proxy = getCurrentInstance()!.proxy
const {message} = createDiscreteApi(["message"])
const { dialog } = createDiscreteApi(["dialog"])
let showModal = ref(false)
const loadingRef = ref(true)
const imgUrl = new URL('../../assets/AccountCircleOutlined.svg', import.meta.url).href
const usersListRef = ref<UsersListType>({
username: null,
email: null,
name_email: null,
pageSize: 12
})
const usersListAllResult : Ref<UsersListAll[]> = ref([])
const getPaidResultMethod = async ()=>{
await apiTokenRequest<UsersListAll[]>(
"url",
"get").then(function(res){
if(res){
console.log('list===', res);
usersListAllResult.value = res
loadingRef.value = false
console.log('usersListAllResult===>', usersListAllResult.value);
}
})
}
getPaidResultMethod()
const queryConditional =async () => {
console.log('条件查询===>', res);
}
const createColumns = ({
detailsLicenses,deleteItem,handleChange,statusRes
}: {
detailsLicenses: (rowData: UsersListAll) => void,
deleteItem: (rowData: UsersListAll) => void,
handleChange: (rowData: UsersListAll) => void,
statusRes: (status: number) => boolean,
}): DataTableColumns<UsersListAll> => {
return [
{
title: 'Name',
key: 'name'
},
{
title: 'Avatar',
key: 'headerUrl',
width:"120px",
render (row) {
return h(
NAvatar,
{
style: {
height:'50px',
width:'50px',
},
color: '#fff',
round:true,
bordered: true,
src:row.headerUrl ? row.headerUrl:imgUrl
},
)
}
},
{
title: 'Action',
key: 'actions',
width:"260px",
render (row) {
return [
h(
NButton,
{
size: 'small',
type: "info",
// quaternary: true,
onClick: () => detailsLicenses(row)
},
{ default: () => 'Licenses' }
),
h( // 启、禁用
NButton,
{
size: 'small',
style: {
marginLeft: "10px",
width: "70px"
},
type: 'primary',
// quaternary: true,
onClick: () => handleChange(row)
},
{ default: () => row.status>0 ? 'Enable':'Disable' }
),
h( // 删除
NButton,
{
size: 'small',
style: {
marginLeft: "10px",
},
type:"error",
// quaternary: true,
onClick: () => deleteItem(row)
},
{ default: () => 'Delete' }
),
]
}
}
]
}
const detailsEvent = async (rowData:UsersListAll)=>{
showModal.value = true
childRef.value= rowData.id
}
const deleteEvent = async (rowData:UsersListAll)=>{
}
const handleChangeEvent = async (rowData:UsersListAll)=>{
}
return{
childRef,
usersListRef,
usersListAllResult,
showModal,
loading: loadingRef,
queryConditional,
data: usersListAllResult,
columns: createColumns({
detailsLicenses (rowData) {
message.info('send mail to ' + rowData.name)
detailsEvent(rowData)
},
deleteItem(rowData){
deleteEvent(rowData)
},
handleChange(rowData){
handleChangeEvent(rowData)
}
}),
pagination: {
pageSize: usersListRef.value.pageSize
// pageSize: 2
},
bodyStyle: {
width: '60vw',
// height: '60vh'
},
segmented: {
content: 'soft',
// footer: 'soft'
} as const,
}
}
})
</script>
<style scoped>
</style>
子组件:都是重点。
<template>
<n-data-table
:bordered="false"
:single-line="false"
:data="detailsData"
:loading="loading"
:columns="childColumns"
:max-height="300"
:pagination="pagination"
striped
/>
1111111{{ props?.id }}
</template>
<script lang="ts">
import {NInput, NSpace,NButton, NForm, NFormItem, NDataTable, NModal} from 'naive-ui'
import { defineComponent, ref, Ref, defineProps, onMounted } from 'vue'
import { apiTokenRequest } from "@/stores/modules/apiEncapsulation"
import type { Result } from "../../api/classes";
import type { DataTableColumns } from 'naive-ui'
export default defineComponent({
components:{
NDataTable
},
})
</script>
<script setup lang="ts">
const props = defineProps({
id:
{
type: String,
}
})
const pagination = ref( {
pageSize: 10
})
const loading = ref(true)
let childColumns :any
const detailsData : Ref<PaidlicenseResult[]> = ref([])
const getDetail= async (id:string|undefined)=>{
await apiTokenRequest<Result[]>(
"url",
"get").then(function(res){
if(res){
console.log('details===', res);
loading.value = false
detailsData.value = res
childColumns = columns()
console.log('=====detailsData===', detailsData.value);
}
})
}
getDetail(props.id)
const columns = () => {
return [
{
title:'id',
key: 'id'
}
]
}
</script>
我原本想await 调用getDetail() 会报错。setup function returned a promise, but no
,想用await是数据还没请求完,表格列名又加载了(当时还没有使用childColumns = columns()
),就会同时出现这些报错type check failed for prop "columns". Expected Array, got Function
和Unhandled error during execution of setup function
还有Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at
。后面我想着,那就等数据请求成功后再调用columns(),用childColumns 字段赋值给组件。