news 2026/3/13 6:14:16

Vue.js从入门到精通:核心技术全解析与实战指南(2025版)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue.js从入门到精通:核心技术全解析与实战指南(2025版)

作为前端三大框架之一,Vue.js以其“渐进式框架”特性、简洁的API设计和强大的生态系统,成为前端开发的主流选择。本文基于Vue 3(Composition API)展开,从环境搭建、核心语法、组件化开发,到状态管理、路由配置、性能优化,再到实战项目落地,全程配套实操步骤、代码示例与问题解决方案,适合零基础入门到进阶提升的开发者系统学习。

本文亮点: 1. 聚焦Vue 3核心特性,摒弃过时Vue 2语法,贴合企业最新技术栈; 2. 每个技术点配套“语法解析+代码示例+效果演示”,可直接复制运行; 3. 融入企业级开发规范与避坑技巧,提升代码质量; 4. 附实战项目完整流程,将零散技术点串联落地。

目录

  1. Vue.js简介与环境搭建(附Node.js配置避坑)

  2. Vue 3核心语法:从Options API到Composition API

  3. 组件化开发:通信、插槽与自定义指令

  4. Vue Router:路由配置与权限控制实战

  5. Pinia状态管理:替代Vuex的轻量方案

  6. Vue项目性能优化:从编码到构建全流程

  7. 实战项目:TodoList全功能开发(附完整代码)

  8. Vue生态拓展与学习资源推荐

一、Vue.js简介与环境搭建

1.1 为什么选择Vue.js?

Vue.js的核心优势在于“渐进式”——开发者可根据需求逐步引入其生态组件(如Router、Pinia),而非一次性接纳整个框架,降低学习与迁移成本。此外,Vue 3的Composition API解决了Vue 2 Options API在大型项目中代码复用、逻辑组织的痛点,配合TypeScript支持,更适合企业级开发。

适用场景:单页应用(SPA)、移动端应用(通过Vue Native/uni-app)、后台管理系统、中小型前端项目快速迭代。

1.2 环境搭建全流程(附避坑指南)

Vue项目依赖Node.js(运行环境)和npm/yarn(包管理工具),需先完成基础环境配置。

1.2.1 安装Node.js与npm

推荐安装LTS版本(长期支持版),避免最新版存在兼容性问题:

  1. 下载Node.js:访问Node.js官方网站,选择“18.20.2 LTS”版本(Windows/macOS通用);

  2. 安装过程:Windows双击安装包,勾选“Add to PATH”(自动配置环境变量);macOS可通过.pkg安装或brew命令安装;

  3. 验证安装:打开终端,输入以下命令,若显示版本号则安装成功:node -v # 输出:v18.20.2npm -v # 输出:9.7.2

避坑指南:若Windows系统提示“node不是内部或外部命令”,需手动配置环境变量——找到Node.js安装目录(如C:\Program Files\nodejs),添加到系统PATH中,重启终端即可。

1.2.2 配置npm镜像(提升下载速度)

默认npm镜像为国外源,下载依赖速度慢,建议切换为淘宝镜像:

# 配置淘宝镜像 npm config set registry https://registry.npmmirror.com/ # 验证配置 npm config get registry # 输出:https://registry.npmmirror.com/ 则成功

1.2.3 安装Vue CLI(脚手架工具)

Vue CLI可快速创建标准化Vue项目,包含webpack配置、热更新、代码检查等功能:

# 全局安装Vue CLI npm install -g @vue/cli # 验证安装 vue --version # 输出:@vue/cli 5.0.8 则成功

1.2.4 创建第一个Vue项目

以创建“vue-demo”项目为例,步骤如下:

# 1. 执行创建命令 vue create vue-demo # 2. 选择项目模板: # 新手推荐选择“Default ([Vue 3] babel, eslint)”(默认Vue 3模板) # 进阶用户可选择“Manually select features”(自定义配置:TypeScript、Router等) # 3. 等待项目创建:自动下载依赖,约1-3分钟(取决于网络速度) # 4. 启动项目 cd vue-demo # 进入项目目录 npm run serve # 启动开发服务器

