Vue 3 开发实战

开发之前

假定你已经下载好了Node工具,并且已经配置好了本地环境以及下载好了本地的代码编辑器(可以使用cursor加快开发速度) 可以在优快云上找教程,这里我们不多做赘述 你还是需要掌握一定的Vue的知识的,不用太多,能看懂文档的程度即可

  • AI编程学习提示词示例:

    你是我的 Vue 3.0 编程老师。
    
    教学目标:
    不要直接给我完整的代码。
    先解释相关的知识点和概念,给出简单不相关的例子。
    根据我目前的知识水平,分配简单的任务让我完成。
    教学流程:
    知识点讲解:解释当前主题的基本概念。
    例子说明:用日常生活中的简单例子来帮助理解。
    布置任务:给出一个小任务,让我通过实践来巩固学习。
    互动方式:
    当我遇到困难时,请用问题引导我思考,而不是直接给出答案。
    在我完成任务后,请给予反馈并鼓励我。
    

创建项目

  • 首先我们需要在本地创建一个新的项目文件夹,这里我们项目的路径是C:\\Users\\Windows\\Desktop\\Task\\ongoing\\Here_Task\\HCI\\category_page ,当然你自己需要记得就行了
  • 然后打开CMD

这里有个巨大的坑,我不清楚为什么必须使用管理员模式打开cmd才能进行之后的操作,反正你最好打开管理员模式去进行操作,否则就会全部都是**npm error**

  • 输入接下来的指令

    npm create vue@latest
    
  • 接下来的操作你截屏下来喂给AI就行了,不用自己专门去浪费时间去记忆

安装项目依赖

  • 记得别关,接下来还是需要使用cmd窗口,而不是编辑器默认的powershell窗口

  • 输入下面的指令安装依赖,必须安装依赖!!!

    npm install
    

    接下来你会看到如下的结果,说明你的依赖安装成功了,这就结束了

在编辑器中尝试运行项目

  • 打开代码编辑器,这里我用的是cursor

  • 打开终端后记得创建一个cmd窗口,如下图所示

  • 接下来输入热部署指令(修改会时时更新的那种部署方式),尝试运行项目

    npm run dev
    
  • 如果你看到如下的页面:

恭喜你,成功启动了这个前端项目!!

正式开发

由于本人只学到了Vue2.0,所以我在这里使用了cursor的AI工具协助我理解代码和开发项目,在这里也会分享一下AI协助开发Vue3项目的一些心得体会

目标页面

  • 打算弄到这种程度吧,一个简单的分类页面,不包括上面的细分领域,仅仅只包括历史、文学、艺术、人物传记这四类真数据,其余都是假数据,不包括书本的PDF数据,仅仅只有这些书本的Json数据和图片数据

框架分析

CategoryPage/
├── public/              # 静态资源(不会被打包处理)
│   └── favicon.ico     # 网站图标
├── src/                # 源代码目录
│   ├── router/         # 路由配置
│   │   └── index.js    # 路由定义(目前为空,等待你添加页面路由)
│   ├── stores/         # 状态管理
│   │   └── counter.js  # 示例store(计数器)
│   ├── App.vue         # 根组件
│   └── main.js         # 应用入口文件
├── vite.config.js      # Vite 构建配置
├── package.json        # 项目依赖和脚本
└── README.md          # 项目说明

