Vue3 父组件传值给子组件+以及使用NModal组件

前言:我想实现表格中点击详情弹窗出一个表格展示该行详细信息。想着这个弹窗里用子组件展示。分担父组件下,怕代码过多。(使用NModal组件弹窗展示)

等我一波百度,嗯,实现方法挺多嘛,什么refs什么的,看似条条大路通罗马,我一试,一试一条死路/(ㄒoㄒ)/~~,最后也没用到refs(我还是更倾向于用这个,毕竟vue2都是这样),一直说找不到$refs,我还去了解了底层**getCurrentInstance()**逻辑,有些又说不提倡这种方式,这个方法能看到我定义的的ref方法名,但是里面是null,又或者我当时子组件不是用的<script setup lang="ts">而是用的export default defineComponent下的setup(){},所以我不信邪,我子组件又改成了export default 还是不行。最后使用的defineProps
在这里插入图片描述

父组件:重点在 <child-detail :id="childRef"/>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 <Suspense> boundary was found in the parent component tree. A component with async setup() must be nested in a <Suspense> in order to be rendered. ,想用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 字段赋值给组件。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值