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

【3】使用TRAE AI在已有框架中新增页面并实现切换的痛苦经历

在这里插入图片描述

对于新手来说,要在已有框架中插入新功能页面,这番操作是一个非常让人痛苦的,围绕着TRAE是说了好多好话和孬话,就是无法实现想要的结果。非常非常的无奈,只能换一种方式实现,以下先通过AI生成,科普一下vue语言在开发中showComponent和router-view的使用方法、案例、优缺点、对比效果。

在这里插入图片描述

一、 Vue 中动态组件(<component :is>)与路由视图(<router-view>)详解

1.1 动态组件(<component :is="showComponent">

作用:在同一个挂载点动态切换不同的 Vue 组件(无需路由变化)。

使用方法:
<template><div><button @click="currentComponent = 'CompA'">显示A</button><button @click="currentComponent = 'CompB'">显示B</button><!-- 动态组件 --><component :is="currentComponent"></component></div>
</template><script>
import CompA from './CompA.vue';
import CompB from './CompB.vue';export default {components: { CompA, CompB },data() {return {currentComponent: 'CompA' // 初始组件};}
};
</script>
典型场景:
  • 标签页切换(如 Dashboard 中的不同功能卡片)
  • 条件渲染不同子组件(如根据用户类型显示不同表单)
  • 动态加载非路由相关的组件
优点:
  1. 轻量级:无需路由配置,适合简单组件切换
  2. 状态保持:结合 <keep-alive> 可缓存组件状态
    <keep-alive><component :is="currentComponent"></component>
    </keep-alive>
    
  3. 灵活性:可通过 JavaScript 逻辑直接控制切换
缺点:
  1. 无 URL 映射:页面刷新后状态丢失
  2. 无路由钩子:缺少导航守卫等路由控制
  3. 需手动管理状态:切换逻辑需自行实现

1.2 路由视图(<router-view>

作用:配合 Vue Router 根据 URL 路径渲染匹配的组件。

使用方法:
// router.js
import { createRouter, createWebHistory } from 'vue-router';
import CompA from './views/CompA.vue';
import CompB from './views/CompB.vue';const routes = [{ path: '/a', component: CompA },{ path: '/b', component: CompB }
];const router = createRouter({history: createWebHistory(),routes
});
<!-- App.vue -->
<template><router-link to="/a">跳转A</router-link><router-link to="/b">跳转B</router-link><!-- 路由出口 --><router-view></router-view>
</template>
典型场景:
  • 多页面应用(如 /home, /about, /user/123)
  • 需要 URL 共享的页面(如分享链接)
  • 需要路由守卫的鉴权流程
优点:
  1. URL 驱动:页面状态可通过 URL 保存/分享
  2. 完整路由功能
    • 嵌套路由 (children)
    • 路由参数 (/user/:id)
    • 导航守卫 (beforeEach)
    • 懒加载 (() => import('./CompA.vue'))
  3. SEO 友好:支持 SSR 和 history 模式
缺点:
  1. 配置复杂:需单独管理路由配置文件
  2. 相对重量级:需要引入 Vue Router 库

1.3 核心对比

特性<component :is><router-view>
核心依赖Vue 核心功能需安装 Vue Router
URL 影响不改变 URL同步更新 URL
状态保持需手动 + <keep-alive>自带路由参数保持
组件通信父组件通过 props 传递通过路由参数/query 传递
生命周期控制常规组件生命周期支持路由守卫 (beforeRouteEnter 等)
适用场景简单组件切换 (如 Tab)完整页面路由 (如 SPA)
代码分割需自行实现动态 import原生支持路由懒加载
示例路径/user/profile

1.4 混合使用案例

结合两者实现带缓存的路由视图:

<template><!-- 缓存指定路由组件 --><keep-alive :include="['UserProfile']"><router-view v-slot="{ Component }"><component :is="Component" /></router-view></keep-alive>
</template>

1.5 选择建议

  • <component :is> 当:

    • 需要局部切换组件(如选项卡)
    • 无需 URL 反映当前状态
    • 简单交互无需路由管理
  • <router-view> 当:

    • 构建多页面应用(MPA/SPA)
    • 需要 URL 导航/深层链接
    • 需要路由守卫、懒加载等高级功能

特殊技巧:在路由组件内部可使用 <component :is> 实现嵌套动态组件,形成"路由+动态组件"的混合架构。

二、实现过程

2.1 DeepSeek的页面实现

提问

将这页html语言的代码转成vue代码,样式保持不变,章节数据 部分取自数据库表,设计一个后端接口实现此功能

回答

Vue实现的《道德经》在线阅读系统

下面我将把提供的HTML代码转换为一个完整的Vue应用,并设计后端接口方案。

设计思路
  • 将静态HTML转换为Vue单文件组件结构
  • 使用Vue Router管理页面路由
  • 使用Vuex管理章节数据
  • 设计RESTful API接口
  • 保持原设计的优雅中国风样式
Vue组件实现
App.vue (主组件)
<template><div class="min-h-screen bg-f8f4e9 font-noto"><Navbar @toggle-mobile-menu="toggleMobileMenu" /><MobileMenu :is-visible="mobileMenuVisible" @close="mobileMenuVisible = false" /><router-view></router-view><Footer /></div>
</template><script>
import Navbar from './components/Navbar.vue'
import MobileMenu from './components/MobileMenu.vue'
import Footer from './components/Footer.vue'export default {components: { Navbar, MobileMenu, Footer },data() {return {mobileMenuVisible: false}},methods: {toggleMobileMenu() {this.mobileMenuVisible = !this.mobileMenuVisible}}
}
</script><style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&display=swap');body {font-family: 'Noto Sans SC', sans-serif;background-color: #f8f4e9;color: #333;
}.chapter-card {transition: all 0.3s ease;background: rgba(255, 255, 255, 0.8);backdrop-filter: blur(10px);border-radius: 12px;overflow: hidden;
}
.chapter-card:hover {transform: translateY(-5px);box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}.content-card {background: rgba(255, 255, 255, 0.9);border-radius: 12px;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}.chapter-image {height: 200px;object-fit: cover;width: 100%;
}.text-content {line-height: 1.8;font-size: 16px;
}.original-text {border-left: 4px solid #8b5a2b;padding-left: 16px;margin-bottom: 24px;
}.translation-text {border-left: 4px solid #5a8b8b;padding-left: 16px;
}.nav-link {position: relative;
}
.nav-link::after {content: '';position: absolute;bottom: -2px;left: 0;width: 0;height: 2px;background-color: #8b5a2b;transition: width 0.3s ease;
}
.nav-link:hover::after {width: 100%;
}
.active-nav::after {width: 100%;
}
</style>
Navbar.vue (导航栏组件)
<template><nav class="bg-white shadow-sm sticky top-0 z-50"><div class="container mx-auto px-4 py-3 flex justify-between items-center"><div class="text-xl font-bold text-amber-800"><i class="fas fa-book-open mr-2"></i>道德经全文</div><div class="hidden md:flex space-x-6"><router-link to="/" class="nav-link" :class="{'active-nav text-amber-800': $route.path === '/'}">首页</router-link><router-link to="/chapters" class="nav-link text-gray-600" :class="{'active-nav text-amber-800': $route.path === '/chapters'}">章节列表</router-link></div><button class="md:hidden text-gray-600 focus:outline-none" @click="$emit('toggle-mobile-menu')"><i class="fas fa-bars"></i></button></div></nav>
</template>
MobileMenu.vue (移动端菜单)
<template><div v-if="isVisible" class="md:hidden bg-white shadow-lg rounded-lg mx-4 mt-2 p-4 absolute w-[calc(100%-2rem)] z-40"><router-link to="/" class="block py-2 px-4 rounded hover:bg-amber-50 text-amber-800"@click="$emit('close')"><i class="fas fa-home mr-2"></i>首页</router-link><router-link to="/chapters" class="block py-2 px-4 rounded hover:bg-amber-50 text-gray-600"@click="$emit('close')"><i class="fas fa-list mr-2"></i>章节列表</router-link></div>
</template><script>
export default {props: {isVisible: Boolean}
}
</script>
Home.vue (首页组件)
<template><section class="container mx-auto px-4 py-12"><div class="text-center mb-12"><h1 class="text-4xl md:text-5xl font-bold text-amber-800 mb-4">道德经</h1><p class="text-xl text-gray-600">老子 · 春秋时期</p></div><div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"><div v-for="(chapter, index) in chapters" :key="index"class="chapter-card cursor-pointer"@click="showChapter(index)"><img :src="chapter.image" :alt="chapter.title" class="chapter-image"><div class="p-4"><h3 class="text-lg font-semibold text-amber-800">{{ chapter.title }}</h3></div></div></div></section>
</template><script>
import { mapState } from 'vuex'export default {computed: {...mapState(['chapters'])},methods: {showChapter(index) {this.$router.push({ name: 'Chapter', params: { id: index } })}}
}
</script>
ChapterDetail.vue (章节详情页)
<template><section class="container mx-auto px-4 py-12"><div class="flex justify-between items-center mb-8"><button @click="$router.push('/')" class="flex items-center text-amber-800 hover:text-amber-600 transition-colors"><i class="fas fa-arrow-left mr-2"></i>返回首页</button><h2 class="text-2xl md:text-3xl font-bold text-amber-800 text-center">{{ chapter.title }}</h2><div class="w-8"></div></div><div class="content-card p-6 md:p-8 mb-8"><img :src="chapter.image" :alt="chapter.title" class="chapter-image rounded-lg mb-8" style="height: 600px; width: 100%; object-fit: contain;"><div class="text-content"><div class="original-text mb-8"><h3 class="text-xl font-semibold text-amber-800 mb-4">原文</h3><p class="whitespace-pre-line">{{ chapter.original }}</p></div><div class="translation-text"><h3 class="text-xl font-semibold text-teal-800 mb-4">释义</h3><p class="whitespace-pre-line">{{ chapter.translation }}</p></div></div></div></section>
</template><script>
import { mapState } from 'vuex'export default {computed: {...mapState(['chapters']),chapter() {const chapterId = parseInt(this.$route.params.id)return this.chapters[chapterId] || {}}}
}
</script>
Footer.vue (页脚组件)
<template><footer class="bg-amber-800 text-white py-8"><div class="container mx-auto px-4 text-center"><p class="mb-2">created by <a href="https://space.coze.cn" class="underline hover:text-amber-200">coze space</a></p><p class="text-sm">页面内容均由 AI 生成,仅供参考</p></div></footer>
</template>
Vue Router配置
// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/views/Home.vue'
import ChapterDetail from '@/views/ChapterDetail.vue'Vue.use(Router)export default new Router({routes: [{path: '/',name: 'Home',component: Home},{path: '/chapters',name: 'Chapters',component: Home},{path: '/chapter/:id',name: 'Chapter',component: ChapterDetail,props: true}]
})
Vuex Store配置
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'Vue.use(Vuex)export default new Vuex.Store({state: {chapters: []},mutations: {SET_CHAPTERS(state, chapters) {state.chapters = chapters}},actions: {async fetchChapters({ commit }) {try {const response = await axios.get('/api/chapters')commit('SET_CHAPTERS', response.data)} catch (error) {console.error('Error fetching chapters:', error)// 如果API失败,使用本地数据commit('SET_CHAPTERS', require('@/data/chapters.json'))}}}
})
后端API设计
数据库表设计 (chapters)
CREATE TABLE chapters (id INT AUTO_INCREMENT PRIMARY KEY,title VARCHAR(50) NOT NULL,original TEXT NOT NULL,translation TEXT NOT NULL,image VARCHAR(255) NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
RESTful API 设计
  1. 获取所有章节
    GET /api/chapters

    // 响应示例
    [{"id": 1,"title": "道德经·第一章","original": "道可道,非常道;名可名,非常名...","translation": "“道”如果可以用言语来表述...","image": "https://s.coze.cn/image/wvYjW1ymBT8/"},// ...其他章节
    ]
    
  2. 获取单个章节
    GET /api/chapters/:id

    {"id": 1,"title": "道德经·第一章","original": "道可道,非常道;名可名,非常名...","translation": "“道”如果可以用言语来表述...","image": "https://s.coze.cn/image/wvYjW1ymBT8/"
    }
    
  3. 创建新章节 (管理员)
    POST /api/chapters

    // 请求体
    {"title": "道德经·新章","original": "新章节原文内容...","translation": "新章节释义内容...","image": "https://s.coze.cn/image/new-image-url/"
    }
    
  4. 更新章节 (管理员)
    PUT /api/chapters/:id

    // 请求体
    {"title": "更新后的标题","original": "更新后的原文...","translation": "更新后的释义...","image": "https://s.coze.cn/image/updated-image-url/"
    }
    
  5. 删除章节 (管理员)
    DELETE /api/chapters/:id

项目部署结构
daodejing-app/
├── backend/
│   ├── controllers/
│   │   └── chapterController.js
│   ├── models/
│   │   └── Chapter.js
│   ├── routes/
│   │   └── chapterRoutes.js
│   ├── app.js
│   └── package.json
├── frontend/
│   ├── public/
│   │   ├── index.html
│   │   └── favicon.ico
│   ├── src/
│   │   ├── assets/
│   │   ├── components/
│   │   │   ├── Navbar.vue
│   │   │   ├── MobileMenu.vue
│   │   │   ├── Footer.vue
│   │   ├── views/
│   │   │   ├── Home.vue
│   │   │   └── ChapterDetail.vue
│   │   ├── store/
│   │   │   └── index.js
│   │   ├── router/
│   │   │   └── index.js
│   │   ├── App.vue
│   │   └── main.js
│   └── package.json
└── README.md
最终实现效果说明

这个Vue应用实现了《道德经》的在线阅读功能,具有以下特点:

  1. 响应式设计:在手机、平板和桌面设备上都能良好显示
  2. 优雅的中国风界面:保留原设计风格,使用暖色调和传统元素
  3. 章节浏览:以卡片形式展示所有81章
  4. 章节详情:点击章节后显示原文和释义
  5. 移动端优化:有专门的移动端菜单
  6. 数据管理:通过Vuex管理章节数据
  7. 路由管理:使用Vue Router实现页面导航

后端API提供了完整的CRUD操作,管理员可以通过API管理章节内容。前端在API请求失败时会使用本地数据作为后备方案。

整个应用保持了原HTML的设计美学,同时增加了现代Vue应用的交互性和可维护性。

要运行此应用,需要:

  1. 创建Vue项目并添加上述文件
  2. 安装必要依赖:vue-router, vuex, axios
  3. 配置后端服务(可选)
  4. 运行 npm run serve 启动前端

2.2 项目整合

根据上面提供的方案,我开始将对应的文件放到之前的项目中去,于是就开始了漫长的拉扯过程。
由于前期对showComponentrouter-view都不了解,而且TRAE在修改代码过程中,因为加入的文件,之前设计的时候还用纯CSS写法,后续就陆续换成了TailWind写法,搞得代码很是乱套,再加上小白不懂细节,搞得一团乱麻。
在这里插入图片描述

不知道是什么原因造成的,之前的交流还能帮我修改代码段
在这里插入图片描述
问着问着,就不再这样做了

在这里插入图片描述
好像是一个对话反复沟通,内容太多了,它的上下文上限了,智能体已经承受不了修改项目代码的负担,只能开始了应付了事的操作。

不管什么原因吧,反正使用AI 的IDE编程,目前为止还是不能完全依靠的,仍然需要其他的语言模型进行线上辅助方可。

当然,这次豆包新发布的1.6也有使用,但面对showComponent和router-view同频处理的问题,仍然是焦头烂额,无法解决。

在这里插入图片描述

最终只能选择放弃,查了资料,将这个切换页面的方式重新设计,采用选项卡选择,当前页面显示的效果来实现。
在这里插入图片描述

总之吧,虽然TRAE AI的IDE已经有了很大的进步,但有的时候还是会糊涂,希望越来越好,对小白的想法能更好的实现。
在这里插入图片描述

http://www.xdnf.cn/news/13851.html

相关文章:

  • boa 找不到动态库的解决办法:
  • 【零基础勇闯嵌入式岗】从单片机低功耗中获得的启发
  • 正则表达式入门
  • 【AIGC】Qwen3-Embedding:Embedding与Rerank模型新标杆
  • 【狂飙AGI】第2课:大模型方向市场分析
  • # Flask:Python的轻量级Web框架入门之旅(超级实用!)
  • 测试过程中有哪些风险?
  • KU115LPE-V10型FPGA加速卡
  • Linux操作系统之文件系统下
  • 友思特方案 | 友思特车载双目相机技术赋能农业:Monarch 智能拖拉机解决方案
  • linux基础day01
  • [25-cv-06422]David律所代理Dreams USA玩具手办商标维权
  • Java日期格式化
  • Swift 解法详解:如何在二叉树中寻找最长连续序列
  • NAS文件共享、PACS影像存储,速率提升400%?
  • PostgreSQL认证怎么选?PGCP中级认证、PGCM高级认证
  • 基于 Redis 的幂等性设计:SpringBoot @Async 在高并发 MySQL 日志存储中的应用
  • Vue3+TypeScript实现迭代器模式
  • FOC电机三环控制
  • aws s3 sdk c++使用指南、适配阿里云oss和aws
  • 「Java EE开发指南」如何用MyEclipse创建一个WEB项目?(一)
  • DDcGAN_codes
  • 【python】执行deactivate没有关闭虚拟环境
  • 交易所 java, web3 交易所简易模块
  • [SKE]CPU 与 GPU 之间数据加密传输的认证与异常处理
  • 【线程与线程池】线程数设置(四)
  • 线程池启动报null :Caused by: java.lang.IllegalArgumentException: null
  • 每日学习一道数模题-2024国赛B题-生产过程中的决策问题
  • ViT架构所需的大型训练集
  • 在 IntelliJ IDEA 中运行时出现“Log already in use? tmlog in ./“