[渲染层错误] [Component] <text>: <cover-view/> 内只能嵌套 <cover-view/> <cover-image/> <button/> <navigator/>

错误分析

这个错误信息表明在小程序开发里,你在 <cover-view> 组件内部嵌套了不被允许的 <text> 组件。按照小程序的规则,<cover-view> 内部仅能嵌套 <cover-view><cover-image><button><navigator><ad> 这些组件,要是嵌套了其他组件(像这里的 <text>),在真机上这些子节点会被忽略。

解决方案

1. 将 <text> 替换为 <cover-view>

由于 <cover-view> 本身就可以用来显示文本内容,所以你可以把 <text> 替换成 <cover-view>。示例如下:

<cover-view class="map-cover-view">
  <cover-view v-on:tap="listTap">列表</cover-view>
</cover-view>
2. 保持结构嵌套的合规性

要是你原本打算在 <cover-view> 里使用更复杂的结构,就要保证所有子组件都在允许的范围内。比如,你想显示图片和文本,可以这样写:

<cover-view class="map-cover-view">
  <cover-image src="your-image-url.png"></cover-image>
  <cover-view v-on:tap="listTap">列表</cover-view>
</cover-view>
3. 样式调整

如果使用 <cover-view> 来替代 <text>,可能需要对样式进行一些调整,以保证显示效果和原来一致。可以在 CSS 里对 <cover-view> 进行样式设置:

.map-cover-view cover-view {
  color: black; /* 设置文本颜色 */
  font-size: 14px; /* 设置字体大小 */
}

代码示例总结

以下是一个完整的示例,包含了修改后的 WXML 和对应的样式:

<!-- wxml 文件 -->
<cover-view class="map-cover-view">
  <cover-view v-on:tap="listTap">列表</cover-view>
</cover-view>
/* wxss 文件 */
.map-cover-view {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: white;
  padding: 5px;
  border-radius: 5px;
}

.map-cover-view cover-view {
  color: black;
  font-size: 14px;
}

通过以上操作,你就可以解决 <cover-view> 内部嵌套组件不合法的问题。

