vue3+TS,父组件传值给子组件,但是父组件显示没有该属性

2022-10-17 13:39:46 +08:00
 slmakm

父组件和配置文件

因为是封装的原因,所以只要看:<page-content />组件和配置文件contentTableConfig

user.vue

<template>
  <div class="user">
    <page-content
      :contentTableConfig="contentTableConfig"
      pageName="users"
    ></page-content>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
//引入展示 table 组件
import PageContent from "@/components/page-content";
//引入展示 table 组件的数据和配置
import { contentTableConfig } from "./config/content.config";

export default defineComponent({
  name: "users",
  components: {
    PageContent
  },
  setup() {
    return {
      contentTableConfig
    };
  }
});
</script>

<style scoped>
.content {
  padding: 20px;
  border-top: 20px solid #f5f5f5;
}
</style>

content.config.ts

export const contentTableConfig = {
  title: "用户列表",
  propList: [
    { prop: "name", label: "用户名", minWidth: "100" },
    { prop: "realname", label: "真实姓名", minWidth: "100" },
    { prop: "cellphonne", label: "电话号码", minWidth: "200" },
    { prop: "enable", label: "状态", minWidth: "100", slotName: "status" },
    {
      prop: "createAt",
      label: "创建时间",
      minWidth: "230",
      slotName: "createAt"
    },
    {
      prop: "updateAt",
      label: "更新时间",
      minWidth: "230",
      slotName: "updateAt"
    },
    { label: "操作", minWidth: "120", slotName: "handler" }
  ],
  showIndexColumn: true,
  showSelectColumn: true
};

子组件

page-content.vue

<template>
  <div class="page-content">
    <hy-table v-bind="contentTableConfig" :listData="dataList">
      <!-- 1.header 中的插槽 -->
      <template #headerHandler>
        <el-button type="primary" size="medium">新建用户</el-button>
      </template>

      <!-- 2.列中的插槽 -->
      <template #status="scope">
        <el-button
          plain
          size="mini"
          :type="scope.row.enable ? 'success' : 'danger'"
        >
          {{ scope.row.enable ? "启用" : "禁用" }}
        </el-button>
      </template>
      <template #createAt="scope">
        <span>{{ $filters.formatTime(scope.row.createAt) }}</span>
      </template>
      <template #updateAt="scope">
        <span>{{ $filters.formatTime(scope.row.updateAt) }}</span>
      </template>
      <template #handler>
        <div class="handle-btns">
          <el-button icon="el-icon-edit" size="mini" type="text"
            >编辑</el-button
          >
          <el-button icon="el-icon-delete" size="mini" type="text"
            >删除</el-button
          >
        </div>
      </template>
    </hy-table>
  </div>
</template>

<script lang="ts">
import { defineComponent, computed } from "vue";
import { useStore } from "@/store";

import HyTable from "@/base-ui/table";

export default defineComponent({
  components: {
    HyTable
  },
  props: {
    contentTableConfig: { //配置文件,这个要传给子组件 HyTable
      type: Object,
      require: true
    },
    pageName: {
      type: String,
      required: true
    }
  },
  setup(props) {
    const dataList = computed(() =>
      store.getters[`system/pageListData`](props.pageName)
    );
    return {
      dataList
    };
  }
});
</script>

<style scoped>
.page-content {
  padding: 20px;
  border-top: 20px solid #f5f5f5;
}
</style>

HyTable.vue

