当前位置: 首页 > article >正文

《Nuxt.js 实战:从放弃到入门》二、Element Plus 集成

20250214160814611152.png

在项目开发过程中,引入公共头部和脚部组件,有助于实现页面布局的统一,提升用户体验。以下是具体的实施步骤和相关代码。

首先,需要创建一个目录,用于存放相关组件文件,为项目文件结构提供清晰的组织方式。

tmpa65da0a3.png

创建 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">&copy; 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 组件框架。

tmpav22susn.png

接入后需对 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">&copy; 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-upload
          class="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-image
          v-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-slider
                  v-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-button
            type="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.raw
  if (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)) return

  isLoading.value = true
  errorMessage.value = ''

  const reader = new FileReader()
  reader.onload = (e) => {
    const img = new Image()
    img.onload = () => {
      originalWidth.value = img.width
      originalHeight.value = img.height
      width.value = img.width
      height.value = img.height
      scale.value = 100
      isLoading.value = false
    }
    img.onerror = () => {
      errorMessage.value = '图片加载失败,请重试'
      isLoading.value = false
    }
    img.src = e.target.result
    imageUrl.value = e.target.result
    originalImageUrl.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.value
  canvas.height = height.value

  const 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.value
  canvas.height = height.value

  const 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

tmpqoxzy4so.png

托管地址:https://github.com/outeasy/outeasy/releases/tag/v0.2


http://www.kler.cn/a/550761.html

相关文章:

  • Oracle 12c中在同一组列上创建多个索引
  • 利用亚马逊AI代码助手生成、构建和编译一个游戏应用(下)
  • 基于springboot社会志愿者服务管理平台(源码+lw+部署文档+讲解),源码可白嫖!
  • 抖去推与超级编导矩阵系统技术深度对比,矩阵系统支持OEM
  • Ubuntu20.04安装IsaacSim4.5与IsaacLab2.0
  • 机器学习-02-机器学习算法思想以及在各行各业的应用
  • 成熟开发者需具备的能力
  • 【react8】如何在网页中直接引入react进行demo开发
  • OS-Genesis:基于逆向任务合成的 GUI 代理轨迹自动化生成
  • 若依Flowable工作流版本监听器使用方法
  • JSX和JS有什么区别
  • 从入门到精通:Postman 实用指南
  • SpringBoot3.x整合WebSocket
  • ES常用查询
  • 基于Dify、Ollama与DeepSeek的私有化AI知识库构建:工具作用、场景与优势分析
  • pythonrsa加密与sha256加密
  • 【亚马逊开发者账号02】终审问题SA+review_Pre-review+Doc.xlsx
  • 串的基本操作--数据结构
  • Copilot基于企业PPT模板生成演示文稿
  • AI前端开发赋能自主创业:ScriptEcho助你乘风破浪