<template> <q-page :key="$route.fullPath"> <!--表头--> <q-banner class="q-py-sm q-px-xs"> <q-breadcrumbs> <q-breadcrumbs-el v-for="item in breadcrumbs" :key="item" :label="item" icon="widgets" /> </q-breadcrumbs> </q-banner> <div class="row q-py-xs q-px-xs items-center"> <div class="col-2"> <q-select dense outlined v-model="scriptListContext.currentView" :options="scriptListContext.views" option-label="name" option-value="id" emit-value map-options @update:model-value="changedView" fit :label="t('Views')" /> </div> <div class="q-mx-sm"> <q-btn v-if="scriptListContext.currentView == scriptListContext.recordType?.id" color="brown-5" :label="t('Customise View')" @click="customiseView" /> <q-btn v-else color="brown-5" :label="t('Edit View')" @click="editView" /> </div> <div><actions-bar-component v-model:script-list-context="scriptListContext" :actives="scriptListContext.buttons" :data="null"></actions-bar-component></div> </div> <q-card flat class="q-pl-xs q-pb-xs q-br-sm q-pt-sm"> <q-card-actions class="bg-grey-3" align="left" vertical> <q-btn color="grey" flat dense size="xs" :icon="expanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down'" @click="expanded = !expanded"></q-btn> </q-card-actions> <q-slide-transition> <div v-show="expanded"> <div class="q-gutter-xs q-pa-sm"> <q-btn color="primary" @click="handleSearch" :label="t('Search')" /> <q-btn color="primary" @click="resetSearch" :label="t('Reset')" /> </div> <q-card-section v-show="search.searchAvailableFilters.length > 0" class="q-gutter-x-md items-center example-break-row"> <div class="row items-start example-container q-gutter-xs"> <template v-for="availableFilter in search.searchAvailableFilters" :key="availableFilter.id"> <template v-if="availableFilter.field.fieldViewType == 0"> <q-checkbox v-model="queryParams[availableFilter.fieldCustomId]" :label="availableFilter.field.name" left-label></q-checkbox> </template> <template v-else-if="availableFilter.field.fieldViewType == 7"> <q-input v-model="queryParamsTemp[availableFilter.fieldCustomId]" :label="availableFilter.field.name" @update:model-value=" (val) => { updateFilter(availableFilter.field, val); } " dense ></q-input> </template> <template v-else-if="availableFilter.field.fieldViewType == 2"> <q-input filled v-model="queryParamsTemp[availableFilter.fieldCustomId + '_from']" :label="availableFilter.field.name" dense @update:model-value=" (val) => { updateFilterDate(availableFilter, 'from', val); } " > <template v-slot:append> <q-icon name="event" class="cursor-pointer"> <q-popup-proxy cover transition-show="scale" transition-hide="scale"> <q-date v-model="queryParamsTemp[availableFilter.fieldCustomId + '_from']" mask="YYYY-MM-DD" @update:model-value=" (val, reason, details) => { updateFilterDate(availableFilter, 'from', val, reason, details); } " > <div class="row items-center justify-end"> <q-btn v-close-popup label="Close" color="primary" flat></q-btn> </div> </q-date> </q-popup-proxy> </q-icon> </template> </q-input> <span>至</span> <q-input filled v-model="queryParamsTemp[availableFilter.fieldCustomId + '_to']" :label="availableFilter.field.name" dense @update:model-value=" (val) => { updateFilterDate(availableFilter, 'to', val); } " > <template v-slot:append> <q-icon name="event" class="cursor-pointer"> <q-popup-proxy cover transition-show="scale" transition-hide="scale"> <q-date v-model="queryParamsTemp[availableFilter.fieldCustomId + '_to']" mask="YYYY-MM-DD" @update:model-value=" (val, reason, details) => { updateFilterDate(availableFilter, 'to', val, reason, details); } " > <div class="row items-center justify-end"> <q-btn v-close-popup label="Close" color="primary" flat></q-btn> </div> </q-date> </q-popup-proxy> </q-icon> </template> </q-input> </template> <template v-else-if="availableFilter.field.fieldViewType == 13"> <q-select v-model="queryParams[availableFilter.fieldCustomId]" :options="fieldOptions[availableFilter.fieldCustomId]" :label="availableFilter.field.name" use-input :option-value="availableFilter.field.fieldListOrRecordTypeIsList ? 'value' : 'id'" option-label="name" emit-value map-options @filter=" (val, update, abort) => { filterFn(availableFilter.field, val, update, abort); } " @filter-abort="abortFilterFn" @update:model-value="updateModelValue" :loading="optionLoading" dense clearable ></q-select> </template> </template> </div> </q-card-section> </div> </q-slide-transition> <q-card-section class="q-pl-xs q-pr-md q-pb-xs"> <q-table class="my-sticky-header-last-column-table" row-key="id" separator="cell" :rows="scriptListContext.items" :columns="columns" dense v-model:pagination="scriptListContext.pagination" :rows-per-page-options="pageOptions" :loading="loading" @request="onRequest" > <template v-slot:top="props"> <q-checkbox v-model="showInactives" :label="t('ShowInactives')"></q-checkbox> <q-space></q-space> <q-btn color="primary" icon-right="archive" :label="t('ExportToExcel')" no-caps @click="exportTable"></q-btn> <q-btn flat round dense :icon="props.inFullscreen ? 'fullscreen_exit' : 'fullscreen'" @click="props.toggleFullscreen" class="q-ml-md"></q-btn> </template> <template v-slot:body="props"> <q-tr :props="props"> <q-td v-for="col in columns" :key="col.name" :props="props"> <div> {{ props.row.value }} <div v-if="col.name == 'index'">{{ props.rowIndex + 1 }}</div> <template v-else-if="col.name == 'actions'"> <actions-bar-component v-model:script-list-context="scriptListContext" :actives="scriptListContext.buttonsRow" :data="props.row"></actions-bar-component> </template> <q-checkbox v-else-if="col.fieldModel?.fieldViewType == fieldViewTypeEnum.CheckBox" v-model="props.row[col.fieldModel.customId]" dense disable></q-checkbox> <template v-else-if="col.fieldModel?.fieldViewType == fieldViewTypeEnum.ListOrRecord"> {{ props.row[col.name] }} </template> <template v-else> {{ props.row[col.name] }} </template> </div> </q-td> </q-tr> </template> </q-table> </q-card-section> </q-card> </q-page> </template> <script setup lang="ts"> import { fetchListResult } from "src/api/customization/search"; import ActionsBarComponent from "src/components/ViewContent/ActionsBarComponent.vue"; import useTableList from "src/composables/useTableList"; import { IActive } from "src/interfaces/IActive"; import { IField } from "src/interfaces/IField"; import { Iparams } from "src/interfaces/Iparams"; import { Icolumn } from "src/interfaces/Icolumn"; import { IScriptListContext } from "src/interfaces/IScriptListContext"; import { formateList } from "src/modules/common-functions/datetimeOpration"; import { exportExcel } from "src/modules/common-functions/excelOpration"; import { onMounted, ref, watch } from "vue"; import { useRoute, useRouter } from "vue-router"; import { useI18n } from "vue-i18n"; import { toRecordTypePage } from "src/utils/routeRedirection"; import { fieldViewTypeEnum } from "src/enums/fieldViewTypeEnum"; import { operatorType } from "src/enums/operatorType"; import { getAction } from "src/api/manage"; import { addLoadingTotal, getLoadingTotal, loadingOne, setQuasar } from "src/modules/common-functions/loadingStatus"; import { listPage } from "src/modules/listPageCS"; const { t } = useI18n(); const route = useRoute(); const router = useRouter(); const showInactives = ref(true); const breadcrumbs: string[] = String(route.name || "").split(","); const optionLoading = ref(false); const expanded = ref(true); const fieldOptions: Record<string, any> = ref({}); const queryParamsTemp: Record<string, any> = ref({}); //初始化查询参数 const queryParas = ref<Iparams>({ RecordTypeId: "", IsInActive: showInactives.value, SkipCount: 0, MaxResultCount: 1000, Filter: "", }); //行按钮 const defaultRowActives: Array<IActive> = [ { id: "btn-view", name: "view", label: "查看", displayAS: 0, function: "", showInView: false, showInEdit: false, location: "row", isStandard: true, }, { id: "btn-edit", name: "edit", label: "编辑", displayAS: 0, function: "", showInView: false, showInEdit: false, location: "row", isStandard: true, }, { id: "btn-delete", name: "delete", label: "删除", displayAS: 0, function: "", showInView: false, showInEdit: false, location: "row", isStandard: true, }, ]; //主表按钮 const defaultActives: Array<IActive> = [ { id: "btn-new", name: "new", label: "新建", displayAS: 0, function: "handleCreate", showInView: false, showInEdit: false, location: "main", isStandard: true, }, ]; //上下文对象 const scriptListContext = ref<IScriptListContext>({ items: [], recordType: { id: route.query.id as string }, fieldOptions: {}, title: "", views: [], currentView: "", fields: [], colsApi: "", rowsApi: "/master-currency/paged", pagination: { sortBy: "", descending: false, page: 1, rowsPerPage: 100, rowsNumber: 0, }, buttons: defaultActives, buttonsRow: defaultRowActives, addButton: (button: IActive) => addButton(button), removeButton: (buttonId: string) => removeButton(buttonId), }); //列属性 const columns = ref<Icolumn[]>([ { name: "index", label: "序号", field: "index", align: "center" as const, headerStyle: "width: 60px", sortable: false, }, { name: "curName", required: true, label: "币别名称", field: "curName", align: "left" as const, sortable: true, }, { name: "isoCode", align: "center" as const, label: "货币ISO代码", field: "isoCode", sortable: true, }, { name: "formatSymbol", label: "显示符号", field: "formatSymbol", sortable: true, }, { name: "isInActive", label: "禁用", field: "isInActive", sortable: true, }, { name: "actions", label: "操作", field: "actions", align: "center" as const, headerStyle: "width: 100px", sortable: false, }, ]); const _listPage = new listPage(scriptListContext as Ref<IScriptListContext>); // 加载数据 onMounted(async () => { await _listPage.pageInit(); getTableData(); }); watch( () => scriptListContext.value.items, (newValue, oldValue) => { formateList(newValue, columns.value); }, { deep: true } ); const addButton = function (button: IActive) { if (button.location?.toLowerCase() == "row") { scriptListContext.value.buttonsRow.push(button); } else { scriptListContext.value.buttons.push(button); } }; const removeButton = function (buttonId: string) { const rb = scriptListContext.value.buttonsRow.find((item: IActive) => item.id == buttonId); if (rb) { scriptListContext.value.buttonsRow.splice(scriptListContext.value.buttonsRow.indexOf(rb), 1); } const btn = scriptListContext.value.buttons.find((item: IActive) => item.id == buttonId); if (btn) { scriptListContext.value.buttons.splice(scriptListContext.value.buttons.indexOf(btn), 1); } }; const { $q, queryParams, pageOptions, loading, onRequest, //服务器端分页 search, getTableData, //初始化加载 handleSearch, //search按钮 resetSearch, //reset按钮 } = useTableList(scriptListContext as Ref<IScriptListContext>, t); setQuasar($q); /** ========== export excel ============== */ const exportTable = async () => { const exportData = await getExportData(); exportExcel(exportData, columns.value); }; const getExportData = async () => { const params: Iparams = { Sorting: scriptListContext.value.pagination.sortBy, Descending: scriptListContext.value.pagination.descending, SkipCount: 0, MaxResultCount: 300, RecordTypeId: "", IsInActive: false, Filter: "", }; const filterParams = { Filter: JSON.stringify(queryParams.value), }; if (!scriptListContext.value.pagination.rowsNumber) return []; const totalPage = scriptListContext.value.pagination.rowsNumber / params.MaxResultCount; addLoadingTotal(totalPage); let exportData: Array<any> = []; for (let i = 0; i < totalPage; i++) { const allParams = Object.assign({}, params, filterParams); await getAction(scriptListContext.value.rowsApi, allParams).then((res) => { exportData = exportData.concat(res.items); params.SkipCount += params.MaxResultCount; loadingOne(); }); } addLoadingTotal(-1 * getLoadingTotal()); return exportData; }; /** ============= 过滤条件 ================ */ const getFieldOptions = async (field: IField, query: Iparams) => { optionLoading.value = true; await fetchListResult(field.fieldListOrRecordTypeId, query) .then((response) => { fieldOptions.value[field.customId] = response.items; }) .catch((res) => { console.log("error res:", res); }) .finally(() => { optionLoading.value = false; }); }; const filterFn = async (field: IField, val: string, update: any, abort: any) => { const queryFilter: any | object = {}; queryFilter["keywords"] = `opt_${operatorType.Like} ${val}`; // 'opt_6 ' + val queryParas.value.SkipCount = 0; queryParas.value.MaxResultCount = 100; queryParas.value.Filter = JSON.stringify(queryFilter); if (!val) { update(async () => { await getFieldOptions(field, queryParas.value); }); return; } update(async () => { await getFieldOptions(field, queryParas.value); }); }; const abortFilterFn = () => { // console.log('delayed filter aborted') }; const updateModelValue = (val: any) => { // console.log('updateModelValue', val) }; const updateFilterDate = (availableFilter: any, direction: string, val: any, reason = "", details: object = {}) => { var values = [queryParamsTemp.value[availableFilter.fieldCustomId + "_from"], queryParamsTemp.value[availableFilter.fieldCustomId + "_to"]]; queryParams.value[availableFilter.fieldCustomId] = "opt_11" + " " + JSON.stringify(values); }; const updateFilter = (field: IField, val: any) => { queryParams.value[field.customId] = "opt_6" + " " + val; }; const changedView = (val: string) => { toRecordTypePage(router, scriptListContext.value.recordType?.customId as string, "list", "", val); }; /** ============= 视图定义 ================ */ const editView = () => { toRecordTypePage(router, "search", "edit", scriptListContext.value.currentView, "3a0eb999-3fa6-d262-4b4e-f85331d1ca7d", undefined, "_blank"); }; const customiseView = () => { toRecordTypePage(router, "search", "create", scriptListContext.value.currentView, "3a0eb999-3fa6-d262-4b4e-f85331d1ca7d", { copy: "T" }, "_blank"); }; </script> <style lang="sass"> .example-break-row .flex-break flex: 1 0 100% !important height: 0 !important .my-sticky-header-last-column-table /* height or max-height is important */ height: 70vh table border-bottom: 1px solid rgba(0, 0, 0, 0.12); /* specifying max-width so the example can highlight the sticky column on any browser window */ // max-width: 600px td:last-child /* bg color is important for td; just specify one */ background-color: #eeeeee tr th position: sticky /* higher than z-index for td below */ z-index: 2 /* bg color is important; just specify one */ background: #eeeeee /* this will be the loading indicator */ thead tr:last-child th /* height of all previous header rows */ top: 48px /* highest z-index */ z-index: 3 thead tr:first-child th top: 0 z-index: 1 tr:last-child th:last-child /* highest z-index */ z-index: 3 td:last-child z-index: 1 td:last-child, th:last-child position: sticky right: 0 /* prevent scrolling behind sticky top row on focus */ tbody /* height of all previous header rows */ scroll-margin-top: 48px tbody tr:nth-child(even) background-color:#fafafa a &:link, &:visited color: blue text-decoration: none &:hover color: purple &:active color: blue .text-orignblue color: red !important .horizontal-items display: flex flex-wrap: nowrap justify-content: space-between align-items: center > q-item margin-right: 10px &:last-child margin-right: 0 // 如果需要为 q-item 添加更多样式,可以在这里继续嵌套 // 例如: // &:hover // background-color: lightgray </style> 一句一句给我解释
最新发布
07-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值