<template>
  <div class="hy-table">
    <div class="header">
      <slot name="header">
        <div class="title">{{ title }}</div>
        <div class="handler">
          <slot name="headerHandler"></slot>
        </div>
      </slot>
    </div>
    <el-table
      :data="listData"
      border
      style="width: 100%"
      @selection-change="handleSelectionChange"
    >
      <el-table-column
        v-if="showSelectColumn"
        type="selection"
        align="center"
        width="60"
      ></el-table-column>
      <el-table-column
        v-if="showIndexColumn"
        type="index"
        label="序号"
        align="center"
        width="80"
      ></el-table-column>
      <template v-for="propItem in propList" :key="propItem.prop">
        <el-table-column v-bind="propItem" align="center">
          <template #default="scope">
            <slot :name="propItem.slotName" :row="scope.row">
              {{ scope.row[propItem.prop] }}
            </slot>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <div class="footer">
      <slot name="footer">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :page-sizes="[100, 200, 300, 400]"
          :page-size="100"
          layout="total, sizes, prev, pager, next, jumper"
          :total="400"
        >
        </el-pagination>
      </slot>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from "vue";

export default defineComponent({
  props: {
    listData: {
      type: Array,
      required: true
    },
    title: { //通过 page-content 组件传过来的 contentTableConfig 对象的属性会不会自动解析,是不是这儿出问题了?
      type: String,
      default: ""
    },
    propList: {
      type: Array as PropType<any[]>,
      required: true
    },
    showIndexColumn: {
      type: Boolean,
      default: false
    },
    showSelectColumn: {
      type: Boolean,
      default: false
    }
  },
  emits: ["selectionChange"],
  setup(props, { emit }) {
    const handleSelectionChange = (value: any) => {
      emit("selectionChange", value);
    };

    const handleSizeChange = () => {
      return;
    };
    const handleCurrentChange = () => {
      return;
    };

    return {
      handleSelectionChange,
      handleSizeChange,
      handleCurrentChange
    };
  }
});
</script>

<style scoped lang="less">
.header {
  display: flex;
  height: 45px;
  padding: 0 5px;
  justify-content: space-between;
  align-items: center;

  .title {
    font-size: 20px;
    font-weight: 700;
  }

  .handler {
    align-items: center;
  }
}

.footer {
  margin-top: 15px;

  .el-pagination {
    text-align: right;
  }
}
</style>

演示 contentTableConfig 传输过程

显示错误的图片

问题出在哪儿了?

1555 次点击
所在节点    Vue.js
10 条回复
Uahh
2022-10-17 14:24:22 +08:00
试试把 contentTableConfig 变量名改成 content_table_config
moreant
2022-10-17 14:48:58 +08:00
page-content.vue 组件的 props 的 contentTableConfig 类型是 Object ,volar 无法推断出类型吧
slmakm
2022-10-17 15:40:02 +08:00
@Uahh 试过了,不行的哦
slmakm
2022-10-17 15:41:08 +08:00
@moreant 可能你说的对,但我不知道怎么解决?流汗
tomieric
2022-10-17 15:46:27 +08:00
```js
propList: {
type: Array as PropType<any[]>,
required: true
},
```

我只看到这个
slmakm
2022-10-17 15:53:35 +08:00
@tomieric 是 as PropType<any[]>出问题了吗?疑惑,没看懂你说的。
slmakm
2022-10-17 15:59:15 +08:00
moreant
2022-10-17 17:33:15 +08:00
@slmakm

page-content.vue 文件

```js
import type { PropType } from 'vue'

interface ContentProp {
prop: string
label: string
minWidth: string
}

interface Content {
title: string
propList: Array<ContentProp>
showIndexColumn: boolean
showSelectColumn: boolean
}

export default defineComponent({
props: {
book: {
// 提供相对 `Object` 更确定的类型
type: Object as PropType<Content>,
required: true
}
}
})

```

参考
https://cn.vuejs.org/guide/typescript/options-api.html#typing-component-props:~:text=%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8-,PropType,-%E8%BF%99%E4%B8%AA%E5%B7%A5%E5%85%B7%E7%B1%BB%E5%9E%8B

顺便一提,建议早用组合式与 <script setup> 早舒服
slmakm
2022-10-17 18:31:17 +08:00
@moreant 牛皮,谢谢大哥
current
2022-10-18 19:22:54 +08:00
被 cue 的莫名其妙。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/887497

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX