需求:基于vue3+ts实现,所有的筛选项是由外部传进来的,组件内部不出现任何业务代码
出现的问题:点击搜索按钮后无法实现搜索功能
//api/users.ts
import request from"@/utils/request"
type Common<T>={
code: string
data:T
mesg: string
time:string
}
export type Users={
categoryId:number
createdBy:string
createdTime:string
description:string
id:number
name:string
operatorId:number|null
selected: boolean
updatedBy:string
updatedTime:string
url:string
}
export type QueriedResult={
current: number
hitCount?: false
optimizeCountSql?:boolean
orders?:any[]
pages?:number
records:Users[]|[]
searchCount?: boolean
size:number
total: number
}
export type Condition=Partial<{
id:number
size:number
name:string
startCreateTime:string
url:string
categoryId:string
endCreateTime: string
current: number
}>
//分页查询
export const userPage= (condition:Condition) => {
return request<Common< QueriedResult>>({
method:'POST',
url:'http://39.97.218.60/boss/resource/getResourcePages',
data: condition,
})
//composables/users.ts
import { userPage } from "@/api/users";
import type { Condition,QueriedResult } from "@/api/users";
import { ElMessage } from "element-plus";
//查询条件
export const queryCondition=reactive<Condition>({
size:10,
name:'',
url:'',
categoryId:'',
current: 1
})
//查询结果
export const queriedResult=ref<QueriedResult>({
//api/users.ts 里QueryMethod里的冒号前的东西一致
current: 1,
records:[],
size:0,
total:0,
})
//查询方法
export const queryMethod=async (params:Condition={}) => {
Object.assign(queryCondition,params)//把两个对象的相同属性合并
const {data}=await userPage(queryCondition)
if(data.code==='000000'){
queriedResult.value=data.data
}else{
ElMessage.error("获取资源失败")
throw new Error("获取资源失败")
}
}
//index.vue
<script setup lang="ts">
import {queriedResult} from '@/composables/users'
import Search from '@/components/search/Search.vue';
import {queryCondition,queryMethod} from '@/composables/users'
import type { FormInstance } from 'element-plus';
import {allResourceCategory,getAllResourceCategory} from '@/composables/category'
import axios from 'axios';
queryMethod()
getAllResourceCategory()
const queryFm=ref<FormInstance>()
const searchDataFn = () => {
axios
.post('http://39.97.218.60/boss/resource/getResourcePages', productionlineForm.value)
.then((response) => {
queriedResult.value = response.data.records;
})
.catch((error) => {
console.error(error);
});
};
const searchData = ref([
{
label: '姓名',
type: 'input',
prop: 'name',
placeholder: '请输入姓名',
},
{
label: '电话',
type: 'input',
prop: 'url',
},
]);
let productionlineForm = ref({
name: '',
url:''
})
const submitEmitsFn = (val) => {
productionlineForm.value = val
searchDataFn();
}
</script>
<template>
<el-card class="box-card">
<template #header>
<Search :searchData="searchData" :searchInfo="productionlineForm" @submitEmits="submitEmitsFn" >
</Search>
</template>
<el-button size="large">添加</el-button>
<el-table :data="queriedResult.records" border style="width: 100%">
<el-table-column type="index" />
<el-table-column prop="name" label="姓名" align="center"/>
<el-table-column prop="url" label="电话" align="center"/>
<el-table-column prop="description" label="城市ID" align="center" />
<el-table-column prop="createdTime" label="年龄" align="center" />
<el-table-column prop="url" label="专业ID" align="center"/>
<el-table-column label="操作" >
<el-button type="primary">编辑</el-button>
<el-button type="danger">删除</el-button>
</el-table-column>
</el-table>
</el-card>
</template>
<style scoped>
.el-table{
margin-top: 17px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
</style>
//Search.vue
<template>
<el-form :model="searchInfo">
<el-row :gutter="10" style="margin: 10px 0;">
<el-col :span="item.span || 6" v-for="item, i in searchData" :key="i">
<el-form-item :label="item.label" :label-width="item.width || '80px'">
<el-input v-if="item.type === 'input'" v-model="searchInfo[item.prop]"
:placeholder="item.placeholder || '请输入'" clearable/>
<el-select v-if="item.type === 'select'" v-model="searchInfo[item.prop]"
:placeholder="item.placeholder || '请选择'" clearable>
<el-option v-for="item2: {label: string, value: any} in item.options" :key="i2" :label="item2.label" :value="item2.value" />
</el-select>
<el-date-picker v-if="item.type === 'date'" type="date" :value-format="item.format || 'YYYY-MM-DD'"
:placeholder="item.placeholder || '请选择日期'" v-model="searchInfo[item.prop]"
style="width: 100%;" clearable></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="btnInfo.span || 6">
<el-row justify="end">
<el-button :type="btnInfo.query || 'primary'" @click="onSubmit('query')">查询</el-button>
<el-button :type="btnInfo.reset || 'default'" @click="onSubmit('reset')">重置</el-button>
</el-row>
</el-col>
</el-row>
</el-form>
</template>
<script setup lang="ts">
interface SearchItem {
span?: number;
label: string;
type: string;
prop: string;
options?: { label: string, value: any }[];
width?: string;
placeholder?: string;
format?: string;
}
interface ButtonInfo {
span?: number;
query?: string;
reset?: string;
}
const props = defineProps({
//搜索信息
searchInfo: {
type: Object,
default: {},
required: true
},
//表单数组
searchData: {
type: Array,
default: [],
required: true
},
//按钮信息
btnInfo: {
type: Object,
default: {},
required: true
}
})
const emit = defineEmits(['submitEmits']);
const onSubmit = (data) => {
if (data == 'reset') {
emit('submitEmits', {});
} else if (data === 'query') {
emit('submitEmits', props.searchInfo);
}
}
</script>
<style lang="scss" scoped></style>
请问如何修改,并写出修改后的具体代码
引用 皆我百晓生 小程序回复内容作答:
根据问题描述,你想要实现一个基于Vue3 + TypeScript的搜索组件封装,并且所有的筛选项都由外部传递进来,组件内部不包含任何业务代码。你已经尝试过一些代码,但是在点击搜索按钮后无法实现搜索功能。
为了解决这个问题,首先需要将搜索按钮点击事件的处理函数submitEmitsFn
修改为调用queryMethod
来进行搜索。另外,由于你使用的是Vue3的Composition API,在Search.vue
中需要使用setup
语法进行组件的逻辑处理。
下面是调整后的代码:
// Search.vue
<template>
<el-form :model="searchInfo">
<el-row :gutter="10" style="margin: 10px 0;">
<el-col :span="item.span || 6" v-for="item, i in searchData" :key="i">
<el-form-item :label="item.label" :label-width="item.width || '80px'">
<el-input v-if="item.type === 'input'" v-model="searchInfo[item.prop]"
:placeholder="item.placeholder || '请输入'" clearable />
<el-select v-if="item.type === 'select'" v-model="searchInfo[item.prop]"
:placeholder="item.placeholder || '请选择'" clearable>
<el-option v-for="item2 in item.options" :key="item2.value" :label="item2.label" :value="item2.value" />
</el-select>
<el-date-picker v-if="item.type === 'date'" type="date" :value-format="item.format || 'yyyy-MM-dd'"
:placeholder="item.placeholder || '请选择日期'" v-model="searchInfo[item.prop]"
style="width: 100%;" clearable></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="btnInfo.span || 6">
<el-row justify="end">
<el-button :type="btnInfo.query || 'primary'" @click="onSubmit('query')">查询</el-button>
<el-button :type="btnInfo.reset || 'default'" @click="onSubmit('reset')">重置</el-button>
</el-row>
</el-col>
</el-row>
</el-form>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue';
interface SearchItem {
span?: number;
label: string;
type: string;
prop: string;
options?: { label: string; value: any }[];
width?: string;
placeholder?: string;
format?: string;
}
interface ButtonInfo {
span?: number;
query?: string;
reset?: string;
}
const props = defineProps({
// 搜索信息
searchInfo: {
type: Object,
default: () => ({}),
required: true
},
// 表单数组
searchData: {
type: Array as () => SearchItem[],
default: () => [],
required: true
},
// 按钮信息
btnInfo: {
type: Object as () => ButtonInfo,
default: () => ({}),
required: true
}
});
const emit = defineEmits(['submitEmits']);
const onSubmit = (data: string) => {
if (data === 'reset') {
emit('submitEmits', {});
} else if (data === 'query') {
emit('submitEmits', props.searchInfo);
}
};
</script>
<style lang="scss" scoped></style>
<!-- index.vue -->
<template>
<el-card class="box-card">
<template #header>
<Search :searchData="searchData" :searchInfo="productionlineForm" @submitEmits="submitEmitsFn"></Search>
</template>
<el-button size="large">添加</el-button>
<el-table :data="queriedResult.records" border style="width: 100%">
<el-table-column type="index" />
<el-table-column prop="name" label="姓名" align="center" />
<el-table-column prop="url" label="电话" align="center" />
<el-table-column prop="description" label="城市ID" align="center" />
<el-table-column prop="createdTime" label="年龄" align="center" />
<el-table-column prop="url" label="专业ID" align="center" />
<el-table-column label="操作">
<el-button type="primary">编辑</el-button>
<el-button type="danger">删除</el-button>
</el-table-column>
</el-table>
</el-card>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue';
import Search from '@/components/search/Search.vue';
import { queryMethod, queriedResult } from '@/composables/users';
import { ElMessage } from 'element-plus';
import axios from 'axios';
const searchData = ref([
{
label: '姓名',
type: 'input',
prop: 'name',
placeholder: '请输入姓名'
},
{
label: '电话',
type: 'input',
prop: 'url'
}
]);
const productionlineForm = ref({
name: '',
url: ''
});
const submitEmitsFn = (val: any) => {
productionlineForm.value = val;
queryMethod(productionlineForm.value); // 调用 queryMethod 函数进行搜索
};
queryMethod(); // 初始化时进行一次搜索
</script>
<style scoped>
.el-table {
margin-top: 17px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
</style>
修改后的代码将搜索按钮的点击事件处理函数submitEmitsFn
改为调用queryMethod
函数,并将productionlineForm.value
作为参数传递给queryMethod
函数进行搜索。另外,在页面初始化时也调用了queryMethod
函数进行一次搜索。
希望这个回答对你有帮助,如果还有任何问题,请随时继续追问。
在index.vue中,你同时使用了composables/users.ts中的queryMethod和一个新的searchDataFn函数来实现搜索功能。
你可以尝试修改index.vue的代码如下:
const searchDataFn = async () => {
await queryMethod(productionlineForm.value)
};
然后在Search.vue中的el-button上绑定搜索函数,如下:
<el-button :type="btnInfo.query || 'primary'" @click="onSubmit('query', searchDataFn)">查询</el-button>
这样就可以将搜索功能集成到queryMethod中,通过调用该方法来实现搜索。
同时,要注意修改Search.vue中onSubmit函数的参数为两个,以支持传入新的searchDataFn函数。
const onSubmit = (data, fn) => {
if (data == 'reset') {
emit('submitEmits', {});
} else if (data === 'query') {
fn();
}
}
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
根据你提供的代码,我看到一些需要修改的地方。首先,在Search.vue
组件中,你定义了一个onSubmit
方法,但是没有调用它。你需要在查询和重置按钮的点击事件中调用onSubmit
方法,将对应的参数传递进去。
修改后的Search.vue
组件代码如下:
<template>
<el-form :model="searchInfo">
<el-row :gutter="10" style="margin: 10px 0;">
<el-col :span="item.span || 6" v-for="item, i in searchData" :key="i">
<el-form-item :label="item.label" :label-width="item.width || '80px'">
<el-input v-if="item.type === 'input'" v-model="searchInfo[item.prop]"
:placeholder="item.placeholder || '请输入'" clearable/>
<el-select v-if="item.type === 'select'" v-model="searchInfo[item.prop]"
:placeholder="item.placeholder || '请选择'" clearable>
<el-option v-for="item2 in item.options" :key="item2.value" :label="item2.label" :value="item2.value" />
</el-select>
<el-date-picker v-if="item.type === 'date'" type="date" :value-format="item.format || 'YYYY-MM-DD'"
:placeholder="item.placeholder || '请选择日期'" v-model="searchInfo[item.prop]"
style="width: 100%;" clearable></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="btnInfo.span || 6">
<el-row justify="end">
<el-button :type="btnInfo.query || 'primary'" @click="onSubmit('query')">查询</el-button>
<el-button :type="btnInfo.reset || 'default'" @click="onSubmit('reset')">重置</el-button>
</el-row>
</el-col>
</el-row>
</el-form>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue';
interface SearchItem {
span?: number;
label: string;
type: string;
prop: string;
options?: { label: string, value: any }[];
width?: string;
placeholder?: string;
format?: string;
}
interface ButtonInfo {
span?: number;
query?: string;
reset?: string;
}
const props = defineProps({
// 搜索信息
searchInfo: {
type: Object,
default: () => ({}),
required: true
},
// 表单数组
searchData: {
type: Array,
default: () => [],
required: true
},
// 按钮信息
btnInfo: {
type: Object,
default: () => ({}),
required: true
}
});
const emit = defineEmits(['submitEmits']);
const onSubmit = (data) => {
if (data === 'reset') {
emit('submitEmits', {});
} else if (data === 'query') {
emit('submitEmits', props.searchInfo);
}
};
</script>
接下来,在index.vue
组件中,你使用了axios
库发送了一个独立的请求来获取搜索结果,而不是调用封装好的queryMethod
方法进行查询。你应该使用queryMethod
方法进行查询,并且在搜索按钮的点击事件中调用该方法。
修改后的index.vue
组件代码如下:
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import Search from '@/components/search/Search.vue';
import { queryCondition, queryMethod } from '@/composables/users';
import { ElMessage } from 'element-plus';
onMounted(queryMethod);
const searchData = ref([
{
label: '姓名',
type: 'input',
prop: 'name',
placeholder: '请输入姓名',
},
{
label: '电话',
type: 'input',
prop: 'url',
},
]);
const productionlineForm = ref({
name: '',
url: ''
});
const submitEmitsFn = (val) => {
productionlineForm.value = val;
queryMethod();
};
</script>
<template>
<el-card class="box-card">
<template #header>
<Search
:searchData="searchData"
:searchInfo="productionlineForm"
:btnInfo="{ query: 'primary', reset: 'default' }"
@submitEmits="submitEmitsFn"
/>
</template>
<div>查询结果展示</div>
</el-card>
</template>
通过以上修改,你应该能够使用queryMethod
方法进行查询,并且在点击查询按钮时触发查询操作。同时,重置按钮也应该能够正确地重置搜索条件。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
参考结合GPT4.0、文心一言,如有帮助,恭请采纳。
这里可能有几个潜在的问题:
1、productionlineForm.value在提交表单的时候是否已经被正确赋值?你可以在submitEmitsFn函数内部打印出productionlineForm.value来查看其值。
2、在searchDataFn函数中,你使用了productionlineForm.value作为请求的参数,但是你的searchData定义中并没有这个值。你应该检查一下你的表单数据productionlineForm.value是否包含了你需要的字段。
3、在axios请求返回后,你尝试将返回的数据设置为queriedResult.value,但是在你的代码中并没有定义queriedResult。你应该在你的代码中定义这个值。
4、在你的模板中,你使用了queriedResult.records作为表格的数据源,但是在你的代码中并没有定义queriedResult。你应该在你的代码中定义这个值。
5、你应该检查你的后端接口是否正常工作,返回的数据格式是否符合你的预期。
<template>
<el-form :model="searchInfo">
<el-row :gutter="10" style="margin: 10px 0;">
<el-col :span="item.span || 6" v-for="item, i in searchData" :key="i">
<el-form-item :label="item.label" :label-width="item.width || '80px'">
<el-input v-if="item.type === 'input'" v-model="searchInfo[item.prop]"
:placeholder="item.placeholder || '请输入'" clearable/>
<el-select v-if="item.type === 'select'" v-model="searchInfo[item.prop]"
:placeholder="item.placeholder || '请选择'" clearable>
<el-option v-for="item2 in item.options" :key="item2.value" :label="item2.label" :value="item2.value" />
</el-select>
<el-date-picker v-if="item.type === 'date'" type="date" :value-format="item.format || 'YYYY-MM-DD'"
:placeholder="item.placeholder || '请选择日期'" v-model="searchInfo[item.prop]"
style="width: 100%;" clearable></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="btnInfo.span || 6">
<el-row justify="end">
<el-button :type="btnInfo.query || 'primary'" @click="onSubmit('query')">查询</el-button>
<el-button :type="btnInfo.reset || 'default'" @click="onSubmit('reset')">重置</el-button>
</el-row>
</el-col>
</el-row>
</el-form>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue';
interface SearchItem {
span?: number;
label: string;
type: string;
prop: string;
options?: { label: string, value: any }[];
width?: string;
placeholder?: string;
format?: string;
}
interface ButtonInfo {
span?: number;
query?: string;
reset?: string;
}
const props = defineProps({
// 搜索信息
searchInfo: {
type: Object,
default: () => ({}),
required: true
},
// 表单数组
searchData: {
type: Array,
default: () => [],
required: true
},
// 按钮信息
btnInfo: {
type: Object,
default: () => ({}),
required: true
}
});
const emit = defineEmits(['submitEmits']);
const onSubmit = (data) => {
if (data === 'reset') {
emit('submitEmits', {});
} else if (data === 'query') {
emit('submitEmits', props.searchInfo);
}
};
</script>
【相关推荐】