在项目开发过程中,引入公共头部和脚部组件,有助于实现页面布局的统一,提升用户体验。以下是具体的实施步骤和相关代码。
首先,需要创建一个目录,用于存放相关组件文件,为项目文件结构提供清晰的组织方式。
创建 Header.vue 组件
Header.vue 组件定义了页面的公共头部部分,包含导航链接等内容。其代码如下:
<template><header class="bg-white shadow-sm"><nav class="container mx-auto px-4 py-3"><div class="flex items-center justify-between"><div class="flex items-center space-x-4"><NuxtLink to="/" class="text-xl font-bold text-gray-800">OutEasy</NuxtLink><div class="hidden md:flex space-x-4"><NuxtLink to="/resize" class="text-gray-600 hover:text-gray-900">图片调整</NuxtLink></div></div></div></nav></header>
</template>
创建 Footer.vue 组件
Footer.vue 组件定义了页面的公共脚部部分,包含版权信息和相关链接。其代码如下:
<template><footer class="bg-gray-50 border-t"><div class="container mx-auto px-4 py-6"><div class="flex flex-col items-center justify-center space-y-2"><p class="text-gray-600 text-sm">© 2024 OutEasy. All rights reserved.</p><div class="flex space-x-4"><a href="#" class="text-gray-500 hover:text-gray-700 text-sm">关于我们</a><a href="#" class="text-gray-500 hover:text-gray-700 text-sm">使用条款</a><a href="#" class="text-gray-500 hover:text-gray-700 text-sm">隐私政策</a></div></div></div></footer>
</template>
在 app.vue 中引入组件
在 app.vue 中,将 Header.vue 和 Footer.vue 组件引入,以构建完整的页面结构。代码如下:
<template><div class="min-h-screen flex flex-col"><Header /><main class="flex-grow"><NuxtPage /></main><Footer /></div>
</template>
在 app.vue 中引入组件
在 app.vue 中,将 Header.vue 和 Footer.vue 组件引入,以构建完整的页面结构。代码如下:
<script setup>
const router = useRouter()onMounted(() => {router.push('/resize')
})
</script><template><div></div>
</template>
接入 Element - Plus UI 组件框架
为优化页面样式和交互,接入 Element - Plus UI 组件框架。
接入后需对 nuxt.config.ts 和 package.json 进行相应配置修改。
nuxt.config.ts,修改后的内容
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({compatibilityDate: '2024-11-01',devtools: { enabled: true },modules: ['element-plus/nuxt'],css: ['element-plus/dist/index.css']
})
package.json修改后的内容
{"name": "nuxt-app","private": true,"type": "module","scripts": {"build": "nuxt build","dev": "nuxt dev","generate": "nuxt generate","preview": "nuxt preview","postinstall": "nuxt prepare"},"dependencies": {"nuxt": "^3.15.4","vue": "latest","vue-router": "latest","element-plus": "^2.6.1","@element-plus/icons-vue": "^2.3.1"}
}
修改相关组件代码以适配新框架
接入 Element - Plus UI 组件框架后,Header.vue、Footer.vue、resize.vue 的代码需相应修改,以使用新框架的组件和样式。
Header.vue 新代码
<template><header><div class="container mx-auto px-4"><el-row :gutter="20" ><!-- el-row 用于创建行布局,justify="space-between" 使内容两端对齐,align="middle" 使内容垂直居中 --><el-col :span="2"><!-- el-col 用于创建列布局,span="6" 可以调整宽度,这里是占据六分之一的宽度 --><el-menu mode="horizontal" router :ellipsis="false"><el-menu-item index="/"><span>OutEasy</span></el-menu-item></el-menu></el-col><el-col :span="2"><!-- 这里给中间部分设置了 span="12",让它占据剩余空间 --><el-menu mode="horizontal" router :ellipsis="false"><el-menu-item index="/resize"><span>图片调整</span></el-menu-item></el-menu></el-col><el-col :offset="20"></el-col></el-row></div></header>
</template><script setup>
</script>
Footer.vue代码如下:
<template><footer class="bg-gray-50 border-t"><el-row justify="center" align="middle" class="w-full min-h-[80px]"><!-- el-row 用于创建行布局,justify="center" 使内容水平居中,align="middle" 使内容垂直居中 --><el-col :span="24"><!-- el-col 用于创建列布局,span="24" 表示占据整行 --><div class="text-center"><p class="text-gray-600 text-sm">© 2024 OutEasy</p></div></el-col></el-row></footer>
</template><style scoped>
footer {border-top: 1px solid #ffffff; /* 对应 border-t 的样式 */
}.text-center {text-align: center;
}.text-gray-600 {color: #4b5563; /* 对应 text-gray-600 的颜色 */
}.text-sm {font-size: 0.875rem; /* 对应 text-sm 的样式 */
}
</style>
resize.vue代码如下:
<template><div class="container mx-auto p-4 max-w-2xl"><el-card><template #header><div class="text-center"><span class="text-xl font-medium">图片尺寸调整</span></div></template><!-- 图片上传区域 --><el-uploadclass="upload-area mb-6"drag:auto-upload="false":show-file-list="false"accept="image/*":on-change="handleFileSelect"><template #trigger><div v-if="!imageUrl && !isLoading && !errorMessage" class="text-center"><el-icon class="el-icon--upload mx-auto block"><upload-filled /></el-icon><div class="el-upload__text">拖拽图片到此处或 <em>点击上传</em></div><div class="text-sm text-gray-400 mt-2">支持 JPG、PNG 格式</div></div></template></el-upload><div v-if="isLoading" class="text-center py-8"><el-icon class="is-loading mb-2" :size="24"><loading /></el-icon><div class="text-gray-600">正在处理图片...</div></div><div v-else-if="errorMessage" class="text-center py-8"><el-alert:title="errorMessage"type="error":closable="false"class="mb-4"/><el-button type="primary" @click="errorMessage = ''">重试</el-button></div><el-imagev-else-if="imageUrl":src="imageUrl"fit="contain"class="mx-auto block max-h-[300px] mt-4"/><!-- 尺寸调整控制面板 --><el-form v-if="imageUrl" class="mt-6 w-full max-w-3xl mx-auto"><el-form-item label="缩放比例" class="mb-6"><el-row class="items-center justify-center"><el-col :span="16"><el-sliderv-model="scale":min="1":max="100":format-tooltip="value => `${value}%`"@input="handleScaleChange"/></el-col><el-col :span="8" class="text-right"><span class="text-gray-600">{{ scale }}%</span></el-col></el-row></el-form-item><el-buttontype="primary"@click="downloadImage"class="w-full mx-auto block">下载调整后的图片</el-button></el-form></el-card></div>
</template><script setup>
import { ref, onMounted } from 'vue'
import { UploadFilled, Loading } from '@element-plus/icons-vue'const fileInput = ref(null)
const imageUrl = ref('')
const originalImageUrl = ref('')
const scale = ref(100)
const width = ref(0)
const height = ref(0)
const originalWidth = ref(0)
const originalHeight = ref(0)
const isLoading = ref(false)
const errorMessage = ref('')// 文件大小限制(10MB)
const MAX_FILE_SIZE = 10 * 1024 * 1024
// 支持的图片格式
const SUPPORTED_FORMATS = ['image/jpeg', 'image/png', 'image/webp']// 处理文件选择
const handleFileSelect = (uploadFile) => {const file = uploadFile.rawif (file) {processImage(file)}
}// 处理拖拽上传
const handleDrop = (event) => {const file = event.dataTransfer.files[0]if (file && file.type.startsWith('image/')) {processImage(file)}
}// 处理图片
const validateFile = (file) => {if (!SUPPORTED_FORMATS.includes(file.type)) {errorMessage.value = '请上传 JPG、PNG 或 WebP 格式的图片'return false}if (file.size > MAX_FILE_SIZE) {errorMessage.value = '图片大小不能超过 10MB'return false}errorMessage.value = ''return true
}const processImage = (file) => {if (!validateFile(file)) returnisLoading.value = trueerrorMessage.value = ''const reader = new FileReader()reader.onload = (e) => {const img = new Image()img.onload = () => {originalWidth.value = img.widthoriginalHeight.value = img.heightwidth.value = img.widthheight.value = img.heightscale.value = 100isLoading.value = false}img.onerror = () => {errorMessage.value = '图片加载失败,请重试'isLoading.value = false}img.src = e.target.resultimageUrl.value = e.target.resultoriginalImageUrl.value = e.target.result}reader.onerror = () => {errorMessage.value = '图片读取失败,请重试'isLoading.value = false}reader.readAsDataURL(file)
}// 处理缩放比例变化
const handleScaleChange = () => {width.value = Math.round(originalWidth.value * scale.value / 100)height.value = Math.round(originalHeight.value * scale.value / 100)// 更新预览图片const canvas = document.createElement('canvas')canvas.width = width.valuecanvas.height = height.valueconst ctx = canvas.getContext('2d')const img = new Image()img.onload = () => {ctx.drawImage(img, 0, 0, width.value, height.value)imageUrl.value = canvas.toDataURL('image/png')}img.src = originalImageUrl.value
}// 下载调整后的图片
const downloadImage = () => {const canvas = document.createElement('canvas')canvas.width = width.valuecanvas.height = height.valueconst ctx = canvas.getContext('2d')const img = new Image()img.onload = () => {ctx.drawImage(img, 0, 0, width.value, height.value)const link = document.createElement('a')link.download = 'resized-image.png'link.href = canvas.toDataURL('image/png')link.click()}img.src = imageUrl.value
}
</script>
安装插件与运行服务
在运行服务前,需安装 Element - Plus 相关插件,使用以下命令进行安装:
npm install @element-plus/nuxt
安装完成后,使用以下命令运行服务:
npm run dev
托管地址:https://github.com/outeasy/outeasy/releases/tag/v0.2