-
el-pagination分页组件
// 子组件 <template> <el-pagination :current-page="currentPage" :page-sizes="pageSizes" :page-size="pageSize" :layout="layout" :total="total" v-bind="$attrs" v-on="$listeners" /> </template> <script> export default { name: 'MyPagination', props: { currentPage: { type: Number, default: 1 }, pageSizes: { type: Array, default: () => [10, 20, 30, 40, 50] }, pageSize: { type: Number, default: 10 }, layout: { type: String, default: 'total, sizes, prev, pager, next, jumper' }, total: { type: Number, required: true } }, methods: { handleSizeChange(newSize) { this.$emit('size-change', newSize) }, handleCurrentChange(newPage) { console.log('触发', newPage) this.$emit('current-change', newPage) } } } </script> // 父组件使用 <template> <div> <my-pagination :current-page="currentPage" :page-sizes="[10, 20, 30, 40]" :page-size="pageSize" :total="total" @current-change="handleCurrentChange" @size-change="handleSizeChange" /> </div> </template> <script> import MyPagination from '@/components/MyPagination/index.vue' import { getDataAPI } from '/api' export default { components: { MyPagination }, data() { return { currentPage: 1, pageSize: 10, total: 100, list: [] } }, methods: { getData() { getDataAPI({ limit: this.pageSize, page: this.page }).then(res => { this.list = res.data }) }, handleCurrentChange(newPage) { this.page =newPage this.getData() }, handleSizeChange(newSize) { this.pageSize =newSize this.getData() } } } </script>
-
el-drawer抽屉组件
// 子组件 <template> <el-drawer :visible="visible" :modal="false" :title="title" @close="handleClose"> <div class="drawer-content"> <slot /> </div> </el-drawer> </template> <script> export default { name: 'MyDrawer', props: { visible: { type: Boolean, required: true }, title: { type: String, default: '' } }, methods: { handleClose() { this.$emit('update:visible', false) } } } </script> <style scoped> .drawer-content { padding: 20px; } </style> //父组件 <template> <div> <el-button type="primary" @click="showDrawer = true">Open Drawer</el-button> <My-drawer :visible.sync="showDrawer" :title="title"> <p>Some content goes here...</p> </My-drawer> </div> </template> <script> import MyDrawer from '@/components/MyDrawer/index.vue' export default { components: { MyDrawer }, data() { return { // 弹框数据 showDrawer: true, title: 'Drawer Title' } }, methods: { } } </script>
-
el-date-picker 选择时间组件
// 子组件 <template> <el-date-picker v-model="internalValue" :type="type" :placeholder="placeholder" :clearable="clearable" /> </template> <script> export default { name: 'MyDatePicker', props: { value: { type: [String, Date], required: true }, type: { type: String, default: 'date' }, placeholder: { type: String, default: '' }, clearable: { type: Boolean, default: true } }, computed: { internalValue: { get() { return this.value }, set(val) { val ? this.$emit('input', val) : this.$emit('input', '') } } } } </script> //父组件 <template> <div> <my-date-picker v-model="date" label="选择日期" placeholder="请选择日期" /> <p>选择的日期:{{ date }}</p> </div> </template> <script> import MyDatePicker from '@/components/MyDatePicker/index.vue' export default { components: { MyDatePicker }, data() { return { date: '' } } } </script>
-
el-select组件封装
// 子组件 <template> <el-select v-model="value" :options="options" :placeholder="placeholder"> <el-option v-for="option in options" :key="option.value" :label="option.label" :value="option.value" /> </el-select> </template> <script> export default { name: 'MySelect', props: { value: { type: [String, Number, Array], default: '' }, options: { type: Array, default: () => [] }, placeholder: { type: String, default: '' } } } </script> // 父组件 <template> <div> <my-select v-model="selectedValue" :options="options" :placeholder="'请选择12'" /> </div> </template> <script> import MySelect from '@/components/MySelect/index.vue' export default { name: 'MyComponent', components: { MySelect }, data() { return { selectedValue: '', options: [ { label: '选项1', value: 'option1' }, { label: '选项2', value: 'option2' }, { label: '选项3', value: 'option3' } ] } } } </script>
-
el-upload文件上传组件封装
// 子组件 <template> <el-upload :drag="drag" :action="action" multiple :headers="headers" :name="type" :data="data" :on-success="onSuccess" :on-remove="onRemove" :before-upload="beforeUpload" > <template v-if="drag"> <i class="el-icon-upload" /> <div class="el-upload__text"> 将文件拖到此处,或<em>点击上传</em> </div> </template> <template v-else> <el-button size="small" type="primary"> <i class="el-icon-upload" /> 点击上传 </el-button> </template> <template #tip> <div class="el-upload__tip"> 只能上传jpg/png文件,且不超过500kb </div> </template> </el-upload> </template> <script> export default { name: 'MyUpload', props: { action: { type: String, required: true }, type: { type: String, default: 'img' }, headers: { type: Object, default: () => ({}) }, data: { type: Object, default: () => ({}) }, drag: { type: Boolean, default: false }, multiple: { type: Boolean, default: false }, showFileList: { type: Boolean, default: true }, fileList: { type: Array, default: () => [] }, onRemove: { type: Function, default: () => { } }, onSuccess: { type: Function, default: () => { } }, beforeUpload: { type: Function, default: () => { } } } } </script> // 父组件 <template> <div> <MyUpload :drag="true" :action="uploadUrl" :file-list="fileList" :on-success="handleSuccess" :before-upload="handleBeforeUpload" :on-remove="handleRemove" :headers="{ token: '2c4b4ec6be48954702fc79c1e513d6fde78d8798' }" :data="data" :type="'img'" /> </div> </template> <script> import MyUpload from '@/components/MyUpload/index.vue' export default { components: { MyUpload }, data() { return { uploadUrl: 'http://ceshi13.dishait.cn/admin/image/upload', fileList: [], data: { // 这里添加这个是因为此接口需要添加这个属性 image_class_id: 168 } } }, methods: { handleBeforeUpload(file) { // 验证文件类型和大小 const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png' const isLt2M = file.size / 1024 / 1024 < 2 if (!isJpgOrPng) { this.$message.error('上传头像图片只能是 JPG/PNG 格式!') } if (!isLt2M) { this.$message.error('上传头像图片大小不能超过 2MB!') } return isJpgOrPng && isLt2M }, handleSuccess(response, file, fileList) { // 上传成功处理 this.fileList = fileList this.$message.success('上传成功') }, handleRemove(file, fileList) { // 删除文件处理 this.fileList = fileList } } } </script>
-
MySearch 搜索组件
// 子组件1 <template> <el-form :model="model" label-width="80px" class="mb-3" size="small"> <el-row :gutter="20"> <slot /> <template v-if="showSearch"> <slot name="show" /> </template> <el-col :span="8" :offset="showSearch ? 0 : 8"> <div class="flex items-center justify-end"> <el-button type="primary" @click="$emit('search')">搜索</el-button> <el-button @click="$emit('reset')">重置</el-button> <el-button v-if="hasShowSearch" type="primary" text @click="showSearch = !showSearch"> <span class="mr-1">{{ showSearch ? '收起' : '展开' }}</span> <el-icon> <ArrowUpBold v-if="showSearch" /> <ArrowDownBold v-else /> </el-icon> </el-button> </div> </el-col> </el-row> </el-form> </template> <script> export default { props: { model: { type: Object, default: () => {} } }, data() { return { showSearch: false, hasShowSearch: !!this.$slots.name } }, created() { }, methods: { } } </script> <style scoped lang="scss"> </style> // 子组件2 <template> <el-col :span="8" :offset="0"> <el-form-item :label="label"> <slot /> </el-form-item> </el-col> </template> <script> export default { props: { label: { type: String, default: '' } } } </script> <style scoped lang="scss"> </style> // 父组件 <template> <!-- 搜索 --> <My-search show-search :model="searchForm" @search="getData" @reset="resetSearchForm"> <MySearchItem label="订单编号"> <el-input v-model="searchForm.no" placeholder="订单编号" clearable @keydown.enter="getData" /> </MySearchItem> <template #show> <MySearchItem label="收货人"> <el-input v-model="searchForm.name" placeholder="收货人" clearable /> </MySearchItem> <MySearchItem label="手机号"> <el-input v-model="searchForm.phone" placeholder="手机号" clearable /> </MySearchItem> <MySearchItem label="开始时间"> <el-date-picker v-model="searchForm.starttime" type="date" placeholder="开始日期" style="width: 90%;" value-format="YYYY-MM-DD" /> </MySearchItem> <MySearchItem label="结束时间"> <el-date-picker v-model="searchForm.endtime" type="date" placeholder="结束日期" style="width: 90%;" value-format="YYYY-MM-DD" /> </MySearchItem> </template> </My-search> </template> <script> import MySearch from '@/components/MySearch/index.vue' import MySearchItem from '@/components/MySearchItem/index.vue' export default { components: { MySearch, MySearchItem }, data() { return { searchForm: { tab: 'all', no: '', starttime: '', endtime: '', name: '', phone: '' }, initForm: { } } }, created() { this.initForm = this.searchForm }, methods: { getData() { console.log(this.searchForm, 'this.searchForm') }, resetSearchForm() { for (const key in this.searchForm) { this.searchForm[key] = this.initForm[key] } this.getData() } } } </script> <style scoped lang="scss"> </style>
- 还有一个不属于el组件的常用组件(数字动画组件)
npm install -d gsap
// 子组件
<template>
<div>
<!-- 数字动画组件 -->
{{ d.num.toFixed(0) }}
</div>
</template>
<script>
import gsap from 'gsap'
export default {
props: {
value: {
type: Number,
default: 0
}
},
data() {
return {
d: {
num: 0
}
}
},
watch: {
value(newValue, oldValue) {
console.log(`message changed from ${oldValue} to ${newValue}`)
this.AnimateToValue()
},
immediate: true
},
created() {
this.AnimateToValue()
},
methods: {
AnimateToValue() {
gsap.to(this.d, {
duration: 0.5,
num: this.value
})
}
}
}
</script>
// 父组件
<template>
<div>
<MyGsap :value="10000" />
</div>
</template>
<script>
import MyGsap from '@/components/MyGsap/index.vue'
export default {
components: {
MyGsap
}
}
</script>