🔧 核心文件功能 ⇒ 以注释的形式给出介绍

  1. main.js

    import { createApp } from 'vue'
    import { createPinia } from 'pinia'
    
    import App from './App.vue'
    import router from './router'
    
    // 创建Vue实例
    const app = createApp(App)
    
    // 注册Pinia(状态管理)、router(路由)
    app.use(createPinia())
    app.use(router)
    
    // 挂载到#app DOM节点
    app.mount('#app')
    
    • .use() 是 Vue 的插件注册方法
    • Pinia 让你可以在组件间共享数据
    • Router 让你可以实现单页应用的页面切换
  2. App.vue

    <script setup></script>
    //这是 Vue 3 的 Composition API 语法糖
    //setup 属性让代码更简洁,自动处理响应式和组件注册
    //目前是空的,表示这个组件暂时没有逻辑代码
    //你可以在这里定义:
    //响应式数据(ref, reactive)
    //计算属性(computed)
    //方法(functions)
    //生命周期钩子(onMounted, onUnmounted 等)
    <template>
      <h1>You did it!</h1>
      <p>
        Visit <a href="<https://vuejs.org/>" target="_blank" rel="noopener">vuejs.org</a> to read the
        documentation
      </p>
    </template>
    //定义组件的 HTML 结构
    //这是用户在浏览器中看到的内容
    //可以使用:
    //Vue 指令(v-if, v-for, v-model 等)
    //数据绑定({{ variable }})
    //事件监听(@click, @input 等)
    <style scoped></style>
    //定义组件的 CSS 样式
    //scoped 关键字表示样式只作用于当前组件,不会影响其他组件
    //目前是空的,没有自定义样式
    
    • .vue文件分为script、template、style三个部分
  3. 工作流程图

    浏览器访问网站
        ↓
    index.html 加载
        ↓
    <div id="app"></div> ← main.js 在这里挂载
        ↓
    main.js 执行
        ├─ 创建 Vue 应用 (createApp)
        ├─ 注册 Pinia (状态管理)
        ├─ 注册 Router (路由)
        └─ 挂载 App.vue 到 #app
             ↓
        App.vue 渲染显示
        "You did it!" 出现在页面上
    

创建基本页面布局(左右分栏)

  • 根据和AI的交互,我们可以简单地将页面分为如下地几个Vue文件

    App.vue (根组件)
    ├── Sidebar.vue (左侧导航栏组件)
    │   └── CategoryItem.vue (单个分类项组件 - 可选)
    └── BookList.vue (书籍列表组件)
    		└── BookItem.vue (单个书籍卡片组件)
    
    • 至于数据,当然并不着急导入,我们一步一步地去搭建这一个页面
  • 新建一个components文件夹,并新建如下的.vue文件,参见左右两边的图片

      

  • 下载一些插件帮助开发吧!!

    • 右边的插件可以快速补全代码,你可以自己去尝试去学习他
    • cursor中右边的Snippets插件似乎还是Vue2.0的语法,兼容性真的不如VScode

对于初学者来说,AI建议将左边的父子组件合并成一个Sidebar.vue文件,这里我们参考AI的建议,修改为 单个的Sidebar.vue文件

编写左边的边栏vue文件

分为三个部分,你需要知道Sidebar.vue的一些简单的Vue语法,这种东西看看代码就可以学习了,整体来说并不难。

  • 这里面有插值语法以及事件的父传子(使用监听)、还有v-for语法

    Vue真的很简单,不难

<script setup>
import { ref } from 'vue';

const categories = ref([
    '历史', '文学', '艺术', '人物传记', '哲学宗教',
    '计算机', '心理', '社会文化', '个人成长', '经济理财', '政治军事', '童书',
    '教育学习', '科学技术', '生活百科', '期刊杂志', '原版书', '医学健康', '男生小说', '女生小说'
]);

const activeCategory = ref('历史');
const emit = defineEmits(['category-change']);

const handleCategoryClick = (category) => {
    activeCategory.value = category
    emit('category-change', category)
};
</script>

<template>
    <aside class="sidebar">
        <h2 class="sidebar-title">分类</h2>
        <nav class="category-list">
            <div v-for="(item, index) in categories" :key="index" class="category-item"
                :class="{ active: activeCategory === item }" @click="handleCategoryClick(item)">
                {{ item }}
            </div>
        </nav>
    </aside>
</template>

<style scoped>
.sidebar {
    width: 200px;
    background-color: #fff;
    border-right: 1px solid #e0e0e0;
    padding: 20px 0;
    flex-shrink: 0;
}

.sidebar-title {
    padding: 10px 20px;
    font-size: 16px;
    color: #666;
    font-weight: normal;
    margin: 0;
}

.category-list {
    margin-top: 10px;
}

.category-item {
    padding: 12px 20px;
    cursor: pointer;
    transition: all 0.3s;
    color: #333;
    user-select: none;
}

.category-item:hover {
    background-color: #f0f0f0;
}

.category-item.active {
    background-color: #4a9eff;
    color: white;
    font-weight: 500;
}
</style>

