本文全面介绍了Vue3的核心特性和开发实践,包括Vue3的新特性和与Vue2的区别,安装与配置Vue3项目的方法,以及组件化开发、响应式原理、生命周期钩子、路由与状态管理等。此外,还通过一个简单的待办事项应用案例演示了Vue3的实际应用。适合不同层次的学习者。
Vue3基础介绍
Vue3简介
Vue.js 是一个用于构建用户界面的渐进式框架。Vue3是Vue.js的最新版本,它在Vue2的基础上引入了一些新的特性和改进,以提高性能和开发体验。Vue3的核心特性包括Composition API、TypeScript支持增强、更小的体积、更好的TypeScript支持、非侵入性的依赖注入,以及更高效的渲染等。这些改进使得Vue3成为了构建现代Web应用的理想选择。
Vue3与Vue2的区别
Vue3与Vue2相比,有以下几个主要区别:
-
响应式系统:Vue3采用了Proxy来替代Object.defineProperty作为响应式系统的基础。这使得响应式数据的变更更为高效,并支持了对数组和对象原生方法的响应。
比如,在Vue2中,以下代码会触发重新渲染:
// Vue2 const state = {} Object.defineProperty(state, 'count', { get() { return this._count; }, set(value) { this._count = value; console.log('count changed'); } }); state.count = 1;
在Vue3中,使用Proxy:
// Vue3 const state = new Proxy({}, { set(target, key, value) { console.log(`${key} changed to ${value}`); target[key] = value; return true; } }); state.count = 1;
-
Composition API:Vue3引入了Composition API,这是一个更灵活的API,允许开发者更明确地组织和重用组件逻辑。Composition API提供了
setup()
函数,它在组件的生命周期中可以访问组件的属性和生命周期钩子。比如,在Vue2中,组件逻辑分散在各个生命周期钩子中:
// Vue2 export default { data() { return { message: 'Hello Vue2' }; }, methods: { sayHello() { console.log(this.message); } } };
在Vue3中,使用Composition API:
// Vue3 import { ref } from 'vue'; export default { setup() { const message = ref('Hello Vue3'); const sayHello = () => { console.log(message.value); }; return { message, sayHello }; } };
-
Teleport API:Vue3引入了Teleport API,这使得组件的内容可以在DOM树的任意位置渲染,而不仅仅限于其父节点。
比如,使用Teleport API:
<teleport to="body"> <div>Content rendered in body</div> </teleport>
-
Fragments:Vue3支持Fragments,即一个组件可以返回多个根节点。
比如,Vue3中可以这样返回多个根节点:
<template> <div> <p>Paragraph 1</p> <p>Paragraph 2</p> </div> </template>
-
更好的TypeScript支持:Vue3的TypeScript支持有所增强,提供了更好的类型推断和更好的工具支持。
-
更高的性能:Vue3的渲染性能有了显著的提升,特别是在虚拟DOM优化和事件委托方面。
-
Element Update Tracker:改进的依赖跟踪系统,提高了模板解析的效率。
- Tree-shaking支持:Vue3优化了Tree-shaking的支持,使得未使用的代码可以被完全移除,从而减小了打包后的体积。
安装与配置Vue3项目
安装Vue3
安装Vue3最简单的方法是使用Vue CLI。首先,确保你已经安装了Node.js和npm。然后,可以通过以下命令全局安装Vue CLI:
npm install -g @vue/cli
安装完Vue CLI后,你可以创建一个新的Vue3项目:
vue create my-vue3-app
在创建项目时,选择Vue 3.0预设,或者在项目设置中手动选择Vue版本为3.0。
配置项目
进入项目目录并安装依赖:
cd my-vue3-app
npm install
运行开发服务器:
npm run serve
这将启动开发服务器,并在默认浏览器中打开项目。此时,你可以开始在项目中进行开发。
Vue3组件化开发
组件的基本概念
Vue组件是可复用的Vue实例,通过组合组件可以构建出复杂的界面。组件可以有自己的数据、事件处理、生命周期等。Vue组件的定义通常包括template、script、style这三个部分,分别定义了组件的结构、逻辑和样式。
创建与使用组件
创建Vue组件的基本步骤如下:
-
定义组件:在Vue中定义一个组件,通常需要通过一个Vue的工厂函数,或者使用Composition API中的
defineComponent
。 - 注册组件:在Vue应用中注册组件,可以通过全局注册或局部注册两种方式。
示例代码
使用defineComponent
创建组件
import { defineComponent } from 'vue'
export default defineComponent({
name: 'HelloWorld',
props: {
msg: String
},
setup(props) {
return () => {
return <div>{props.msg}</div>
}
}
})
在父组件中使用
import HelloWorld from './components/HelloWorld.vue'
export default {
components: {
HelloWorld
},
setup() {
return {
message: 'Hello from parent'
}
}
}
在模板中使用
<template>
<div id="app">
<HelloWorld :msg="message" />
</div>
</template>
属性与事件的传递
在父组件和子组件之间传递数据是组件化开发的关键。父组件可以通过属性(props)向子组件传递数据,而子组件则可以通过事件(events)向父组件发送数据。
属性传递
父组件可以通过属性向子组件传递数据:
<template>
<div>
<ChildComponent :message="parentMessage" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
setup() {
return {
parentMessage: 'Hello from parent'
}
}
}
</script>
事件传递
子组件可以通过自定义事件向父组件发送数据:
// ChildComponent.vue
<template>
<div>
<button @click="sendData">Click me</button>
</div>
</template>
<script>
export default {
props: {
message: String
},
methods: {
sendData() {
this.$emit('child-event', 'Hello from child')
}
}
}
</script>
<!-- ParentComponent.vue -->
<template>
<div>
<ChildComponent @child-event="handleChildEvent" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
setup() {
const handleChildEvent = (msg) => {
console.log(msg)
}
return {
handleChildEvent
}
}
}
</script>
Vue3响应式原理
响应式系统概述
Vue3的响应式系统是基于ES6的Proxy对象构建的。与Vue2相比,Vue3的响应式依赖于Proxy可以更高效地追踪数据变化,支持对数组和对象原生方法的响应。此外,Vue3还优化了依赖跟踪的算法,使得在大规模数据变化时有更好的性能表现。
-
在Vue2中,Vue使用
Object.defineProperty
实现响应式。比如:const state = {} Object.defineProperty(state, 'count', { get() { return this._count; }, set(value) { this._count = value; console.log('count changed'); } }); state.count = 1;
- 在Vue3中,使用Proxy实现响应式:
const state = new Proxy({}, { set(target, key, value) { target[key] = value; console.log(`${key} changed to ${value}`); return true; } }); state.count = 1;
ref与reactive的使用
Vue3提供了两种主要的响应式数据定义方式:ref
和reactive
。这两种方式各有特点,根据具体场景选择合适的方式可以提高开发效率和性能。
-
ref
:用于包装基本值类型(如number
和string
),返回一个可变的Ref
对象,可以通过.value
访问或修改值。 reactive
:用于包装对象,返回一个与原对象结构一致的响应式对象,可以直接访问对象属性。
示例代码
import { ref, reactive } from 'vue'
const countRef = ref(0)
const countReactive = reactive({ count: 0 })
console.log(countRef.value) // 输出:0
console.log(countReactive.count) // 输出:0
countRef.value++
countReactive.count++
console.log(countRef.value) // 输出:1
console.log(countReactive.count) // 输出:1
响应式数据的监听与修改
Vue3提供了watch
和computed
两个函数来监听响应式数据的变化和创建计算属性。
-
watch
:用于监听响应式数据的变化,并在数据变化时执行回调函数。 computed
:用于创建计算属性,根据依赖的响应式数据计算新的值。
示例代码
import { ref, watch, computed } from 'vue'
const count = ref(0)
watch(() => count.value, (newVal, oldVal) => {
console.log(`count changed from ${oldVal} to ${newVal}`)
})
const doubleCount = computed(() => {
return count.value * 2
})
console.log(doubleCount.value) // 输出:0
count.value++
console.log(doubleCount.value) // 输出:2
Vue3生命周期钩子
生命周期钩子概述
Vue组件的生命周期指的是组件从创建到销毁的整个过程中的各个阶段。每个阶段都有对应的生命周期钩子,开发者可以在这些钩子中执行特定的逻辑。Vue3的生命周期钩子与Vue2相比有一些变化,但核心概念依然保持一致。
常用生命周期钩子的使用
以下是一些常用的生命周期钩子及其用途:
-
beforeCreate:在实例初始化之前,即数据观测 (data observer) 和事件配置 (event configuration) 之前被调用。
-
created:在实例创建完成后被调用。此时实例已完成数据观测 (data observer) 和事件配置 (event configuration) 。
-
beforeMount:在挂载开始之前被调用。此时,组件实例的
$el
属性还不存在。 -
mounted:在组件挂载完成后被调用。此时,组件已插入DOM中。
-
beforeUnmount:在卸载组件实例之前被调用。此时,组件实例还存在,但已经从DOM中移除。
- unmounted:在组件实例卸载后被调用。此时,组件实例已不存在。
示例代码
import { ref, onBeforeMount, onMounted, onBeforeUnmount, onUnmounted } from 'vue'
export default {
setup() {
const message = ref('Hello, Vue3!')
onBeforeMount(() => {
console.log('beforeMount')
})
onMounted(() => {
console.log('mounted')
})
onBeforeUnmount(() => {
console.log('beforeUnmount')
})
onUnmounted(() => {
console.log('unmounted')
})
return {
message
}
}
}
生命周期钩子的应用场景
生命周期钩子可以用于执行组件挂载后的初始化操作、数据异步加载、DOM操作等。例如,可以在mounted
钩子中执行网络请求、DOM操作等。
示例代码
import { ref, onMounted } from 'vue'
export default {
setup() {
const message = ref('Loading...')
onMounted(() => {
fetch('/api/data')
.then(response => response.json())
.then(data => {
message.value = data.message
})
})
return {
message
}
}
}
Vue3路由与状态管理
Vue Router的基本使用
Vue Router是Vue.js的官方路由管理器,它可以让应用实现基于URL的路由管理。路由配置由一个路由表定义,每个路由条目包含一个路径和对应的组件。
简单配置
// router/index.js
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
import Home from './views/Home.vue'
import About from './views/About.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
})
export default router
路由导航
可以在组件中使用router-link
和router-view
来导航到不同路由。
<template>
<div>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
<router-view></router-view>
</div>
</template>
``
### Vuex的基本概念与使用
Vuex是Vue.js的状态管理库,它提供了一个集中式存储用于管理应用的所有组件中的状态。Vuex的状态以单一状态树的形式存在,每个组件可以通过`store`实例访问和更新这个状态树。
#### 安装Vuex
```bash
npm install vuex@next --save
基本使用
// store/index.js
import { createStore } from 'vuex'
export default createStore({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
increment({ commit }) {
commit('increment')
}
},
getters: {
doubleCount: state => state.count * 2
}
})
<!-- App.vue -->
<template>
<div>
<button @click="increment">Increment</button>
{{ count }}
{{ doubleCount }}
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
setup() {
const { count, doubleCount } = mapGetters(['count', 'doubleCount'])
const { increment } = mapActions(['increment'])
return {
count,
doubleCount,
increment
}
}
}
</script>
``
### 路由与状态管理的实际案例
假设我们正在开发一个简单的博客应用,其中包括文章列表和文章详情页。我们可以使用Vue Router实现导航,使用Vuex管理应用状态。
#### 路由配置
```js
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from './views/Home.vue'
import Article from './views/Article.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Home },
{ path: '/article/:id', component: Article }
]
})
export default router
Vuex状态管理
// store/index.js
import { createStore } from 'vuex'
export default createStore({
state: {
articles: []
},
mutations: {
setArticles(state, articles) {
state.articles = articles
}
},
actions: {
fetchArticles({ commit }) {
return fetch('/api/articles')
.then(response => response.json())
.then(articles => commit('setArticles', articles))
}
},
getters: {
articles: state => state.articles,
findArticleById: state => id => state.articles.find(article => article.id === id)
}
})
在组件中使用
<!-- Home.vue -->
<template>
<div>
<ul>
<li v-for="article in articles" :key="article.id">
<router-link :to="{ name: 'Article', params: { id: article.id } }">
{{ article.title }}
</router-link>
</li>
</ul>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
setup() {
const { articles, fetchArticles } = mapActions(['articles', 'fetchArticles'])
onMounted(() => {
fetchArticles()
})
return {
articles
}
}
}
</script>
<!-- Article.vue -->
<template>
<div>
<h1>{{ article.title }}</h1>
<p>{{ article.content }}</p>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
setup() {
const { findArticleById } = mapGetters(['findArticleById'])
const route = useRoute()
const article = computed(() => findArticleById(route.params.id))
return {
article
}
}
}
</script>
Vue3项目实战
小项目案例分析
我们将构建一个简单的待办事项(Todo List)应用,该应用允许用户添加、删除和标记待办事项。我们将使用Vue3的基本特性,包括组件化、路由和状态管理。
项目结构
- src
- components
- TodoItem.vue
- TodoList.vue
- AddTodo.vue
- views
- Home.vue
- router
- index.js
- store
- index.js
- main.js
- App.vue
项目实战步骤详解
-
项目初始化
- 使用Vue CLI创建一个新的Vue3项目。
- 安装Vue Router和Vuex。
-
组件开发
- 创建
TodoItem
组件,用于显示单个待办事项。 - 创建
TodoList
组件,用于显示所有待办事项。 - 创建
AddTodo
组件,用于添加新的待办事项。
- 创建
-
路由配置
- 配置Vue Router,让应用可以导航到不同的视图。
-
状态管理
- 使用Vuex管理应用的状态,包括待办事项列表。
- 在组件中使用Vuex来添加、删除和标记待办事项。
- 页面开发
- 创建
Home
视图,显示待办事项列表和添加新待办事项的界面。
- 创建
示例代码
初始化项目
vue create todo-app
cd todo-app
npm install vue-router@next vuex@next
创建TodoItem
组件
<!-- src/components/TodoItem.vue -->
<template>
<li>
<input type="checkbox" v-model="checked" />
<span :class="{ completed: checked }">{{ todo.title }}</span>
<button @click="deleteTodo">Delete</button>
</li>
</template>
<script>
export default {
props: {
todo: Object
},
data() {
return {
checked: this.todo.completed
}
},
methods: {
deleteTodo() {
this.$emit('delete', this.todo.id)
}
}
}
</script>
<style>
.completed {
text-decoration: line-through;
}
</style>
创建TodoList
组件
<!-- src/components/TodoList.vue -->
<template>
<ul>
<TodoItem v-for="todo in todos" :key="todo.id" :todo="todo" @delete="deleteTodo" />
</ul>
</template>
<script>
import TodoItem from './TodoItem.vue'
export default {
props: {
todos: Array
},
methods: {
deleteTodo(id) {
this.$emit('delete', id)
}
}
}
</script>
创建AddTodo
组件
<!-- src/components/AddTodo.vue -->
<template>
<form @submit.prevent="addTodo">
<input v-model="newTodo" placeholder="Add a new todo" />
<button type="submit">Add</button>
</form>
</template>
<script>
export default {
data() {
return {
newTodo: ''
}
},
methods: {
addTodo() {
this.$emit('add', this.newTodo)
this.newTodo = ''
}
}
}
</script>
配置路由
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Home }
]
})
export default router
配置Vuex
// src/store/index.js
import { createStore } from 'vuex'
export default createStore({
state: {
todos: []
},
mutations: {
addTodo(state, todo) {
state.todos.push(todo)
},
deleteTodo(state, id) {
state.todos = state.todos.filter(todo => todo.id !== id)
},
toggleTodo(state, id) {
const todo = state.todos.find(todo => todo.id === id)
if (todo) {
todo.completed = !todo.completed
}
}
},
actions: {
addTodo({ commit }, todo) {
commit('addTodo', todo)
},
deleteTodo({ commit }, id) {
commit('deleteTodo', id)
},
toggleTodo({ commit }, id) {
commit('toggleTodo', id)
}
},
getters: {
todos: state => state.todos
}
})
创建Home
视图
<!-- src/views/Home.vue -->
<template>
<div>
<AddTodo @add="addTodo" />
<TodoList :todos="todos" @delete="deleteTodo" />
</div>
</template>
<script>
import { computed, onMounted } from 'vue'
import { useStore } from 'vuex'
import AddTodo from '../components/AddTodo.vue'
import TodoList from '../components/TodoList.vue'
export default {
components: {
AddTodo,
TodoList
},
setup() {
const store = useStore()
const todos = computed(() => store.getters.todos)
const addTodo = (todo) => {
store.dispatch('addTodo', { id: Date.now(), title: todo, completed: false })
}
const deleteTodo = (id) => {
store.dispatch('deleteTodo', id)
}
onMounted(() => {
store.dispatch('fetchTodos')
})
return {
todos,
addTodo,
deleteTodo
}
}
}
</script>
``
### 项目部署与上线
#### 打包应用
```bash
npm run build
打包后会在dist
目录下生成静态文件,可以将这些文件部署到任何静态文件服务器上。
部署到服务器
-
安装Web服务器
- 对于开发环境,可以使用简单的Web服务器如http-server。
- 对于生产环境,推荐使用Nginx或Apache等成熟的Web服务器。
- 部署静态文件
- 将
dist
目录中的文件复制到Web服务器的根目录。
- 将
示例代码
# 使用http-server
npm install -g http-server
cd dist
http-server
``
通过上述步骤,你可以成功构建一个简单的待办事项应用,并将其部署到服务器上。这不仅是一个完整的Vue3项目实战,也是一个良好的学习案例,可以让你更好地理解Vue3的各项特性。
共同学习,写下你的评论
评论加载中...
作者其他优质文章