启动成功后,终端会显示访问地址(默认:http://localhost:8080),打开浏览器访问该地址,即可看到Vue默认欢迎页面。

配图1:Vue项目启动成功页面

二、Vue 3核心语法:从Options API到Composition API

Vue 3兼容Vue 2的Options API(选项式API),但推荐使用Composition API(组合式API)——通过setup函数或<script setup>语法糖,将分散的逻辑聚合,提升代码复用性。

2.1 核心语法对比:Options API vs Composition API

以“计数器”功能为例,对比两种API的实现方式:

2.1.1 Options API实现(Vue 2风格)

<template> <div> <h2>计数器:{{ count }}</h2> <button @click="increment">+1</button> </div> </template> <script> export default { // 数据 data() { return { count: 0 } }, // 方法 methods: { increment() { this.count++ } }, // 生命周期钩子 mounted() { console.log('组件挂载完成,初始count:', this.count) } } </script>

2.1.2 Composition API实现(Vue 3推荐)

使用<script setup>语法糖(简化代码,无需导出默认对象):

<template> <div> <h2>计数器:{{ count }}</h2> <button @click="increment">+1</button> </div> </template> <script setup> // 从Vue中导入需要的API import { ref, onMounted } from 'vue' // 定义响应式数据(基本类型用ref) const count = ref(0) // 定义方法 const increment = () => { count.value++ // ref类型需通过.value访问 } // 生命周期钩子(Composition API中钩子前缀加on) onMounted(() => { console.log('组件挂载完成,初始count:', count.value) }) </script>

2.1.3 核心差异总结

对比维度

Options API

Composition API

逻辑组织

按选项(data、methods、mounted)拆分,分散在不同配置中

按功能聚合,相关逻辑写在同一处,便于维护

代码复用

依赖mixins,易出现命名冲突

通过组合函数(Composables)复用,逻辑清晰无冲突

TypeScript支持

较差,类型推断不精准

优秀,原生支持TypeScript,类型推断精准

2.2 Composition API核心API详解

2.2.1 响应式数据:ref与reactive

Vue 3通过ref和reactive实现数据响应式,对应不同数据类型:

  • ref:用于基本类型(Number、String、Boolean),通过.value访问/修改值;

  • reactive:用于引用类型(Object、Array),直接访问属性,无需.value。

<script setup> import { ref, reactive } from 'vue' // 基本类型响应式 const name = ref('Vue 3') name.value = 'Vue.js 3.4' // 修改值 // 引用类型响应式 const user = reactive({ age: 3, address: '中国' }) user.age = 4 // 直接修改属性 // 数组响应式(也可用reactive) const list = reactive([1, 2, 3]) list.push(4) // 直接调用数组方法 </script>

2.2.2 计算属性:computed

用于依赖其他响应式数据的计算逻辑,缓存计算结果,避免重复计算:

<template> <div> <p>原始列表:{{ list }}</p> <p>偶数列表:{{ evenList }}</p> </div> </template> <script setup> import { ref, computed } from 'vue' const list = ref([1, 2, 3, 4, 5]) // 计算属性:筛选偶数 const evenList = computed(() => { return list.value.filter(item => item % 2 === 0) }) </script>

2.2.3 侦听器:watch

监听响应式数据变化,执行自定义逻辑:

<script setup> import { ref, watch } from 'vue' const count = ref(0) // 监听count变化 watch(count, (newVal, oldVal) => { console.log(`count从${oldVal}变为${newVal}`) }, { immediate: true, // 初始时执行一次 deep: false // 是否深度监听(引用类型需开启) }) // 监听引用类型某属性 const user = ref({ age: 3 }) watch(() => user.value.age, (newAge) => { console.log('年龄变化:', newAge) }) </script>

三、组件化开发:通信、插槽与自定义指令

组件化是前端框架的核心思想,将页面拆分为独立、可复用的组件,提升开发效率与代码可维护性。Vue 3的组件化开发更灵活,支持多种通信方式与插槽用法。

3.1 组件基础:定义与使用

Vue组件默认以.vue文件形式存在,包含<template>(模板)、<script>(逻辑)、<style>(样式)三部分:

3.1.1 定义组件(MyButton.vue)

<template> <button class="my-btn" @click="handleClick"> {{ btnText }} </button> </template> <script setup> // 定义props(父组件向子组件传值) const props = defineProps({ btnText: { type: String, required: true, // 必传属性 default: '按钮' // 默认值(可选) } }) // 定义事件(子组件向父组件传值) const emit = defineEmits(['click']) const handleClick = () => { emit('click') // 触发事件 } </script> <style scoped> /* scoped表示样式仅作用于当前组件 */ .my-btn { padding: 8px 16px; background: #42b983; color: white; border: none; border-radius: 4px; cursor: pointer; } </style>

3.1.2 使用组件(父组件App.vue)

<template> <div> <h2>组件使用示例</h2> <MyButton btnText="点击触发" @click="handleBtnClick" /> </div> </template> <script setup> // 导入组件(Vue 3自动注册,无需components配置) import MyButton from './components/MyButton.vue' const handleBtnClick = () => { alert('子组件按钮被点击') } </script>

配图2:组件渲染效果

3.2 组件通信方式汇总(企业级常用)

组件通信是组件化开发的核心,不同场景适配不同通信方式,以下是企业级开发中最常用的4种:

3.2.1 父传子:props

适用场景:父组件向子组件传递数据(单向数据流,子组件不可直接修改props)。

<!-- 父组件 --> <template> <Child :user="userInfo" :isShow="true" /> </template> <script setup> import Child from './Child.vue' const userInfo = { name: '张三', age: 20 } </script> <!-- 子组件Child.vue --> <script setup> const props = defineProps({ user: { type: Object, required: true }, isShow: Boolean }) console.log(props.user.name) // 访问父组件传递的数据 </script>

3.2.2 子传父:emit事件

适用场景:子组件向父组件传递数据或触发父组件逻辑。

<!-- 子组件Child.vue --> <template> <button @click="sendData">向父组件传值</button> </template> <script setup> const emit = defineEmits(['send']) // 定义可触发的事件 const sendData = () => { emit('send', '子组件传递的数据') // 触发事件并传值 } </script> <!-- 父组件 --> <template> <Child @send="receiveData" /> </template> <script setup> import Child from './Child.vue' const receiveData = (data) => { console.log('接收子组件数据:', data) // 输出:子组件传递的数据 } </script>

3.2.3 跨组件通信:Pinia

适用场景:祖孙组件、非父子组件等跨层级通信(替代Vue 2的Vuex)。具体用法见第五章。

3.2.4 依赖注入:provide/inject

适用场景:深层级组件通信(如爷爷组件向孙子组件传值,无需逐层传递)。

<!-- 顶层组件(爷爷) --> <script setup> import { provide } from 'vue' // 提供数据(可传递任意类型) provide('themeColor', 'red') // 提供方法 provide('changeTheme', (color) => { console.log('切换主题色:', color) }) </script> <!-- 深层组件(孙子) --> <script setup> import { inject } from 'vue' // 注入数据 const themeColor = inject('themeColor', 'blue') // 第二个参数是默认值 // 注入方法 const changeTheme = inject('changeTheme') changeTheme('blue') // 调用顶层组件提供的方法 </script>

3.3 插槽:组件内容分发

插槽用于父组件向子组件传递HTML内容,实现组件的灵活复用,分为默认插槽、具名插槽、作用域插槽三种。

3.3.1 默认插槽(基础用法)

<!-- 子组件Card.vue --> <template> <div class="card"> <!-- 默认插槽:接收父组件传递的内容 --> <slot>默认内容(父组件未传内容时显示)</slot> </div> </template> <!-- 父组件 --> <template> <Card> <h3>卡片标题</h3> <p>卡片内容:这是通过默认插槽传递的HTML内容</p> </Card> </template>

3.3.2 具名插槽(多区域分发)

当子组件需要多个插槽区域时,使用具名插槽:

<!-- 子组件Card.vue --> <template> <div class="card"> <div class="card-header"> <slot name="header">默认标题</slot> </div> <div class="card-body"> <slot name="body">默认内容</slot> </div> </div> </template> <!-- 父组件 --> <template> <Card> <template #header&gt; <!-- 简写:#header = v-slot:header --> <h3>自定义标题</h3> </template> <template #body> <p>自定义内容:具名插槽可实现多区域内容分发</p> </template> </Card> </template>

四、Vue Router:路由配置与权限控制实战

Vue Router是Vue官方的路由插件,用于实现单页应用(SPA)的页面跳转。在后台管理系统、多页面应用中必不可少,核心功能包括路由配置、参数传递、嵌套路由、权限控制等。

4.1 Vue Router安装与基础配置

4.1.1 安装Vue Router

# 进入项目目录 cd vue-demo # 安装Vue Router(Vue 3对应版本4.x) npm install vue-router@4

4.1.2 基础路由配置

步骤1:创建路由配置文件(src/router/index.js)

// src/router/index.js import { createRouter, createWebHistory } from 'vue-router' // 导入页面组件 import Home from '../views/Home.vue' import About from '../views/About.vue' // 路由规则 const routes = [ { path: '/', // 路由路径 name: 'Home', // 路由名称(可选) component: Home // 对应组件 }, { path: '/about', name: 'About', component: About } ] // 创建路由实例 const router = createRouter({ history: createWebHistory(), // 采用HTML5 history模式(无#号) routes // 传入路由规则 }) export default router

步骤2:在main.js中引入路由

// src/main.js import { createApp } from 'vue' import App from './App.vue' import router from './router' // 引入路由 // 挂载路由 createApp(App).use(router).mount('#app')

步骤3:使用路由(App.vue中添加路由出口和导航)

<template> <div id="app"> <!-- 路由导航:router-link替代a标签,避免页面刷新 --> <nav> <router-link to="/">首页</router-link> <router-link to="/about">关于我们</router-link> </nav> <!-- 路由出口:匹配的路由组件将渲染在这里 --> <router-view></router-view> </div> </template>

配图3:路由跳转效果

4.2 路由参数传递(两种常用方式)

4.2.1 动态路由参数(适用于详情页)

场景:从列表页跳转到详情页,传递ID参数。

// 1. 配置动态路由(router/index.js) const routes = [ // ...其他路由 { path: '/user/:id', // 动态参数id name: 'User', component: () => import('../views/User.vue') // 懒加载组件(优化性能) } ]

<!-- 2. 跳转传递参数(列表页) --> <router-link :to="`/user/${1}`">用户1</router-link> <!-- 或通过编程式导航 --> <button @click="goToUser(2)">用户2</button> <script setup> import { useRouter } from 'vue-router' const router = useRouter() const goToUser = (id) => { router.push(`/user/${id}`) } </script>

<!-- 3. 接收参数(详情页User.vue) --> <script setup> import { useRoute } from 'vue-router' const route = useRoute() console.log('用户ID:', route.params.id) // 输出传递的id参数 </script>

4.2.2 query参数(适用于列表筛选)

场景:列表页筛选条件传递(如页码、搜索关键词),参数显示在URL中(?key=value)。

<!-- 跳转传递query参数 --> <router-link :to="{ path: '/list', query: { page: 1, keyword: 'vue' } }"> 列表页(第1页,搜索vue) </router-link> <!-- 接收query参数 --> <script setup> import { useRoute } from 'vue-router' const route = useRoute() console.log('页码:', route.query.page) // 输出:1 console.log('关键词:', route.query.keyword) // 输出:vue </script>

4.3 企业级权限控制(路由守卫)

权限控制是后台管理系统的核心需求,通过Vue Router的“路由守卫”实现——在路由跳转前判断用户是否有权限访问目标页面。

核心场景:未登录用户禁止访问首页、列表页等需要权限的页面,自动跳转到登录页。

// src/router/index.js import { createRouter, createWebHistory } from 'vue-router' const routes = [ { path: '/login', name: 'Login', component: () => import('../views/Login.vue') }, { path: '/', name: 'Home', component: () => import('../views/Home.vue'), meta: { requiresAuth: true } // 标记需要登录权限 } ] const router = createRouter({ history: createWebHistory(), routes }) // 全局前置守卫:路由跳转前执行 router.beforeEach((to, from, next) => { // 判断目标路由是否需要权限 if (to.meta.requiresAuth) { // 模拟判断是否登录(实际项目中从Pinia/本地存储获取) const isLogin = localStorage.getItem('token') // 登录成功后存储token if (isLogin) { next() // 已登录,放行 } else { next('/login') // 未登录,跳转到登录页 } } else { next() // 不需要权限,直接放行 } }) export default router

配图4:权限控制效果演示

五、Pinia状态管理:替代Vuex的轻量方案

Pinia是Vue官方推荐的状态管理库,用于管理跨组件共享的状态(如用户信息、全局配置),相比Vuex更简洁、更易用,原生支持TypeScript,已成为Vue 3项目的首选状态管理方案。

5.1 Pinia安装与基础使用

5.1.1 安装Pinia

npm install pinia

5.1.2 创建Pinia实例并挂载

// src/main.js import { createApp } from 'vue' import App from './App.vue' import { createPinia } from 'pinia' // 引入Pinia import router from './router' const app = createApp(App) app.use(createPinia()) // 挂载Pinia app.use(router) app.mount('#app')

5.1.3 定义Store(状态容器)

创建src/stores/user.js(Store是Pinia的核心,用于存储共享状态和方法):

// src/stores/user.js import { defineStore } from 'pinia' // 定义Store:第一个参数是Store唯一标识,第二个参数是配置对象 export const useUserStore = defineStore('user', { // 状态:存储共享数据 state: () => ({ token: localStorage.getItem('token') || '', // 登录token userInfo: JSON.parse(localStorage.getItem('userInfo')) || null // 用户信息 }), // 计算属性:基于state派生的状态(类似Vue的computed) getters: { // 判断是否登录 isLogin: (state) => !!state.token }, // 动作:修改state的方法(支持同步/异步) actions: { // 登录:保存token和用户信息 login(token, userInfo) { this.token = token this.userInfo = userInfo // 持久化存储到本地(防止页面刷新丢失) localStorage.setItem('token', token) localStorage.setItem('userInfo', JSON.stringify(userInfo)) }, // 退出登录:清除状态 logout() { this.token = '' this.userInfo = null localStorage.clear() } } })

5.1.4 在组件中使用Store

<!-- 登录组件Login.vue --> <template> <div class="login"> <h2>登录页面</h2> <button @click="handleLogin">模拟登录</button> </div> </template> <script setup> import { useUserStore } from '@/stores/user' import { useRouter } from 'vue-router' const userStore = useUserStore() // 获取Store实例 const router = useRouter() const handleLogin = () => { // 模拟接口请求成功后获取token和用户信息 const token = 'fake-token-123456' const userInfo = { name: '张三', role: 'admin' } // 调用Store的login方法 userStore.login(token, userInfo) // 跳转到首页 router.push('/') } </script>

<!-- 首页Home.vue --> <template> <div> <h2>欢迎您,{{ userStore.userInfo?.name }}</h2> <p>用户角色:{{ userStore.userInfo?.role }}</p> <button @click="userStore.logout">退出登录</button> </div> </template> <script setup> import { useUserStore } from '@/stores/user' const userStore = useUserStore() </script>

六、Vue项目性能优化:从编码到构建全流程

性能优化是企业级项目的必备技能,Vue项目的优化可分为“编码阶段”“构建阶段”“运行阶段”三个维度,以下是高频优化手段:

6.1 编码阶段优化(开发时可落地)

6.1.1 组件懒加载(路由级别)

默认情况下,Vue项目启动时会加载所有组件,导致首屏加载缓慢。通过路由懒加载,可实现组件按需加载(访问时才加载):

// 优化前:直接导入,启动时加载 import Home from '../views/Home.vue' // 优化后:懒加载,访问时才加载 const Home = () => import('../views/Home.vue') // 路由配置 const routes = [ { path: '/', component: Home } ]

6.1.2 v-for优化:key属性与避免同时使用v-if

  • v-for必须加key属性(唯一标识,避免DOM重复渲染);

  • 避免v-for与v-if同时使用(v-for优先级高于v-if,会导致重复判断),可先通过computed筛选数据。

<!-- 优化前:v-for与v-if同时使用 --> <div v-for="item in list" :key="item.id" v-if="item.status === 1"> {{ item.name }} </div> <!-- 优化后:computed筛选数据 --> <div v-for="item in activeList" :key="item.id"> {{ item.name }} </div> <script setup> import { ref, computed } from 'vue' const list = ref([/* 数据 */]) const activeList = computed(() => { return list.value.filter(item => item.status === 1) }) </script>

6.1.3 响应式数据优化:避免不必要的响应式

对于不需要响应式的数据(如静态配置、常量),避免使用ref/reactive包裹,减少Vue的响应式监听开销:

<script setup> // 优化前:不必要的响应式 const config = ref({ baseUrl: 'https://api.example.com' }) // 优化后:非响应式常量 const config = { baseUrl: 'https://api.example.com' } </script>

6.2 构建阶段优化(打包时配置)

6.2.1 压缩代码与移除console

Vue CLI项目可通过vue.config.js配置,实现打包时压缩代码、移除console.log,减小包体积:

// vue.config.js module.exports = { configureWebpack: (config) => { // 生产环境配置 if (process.env.NODE_ENV === 'production') { // 压缩代码 config.optimization.minimize = true // 移除console config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true } } }

6.2.2 第三方库按需引入

对于Element Plus、Ant Design Vue等UI库,避免全量引入,只引入需要的组件:

<!-- 优化前:全量引入(包体积大) --> import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' app.use(ElementPlus) <!-- 优化后:按需引入(推荐) --> import { ElButton, ElInput } from 'element-plus' import 'element-plus/theme-chalk/el-button.css' import 'element-plus/theme-chalk/el-input.css' app.use(ElButton).use(ElInput)

6.3 运行阶段优化(用户体验)

6.3.1 图片优化

  • 使用webp格式图片(体积比jpg小30%+);

  • 大图片懒加载(使用vue-lazyload插件);

  • 根据屏幕尺寸加载不同分辨率图片。

6.3.2 首屏加载优化:添加骨架屏

首屏加载时显示骨架屏(占位元素),替代空白页面,提升用户体验:可使用vue-skeleton-webpack-plugin插件实现。

七、实战项目:TodoList全功能开发

本节通过TodoList项目,将前面讲解的核心技术(Composition API、组件化、Pinia、Vue Router)串联落地,实现“添加任务、删除任务、修改状态、筛选任务”全功能。

7.1 项目结构

src/ ├── components/ # 组件 │ ├── TodoInput.vue # 任务输入组件 │ ├── TodoItem.vue # 任务项组件 │ └── TodoFilter.vue # 任务筛选组件 ├── views/ │ └── TodoList.vue # 任务列表页面 ├── stores/ │ └── todo.js # 任务状态管理 ├── router/ │ └── index.js # 路由配置 └── main.js # 入口文件

7.2 核心代码实现

7.2.1 定义Todo Store(src/stores/todo.js)

import { defineStore } from 'pinia' export const useTodoStore = defineStore('todo', { state: () => ({ todos: JSON.parse(localStorage.getItem('todos')) || [ { id: 1, title: '学习Vue 3', done: false }, { id: 2, title: '掌握Pinia', done: true } ], filter: 'all' // 筛选条件:all(全部)、active(未完成)、completed(已完成) }), getters: { // 筛选后的任务列表 filteredTodos: (state) => { switch (state.filter) { case 'active': return state.todos.filter(todo => !todo.done) case 'completed': return state.todos.filter(todo => todo.done) default: return state.todos } }, // 未完成任务数量 activeCount: (state) => { return state.todos.filter(todo => !todo.done).length } }, actions: { // 添加任务 addTodo(title) { if (!title.trim()) return const newTodo = { id: Date.now(), // 用时间戳作为唯一ID title, done: false } this.todos.push(newTodo) this.saveToLocal() // 持久化存储 }, // 删除任务 deleteTodo(id) { this.todos = this.todos.filter(todo => todo.id !== id) this.saveToLocal() }, // 切换任务状态 toggleTodo(id) { const todo = this.todos.find(todo => todo.id === id) if (todo) todo.done = !todo.done this.saveToLocal() }, // 设置筛选条件 setFilter(filter) { this.filter = filter }, // 持久化存储到本地 saveToLocal() { localStorage.setItem('todos', JSON.stringify(this.todos)) } } })

7.2.2 任务输入组件(src/components/TodoInput.vue)

<template> <input type="text" v-model="title" placeholder="请输入任务..." @keyup.enter="addTodo" class="todo-input" > </template> <script setup> import { ref } from 'vue' import { useTodoStore } from '@/stores/todo' const todoStore = useTodoStore() const title = ref('') const addTodo = () => { todoStore.addTodo(title.value) title.value = '' // 清空输入框 } </script> <style scoped> .todo-input { width: 100%; padding: 10px; font-size: 16px; border: 1px solid #ddd; border-radius: 4px; margin-bottom: 20px; } </style>

7.2.3 任务列表页面(src/views/TodoList.vue)

<template> <div class="todo-container"> <h2>TodoList 任务列表</h2> <TodoInput /> <div class="todo-list"> <TodoItem v-for="todo in todoStore.filteredTodos" :key="todo.id" :todo="todo" /> </div> <div class="todo-footer"> <span>剩余 {{ todoStore.activeCount }} 个任务</span> <TodoFilter /> </div> </div> </template> <script setup> import TodoInput from '@/components/TodoInput.vue' import TodoItem from '@/components/TodoItem.vue' import TodoFilter from '@/components/TodoFilter.vue' import { useTodoStore } from '@/stores/todo' const todoStore = useTodoStore() </script> <style scoped> .todo-container { width: 500px; margin: 20px auto; padding: 20px; border: 1px solid #eee; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.1); } .todo-list { margin-bottom: 20px; } .todo-footer { display: flex; justify-content: space-between; align-items: center; color: #666; } </style>

7.3 项目效果演示

配图5:TodoList项目最终效果

八、Vue生态拓展与学习资源推荐

8.1 核心生态工具

  • UI组件库:Element Plus(Vue 3)、Ant Design Vue、Vant(移动端);

  • 构建工具:Vite(替代webpack,更快的构建速度);

  • 移动端开发:uni-app(一套代码多端发布:H5、小程序、App)、Vue Native;

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/11 21:46:51

学校图书馆自动化恒温恒湿控制系统技术方案

学校图书馆自动化恒温恒湿控制系统技术方案 一、项目背景与核心目标 &#xff08;一&#xff09;项目背景 学校图书馆作为教学辅助核心场所&#xff0c;兼具文献保存与师生阅览双重属性&#xff1a;一方面&#xff0c;教材、图书、特藏资料&#xff08;如校史档案&#xff0…

作者头像 李华
网站建设 2026/3/11 21:41:44

数据自己掌控!Nextcloud+CPolar 打造灵活私有云

前言 Nextcloud 是一款私有云存储工具&#xff0c;支持文件存储、同步、共享&#xff0c;还能进行在线编辑和权限管理&#xff0c;适合个人用户和企业团队存储重要数据&#xff0c;优点是数据存储在自己的服务器&#xff0c;安全性高&#xff0c;且支持多设备同步。 使用 Nex…

作者头像 李华
网站建设 2026/3/11 21:04:55

Windows系统文件tsgqec.dll丢失损坏问题 下载修复方法

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/3/3 7:52:36

微信小程序uniapp-vue旅游景点门票预订服务平台

文章目录具体实现截图主要技术与实现手段系统设计与实现的思路系统设计方法java类核心代码部分展示结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;具体实现截图 本系统&#xff08;程序源码数据库调试部署讲解&#xff09;带文档1万…

作者头像 李华
网站建设 2026/3/12 6:43:23

微信小程序uniapp-vue校园二手商城交易评价系统

文章目录 具体实现截图主要技术与实现手段系统设计与实现的思路系统设计方法java类核心代码部分展示结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 具体实现截图 本系统&#xff08;程序源码数据库调试部署讲解&#xff09;带文档1…

作者头像 李华
网站建设 2026/3/9 21:42:40

代码签名证书:选型与申请全攻略

代码签名的定义 代码签名是一种数字签名技术&#xff0c;用于验证软件或代码的发布者身份及完整性。通过代码签名证书&#xff0c;开发者可以对可执行文件、脚本、驱动程序等文件进行签名&#xff0c;确保用户下载的代码未被篡改且来源可信。 …

作者头像 李华