编写右侧的BookList和BookItem

  • 首先我们需要确定相关的数据流向的问题

    首先是栏目的信息,我们从App流入到BookList

    其次我们需要将数据的信息从BookList流入到BookItem

  • BookList的代码

    <script setup>
    import { ref } from "vue";
    import BookItem from "./BookItem.vue";
    
    const props = defineProps({
        currentCategory: String
    });
    
    const books = ref([
        {
            id: 1,
            rank: 1,
            title: '明朝那些事儿(全集)',
            author: '当年明月',
            cover: '<https://via.placeholder.com/120x160?text=明朝那些事儿>',
            readers: 3.6,
            recommendation: 92.3,
            tags: ['神作'],
            description: '《明朝那些事儿》主要讲述的是从1344年到1644年这三百年间关于明朝的一些故事,以史料为基础,以年代和具体人物为主线,并加入了小说的笔法,语言幽默风趣。对明朝十七帝和其他王公权贵和小人物的命运进行全景展示...'
        },
        {
            id: 2,
            rank: 2,
            title: '大明王朝1566(全集)',
            author: '刘和平',
            cover: '<https://via.placeholder.com/120x160?text=大明王朝>',
            readers: 5.9,
            recommendation: 91.6,
            tags: ['神作'],
            description: '豆瓣9.5分高评好剧《大明王朝1566》同名小说,台湾翻拍必读,新加坡内阁政治参考书。此书为《雍正王朝》编剧、《北平无战事》作者刘和平成名之作。全书以倒叙大臣架空草率宋朝为连索...'
        },
        {
            id: 3,
            rank: 3,
            title: '张居正(全4卷)',
            author: '熊召政',
            cover: '<https://via.placeholder.com/120x160?text=张居正>',
            readers: 4.2,
            recommendation: 87.3,
            tags: ['好评如潮'],
            description: '张居正是一位个性不凡的政治家,是明万历年间同房行革命而彪炳史册的传奇人物。他身上首辅之位后,理致十年:整治更治,刷新颓风;整治教育,延揽贤士;革新税赋,梳理财政;推行新法...'
        }
    ])
    </script>
    
    <template>
        <div class="book-list-container">
            <div class="book-list">
                <BookItem v-for="book in books" :key="book.id" :book="book" />
            </div>
        </div>
    </template>
    
    <style scoped>
    .book-list-container {
        background-color: white;
        border-radius: 8px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        overflow: hidden;
    }
    </style>
    
  • BookItem.vue的代码

    <script setup>
    const props = defineProps({
        book: {
            type: Object,
            required: true
        }
    })
    </script>
    
    <template>
        <div class="book-item">
            <!-- 排名 -->
            <div class="book-rank">{{ book.rank }}</div>
    
            <!-- 封面图 -->
            <img :src="book.cover" :alt="book.title" class="book-cover" />
    
            <!-- 书籍信息 -->
            <div class="book-info">
                <h3 class="book-title">{{ book.title }}</h3>
                <p class="book-author">{{ book.author }}</p>
    
                <!-- 统计信息 -->
                <div class="book-stats">
                    <span class="stat-item">{{ book.readers }}万人今日阅读</span>
                    <span class="stat-divider">|</span>
                    <span class="stat-item">推荐值 {{ book.recommendation }}%</span>
                    <span class="book-tag" :class="book.tags[0]">
                        {{ book.tags[0] }}
                    </span>
                </div>
    
                <!-- 简介 -->
                <p class="book-description">{{ book.description }}</p>
            </div>
        </div>
    </template>
    
    <style scoped>
    .book-item {
        display: flex;
        gap: 20px;
        padding: 20px;
        border-bottom: 1px solid #f0f0f0;
        transition: background-color 0.3s;
    }
    
    .book-item:hover {
        background-color: #fafafa;
    }
    
    .book-item:last-child {
        border-bottom: none;
    }
    
    .book-rank {
        font-size: 28px;
        font-weight: bold;
        color: #999;
        min-width: 40px;
        text-align: center;
    }
    
    .book-cover {
        width: 120px;
        height: 160px;
        object-fit: cover;
        border-radius: 4px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        transition: transform 0.3s;
    }
    
    .book-cover:hover {
        transform: scale(1.05);
    }
    
    .book-info {
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 8px;
    }
    
    .book-title {
        font-size: 20px;
        color: #333;
        margin: 0;
        cursor: pointer;
    }
    
    .book-title:hover {
        color: #4a9eff;
    }
    
    .book-author {
        color: #666;
        font-size: 14px;
        margin: 0;
    }
    
    .book-stats {
        display: flex;
        align-items: center;
        gap: 8px;
        font-size: 14px;
        color: #999;
    }
    
    .stat-divider {
        color: #ddd;
    }
    
    .book-tag {
        padding: 2px 8px;
        border-radius: 4px;
        font-size: 12px;
        margin-left: 8px;
        font-weight: 500;
    }
    
    .book-tag.神作 {
        background-color: #fff3e0;
        color: #ff9800;
    }
    
    .book-tag.好评如潮 {
        background-color: #fce4ec;
        color: #e91e63;
    }
    
    .book-description {
        color: #666;
        font-size: 14px;
        line-height: 1.6;
        margin: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        -webkit-box-orient: vertical;
    }
    </style>
    

