本文将详细介绍Vue3项目实战,从基础入门到组件化开发、路由与导航、状态管理等核心概念,帮助新手快速上手,并提供一些实用的技巧和最佳实践。文章还涵盖了Vue3项目的创建与运行流程,以及项目部署与上线的指导方法。
Vue.js 是一个用于构建用户界面的渐进式框架。与其它框架不同的是,Vue.js 采用自底向上增量开发的设计,其核心库只关注视图层,易于与其它库或已存在的项目整合。Vue 3 是 Vue 的最新版本,提供了更好的性能、TypeScript 支持以及更强大的工具链。
要开始使用 Vue 3,首先需要安装 Vue CLI,这是一个 Vue.js 的命令行工具,可以用来初始化、构建和运行 Vue 项目。Vue CLI 提供了多种配置选项,可以根据项目的具体需求进行选择。
安装 Vue CLI
npm install -g @vue/cli
创建 Vue 项目
使用 Vue CLI 创建一个新的 Vue 项目:
vue create my-vue-app
选择默认配置或手动配置,然后等待项目创建完成。
启动项目
进入项目目录并启动开发服务器:
cd my-vue-app npm run serve
开发服务器将在本地主机的 http://localhost:8080
上运行。
Vue 3 通过 ref
和 reactive
提供响应式数据绑定。ref
用于创建一个可变的引用,而 reactive
用于创建一个响应式对象。
import { ref, reactive } from 'vue'; const count = ref(0); // 创建一个 ref 对象,初始值为 0 const state = reactive({ count: 0 }); // 创建一个响应式对象
在组件中使用 ref
:
<template> <div> <p>{{ count }}</p> <button @click="increment">Increment</button> </div> </template> <script setup> import { ref } from 'vue'; const count = ref(0); const increment = () => { count.value++; }; </script>
Vue 使用模板语法将 DOM 结构与 Vue 应用的数据绑定起来。模板语法包含插值、指令、条件渲染、列表渲染等。
<template> <div> <span>{{ count }}</span> <button @click="increment">Increment</button> </div> </template>
计算属性是基于其依赖的数据自动计算的属性。它们只有在相关依赖发生变化时才会重新计算。
computed: { doubleCount() { return this.count * 2; } }
方法则是普通函数,可以访问 this
上的数据。
methods: { increment() { this.count++; console.log(this.doubleCount); // 调用计算属性 } }
Vue 提供了一组生命周期钩子,允许我们在 Vue 实例的不同生命周期阶段进行操作。
created() { console.log('Component is created'); }, mounted() { console.log('Component is mounted'); },
使用 Vue CLI 创建一个简单的 Vue 项目:
vue create my-vue-app
一个典型的 Vue 项目结构如下:
my-vue-app/ │ ├── node_modules/ ├── public/ │ ├── index.html │ └── favicon.ico ├── src/ │ ├── assets/ │ ├── components/ │ ├── App.vue │ └── main.js ├── .gitignore ├── babel.config.js ├── package.json └── README.md
npm run serve
开发服务器将在 http://localhost:8080
上运行。
Vue 组件是可重用的 Vue 实例,每个组件都有自己的模板、样式和逻辑。
// Button.vue <template> <button @click="handleClick">{{ label }}</button> </template> <script> export default { props: ['label'], methods: { handleClick() { this.$emit('click'); } } } </script>
带复杂属性和事件的组件:
// MyComponent.vue <template> <div> <button @click="handleClick" :disabled="isDisabled">Click Me</button> <span>{{ message }}</span> </div> </template> <script> export default { props: { message: String, isDisabled: Boolean }, methods: { handleClick() { console.log('Button clicked'); } } } </script>
// App.vue <template> <div> <Button label="Click Me" @click="increment" /> <MyComponent message="Hello" :is-disabled="isDisabled" /> </div> </template> <script> import Button from './components/Button.vue'; import MyComponent from './components/MyComponent.vue'; export default { components: { Button, MyComponent }, setup() { const count = ref(0); const isDisabled = ref(false); const increment = () => { count.value++; }; return { count, increment, isDisabled }; } } </script>
// Parent.vue <template> <div> <Child :message="parentMessage" /> </div> </template> <script> import Child from './Child.vue'; export default { components: { Child }, setup() { const parentMessage = ref('Hello from Parent'); return { parentMessage }; } } </script>
// Child.vue <template> <div>{{ message }}</div> </template> <script> export default { props: ['message'] } </script>
// Child.vue <template> <div> <button @click="sendMessageToParent">Send Message</button> </div> </template> <script> export default { methods: { sendMessageToParent() { this.$emit('message-from-child', 'Hello from Child'); } } } </script>
// Parent.vue <template> <div> <Child @message-from-child="handleMessageFromChild" /> </div> </template> <script> import Child from './Child.vue'; export default { components: { Child }, setup() { const handleMessageFromChild = (message) => { console.log(message); // 输出 "Hello from Child" }; return { handleMessageFromChild }; } } </script>
CSS Modules 是一种局部作用域的 CSS,可以帮助解决 CSS 代码的全局污染问题。
/* Button.module.css */ .button { color: blue; }
// Button.vue <template> <button :class="$style.button">{{ label }}</button> </template> <script setup> import { ref } from 'vue'; import './Button.module.css'; </script> <style module> .button { color: green; } </style>
Vue 3 的响应式系统基于 Proxy
对象实现。通过 Proxy
对象,Vue 可以追踪数据的变化并触发视图更新。
import { reactive } from 'vue'; const state = reactive({ count: 0 });
state.count++;
ref
用于创建一个可变的引用,适用于基本类型值。
import { ref } from 'vue'; const count = ref(0);
reactive
用于创建一个响应式对象,适用于复杂的数据结构。
import { reactive } from 'vue'; const state = reactive({ count: 0, message: 'Hello Vue' });
import { ref, reactive } from 'vue'; const count = ref(0); // 基本类型值 const state = reactive({ count: 0, message: 'Hello Vue' }); // 对象
// Counter.vue <template> <div> <p>{{ count }}</p> <button @click="increment">Increment</button> </div> </template> <script setup> import { ref } from 'vue'; const count = ref(0); const increment = () => { count.value++; }; </script>
// ComplexCounter.vue <template> <div> <p>{{ count }}</p> <button @click="increment">Increment</button> <button @click="decrement">Decrement</button> </div> </template> <script setup> import { ref } from 'vue'; const count = ref(0); const increment = () => { count.value++; }; const decrement = () => { count.value--; }; </script>
Vue Router 是 Vue.js 的官方路由库,用于处理单页面应用的路由。
npm install vue-router@next
// main.js import { createRouter, createWebHistory } from 'vue-router'; import Home from './views/Home.vue'; import About from './views/About.vue'; const routes = [ { path: '/', component: Home }, { path: '/about', component: About } ]; const router = createRouter({ history: createWebHistory(), routes }); import { createApp } from 'vue'; import App from './App.vue'; createApp(App).use(router).mount('#app');
const routes = [ { path: '/', component: Home }, { path: '/about', component: About }, { path: '/user/:id', component: User } ];
<router-link to="/">Home</router-link> <router-link to="/about">About</router-link> <router-link :to="{ name: 'User', params: { id: 123 }}">User</router-link>
const routes = [ { path: '/user/:id', component: User } ];
<router-link :to="{ name: 'User', params: { id: 123 }}">User</router-link>
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
npm install vuex@next
// store.js import { createStore } from 'vuex'; export default createStore({ state: { count: 0 }, mutations: { increment(state) { state.count++; } }, actions: { increment({ commit }) { commit('increment'); } }, getters: { count(state) { return state.count; } } });
// main.js import { createApp } from 'vue'; import { createRouter, createWebHistory } from 'vue-router'; import App from './App.vue'; import store from './store'; const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', component: Home }, { path: '/about', component: About } ] }); createApp(App).use(router).use(store).mount('#app');
// Home.vue <template> <div> <p>{{ count }}</p> <button @click="increment">Increment</button> </div> </template> <script setup> import { computed } from 'vue'; import { useStore } from 'vuex'; const store = useStore(); const count = computed(() => store.state.count); const increment = () => store.dispatch('increment'); </script>
// store/modules/user.js export default { state: { name: 'John Doe' }, mutations: { setName(state, name) { state.name = name; } }, actions: { setName({ commit }, name) { commit('setName', name); } }, getters: { name(state) { return state.name; } } };
// store.js import { createStore } from 'vuex'; import userModule from './modules/user'; export default createStore({ modules: { user: userModule } });
// store/modules/user.js export default { state: { name: 'John Doe' }, mutations: { setName(state, name) { state.name = name; } }, actions: { async setName({ commit }) { const name = await fetchName(); commit('setName', name); } }, getters: { name(state) { return state.name; } } };
解决方法:使用 Vuex 状态管理库。
// store.js import { createStore } from 'vuex'; import userModule from './modules/user'; export default createStore({ modules: { user: userModule } });
解决方法:确保路由配置正确。
// main.js import { createRouter, createWebHistory } from 'vue-router'; import Home from './views/Home.vue'; import About from './views/About.vue'; const routes = [ { path: '/', component: Home }, { path: '/about', component: About } ]; const router = createRouter({ history: createWebHistory(), routes });
安装 GitHub Pages CLI
npm install -g github-pages
配置 package.json
"scripts": { "deploy": "gh-pages -d dist" }
构建项目
npm run build
部署
npm run deploy
安装 Vercel CLI
npm install -g vercel
部署项目
vercel