效果示意

导入数据

在导入数据之前,我们需要预先爬取相关的数据

放在哪里?

  • 这里我们区分一下不同数据的导入路径

    开始
    ↓
    问:文件数量多吗(>100个)?
    ├─ 是 → public/
    └─ 否 → 继续
    		↓
    		问:需要被优化/压缩吗?
    		├─ 是 → assets/
    		└─ 否 → 继续
    				↓
    				问:需要固定的URL吗?
    				├─ 是 → public/
    				└─ 否 → assets/
    

如何构建

  • Json数据的格式应该如下:

    {
        "index": 1,
        "title": "明朝那些事儿(全集)",
        "author": "当年明月",
        "coverImage": "images/history/1_明朝那些事儿(全集).jpg",
        "description": "《明朝那些事儿》主要讲述的是从1344年到1644年这三百年间关于明朝的一些故事。以史料为基础,以年代和具体人物为主线,并加入了小说的笔法,语言幽默风趣。对明朝十七帝和其他王公权贵和小人物的命运进行全景展示,尤其对官场政治、战争、帝王心术着墨最多,并加入对当时政治经济制度、人伦道德的演义。它以一种网络语言向读者娓娓道出明朝三百多年的历史故事、人物。其中原本在历史中陌生、模糊的历史人物在书中一个个变得鲜活起来。《明朝那些事儿》为我们解读历史中的另一面,让历史变成一部活生生的生活故事。"
    }
    
    • 这里使用images/可以方便将图片从public中导出来
  • 然后我们应该在BookList中导入相关的图片

    这里我们需要使用@(src/)

    import historyBooks from '@/assets/data/history_books.json';
    import artBooks from '@/assets/data/art_books.json';
    import biographyBooks from '@/assets/data/biography_books.json';
    import literatureBooks from '@/assets/data/literature_books.json';
    
  • 数据组织形式:

    使用Map的形式进行组织:

    const booksMap = {
        '历史': historyBooks,
        '文学': literatureBooks,
        '艺术': artBooks,
        '人物传记': biographyBooks,
    }
    

如何动态监测

  • 使用watch模块去搭建
const books = ref(booksMap[props.currentCategory] || historyBooks);

watch(() => props.currentCategory, (newVal) => {
    books.value = booksMap[newVal] || historyBooks;
})

最终效果

Git管理

创建分支

首先,为什么要创建分支??

  • 很简单:方便组织管理,比如说A在main上面添加了一些东西,B也在main上面添加了一些东西,这样会导致不同的用户添加的东西不一样,会导致出现冲突的可能性
  • 这时候,管理者就可以使用git中的分支去进行项目管理,A、B在各自的分支下进行工作,这样A、B的工作就会互不干扰,最后管理者只需要在最后合并分支即可了,当然分支的构建以及文件的存储也需要按照一定的规范进行

修改本地代码上传即可

  • 这一步其实应该在最开始进行是最好的
  • 所以以后进行项目前需要规定好项目的规范文档!!这是最重要的,可以减少很多的后续时间
  • 然后提交更改信息,本地保存后同步到远端即可!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值