Vue3基础概念介绍
什么是Vue3
Vue.js 是一个渐进式前端框架,它允许你以渐进的方式将 Vue 添加到现有的项目中。Vue3 是 Vue.js 的最新版本,它引入了大量的改进,包括更好的性能、更小的打包体积、更易于调试的错误信息等。Vue3 采用了一种称为 Proxy
的 JavaScript 特性,用以替代 Vue2 中使用的基于 Object.defineProperty
的代理机制,从而实现了更高效的状态管理。
Vue3相对Vue2的主要改进
Vue3 相比 Vue2 的主要改进在以下几个方面:
-
更好的性能:Vue3 通过优化内部结构,可以更快地更新视图。特别是对于复杂组件,Vue3 可以减少不必要的 DOM 操作。
-
更小的打包体积:Vue3 的核心库体积更小,这意味着它在浏览器中的加载速度更快。这主要是因为 Vue3 对模板编译器进行了重构,减少了编译器的大小。
-
更好的工具支持:Vue3 提供了更详细的错误信息和警告,使得调试更为简单。同时,它也支持 TypeScript,这使得 Vue3 对于那些希望在开发过程中使用静态类型的人来说更加实用。
-
更好的兼容性:Vue3 兼容了更多的浏览器版本和 JavaScript 运行时环境,包括一些更现代的特性,如
Proxy
。 - Composition API:Vue3 引入了一个新的 API,称为 Composition API,它允许开发者更灵活地组织组件逻辑。Composition API 通过
ref
和reactive
提供一种声明性的方式来管理状态。
安装Vue3的开发环境
安装 Vue3 的开发环境,首先需要安装 Node.js。请确保你已经安装了 Node.js 的最新版本。接下来,你可以使用 Vue CLI 来搭建一个新的 Vue 项目。
步骤1:全局安装 Node.js
# 安装 Node.js
sudo apt update
sudo apt install nodejs
sudo apt install npm
步骤2:全局安装 Vue CLI
npm install -g @vue/cli
步骤3:创建一个新的 Vue 项目
vue create my-vue3-project
在创建项目的过程中,Vue CLI 会询问你一些关于项目配置的问题。选择一个预设或手动配置你的项目设置。选择 Vue 3 作为版本。
步骤4:启动开发服务器
创建完项目后,你可以在项目的根目录下运行以下命令来启动开发服务器:
npm run serve
这会启动一个本地开发服务器,你可以在浏览器中通过 http://localhost:8080
访问你的 Vue 应用。
使用Vue CLI快速搭建项目
Vue CLI 是一个命令行工具,可以用来快速搭建 Vue 项目。通过它,你可以轻松地创建一个新的 Vue 项目,并且可以很方便地进行配置和扩展。
步骤1:使用 Vue CLI 创建新项目
vue create my-vue3-project
在创建项目时,Vue CLI 会问你一些配置选项。如果你是新手,选择默认的设置即可。如果你对项目有特殊的要求,可以选择手动配置项目设置。
步骤2:选择 Vue 3 作为版本
在创建新项目时,Vue CLI 会询问你选择一个预设或手动选择特性。选择 Vue 3 作为版本,这样你就可以开始使用 Vue 3 的新特性了。
项目的基本结构与文件管理
一个 Vue 项目的基本结构如下:
my-vue3-project/
├── node_modules/
├── public/
│ └── index.html
├── src/
│ ├── assets/
│ ├── components/
│ ├── App.vue
│ └── main.js
├── .gitignore
├── babel.config.js
├── package.json
└── vue.config.js
node_modules/
:存放项目依赖的模块。public/
:存放静态文件,如index.html
。src/
:存放项目源代码。assets/
:存放静态资源,如图片、字体等。components/
:存放可复用的组件。App.vue
:应用的主组件。main.js
:应用的入口文件。
.gitignore
:定义 Git 托管代码时需要忽略的文件。babel.config.js
:Babel 配置文件,用于将 ES6+ 代码转译为兼容性更好的 JavaScript。package.json
:项目信息文件,包含版本号、依赖和脚本命令等。vue.config.js
:Vue CLI 的配置文件,可以自定义一些项目配置。
配置开发环境
在开始开发之前,你需要确保你的开发环境已经正确配置好。一般情况下,使用 Vue CLI 创建的项目已经为你配置好了基础的开发环境。例如,package.json
中包含了一些有用的脚本命令,例如:
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
}
}
这些命令分别用于启动开发服务器、构建生产环境代码和进行代码格式检查。
Vue3组件开发组件的基本使用方法
在 Vue 中,组件是构建应用的基本单元。每个组件通常包括一个模板、一个逻辑部分和一个样式部分。
创建组件
创建一个新的组件文件,例如 HelloWorld.vue
:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,
check out the
<a target="_blank" rel="noopener">vue-cli documentation</a>
</p>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<style scoped>
.hello {
background-color: #eee;
}
</style>
在这段代码中:
<template>
标签内的内容是组件的模板。<script>
标签内的内容是组件的逻辑代码,使用export default
导出一个对象,这个对象包含组件的配置信息。<style>
标签内的内容是组件的样式,使用scoped
属性来使样式仅作用于当前组件。
使用组件
在父组件中使用子组件:
<template>
<div id="app">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
这里,我们通过 import
语句导入 HelloWorld
组件,并在 components
选项中注册它。在模板中,我们使用 <HelloWorld>
标签来引用这个组件,并传递 msg
属性。
传递属性和插槽的使用
传递属性
在前面的例子中,我们已经看到了如何通过 props
来传递属性给子组件。这里再详细解释一下。
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: {
type: String,
required: true
}
}
}
</script>
这里,我们通过 props
选项来定义 msg
属性。type
属性指定了属性的类型,required
属性表示这个属性是必需的。
在父组件中使用:
<template>
<div id="app">
<HelloWorld msg="Hello from Parent"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
使用插槽
插槽允许你将父组件的内容传递给子组件,以实现细粒度且灵活的布局。默认插槽用于向组件模板中的指定位置插入内容,具名插槽则允许你向组件模板中的多个位置插入内容。
<template>
<div class="hello">
<slot name="header"></slot>
<h1>Hello from {{ name }}</h1>
<slot name="footer"></slot>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
name: String
}
}
</script>
在父组件中使用:
<template>
<div id="app">
<HelloWorld name="Vue3">
<template v-slot:header>
<h2>Header</h2>
</template>
<template v-slot:footer>
<p>Footer</p>
</template>
</HelloWorld>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
组件之间的通信
组件之间的通信主要包括父组件向子组件传递数据(通过 props
)和子组件向父组件传递数据(通过 事件
)。
父组件向子组件传递数据
通过 props
,父组件可以向子组件传递数据。上文已经展示了如何通过 props
传递字符串类型的属性,下面展示如何传递对象或数组类型的属性。
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>{{ user.name }} is {{ user.age }} years old.</p>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String,
user: Object
}
}
</script>
在父组件中使用:
<template>
<div id="app">
<HelloWorld
msg="Hello from Parent"
:user="{ name: 'John Doe', age: 30 }"
/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
子组件向父组件传递数据
子组件可以通过 $emit
方法向父组件发送事件,父组件可以通过 v-on
指令监听这些事件。
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<button @click="sendDataToParent">Send Data</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
methods: {
sendDataToParent() {
this.$emit('data-sent', 'Hello from Child')
}
}
}
</script>
在父组件中使用:
<template>
<div id="app">
<HelloWorld
msg="Hello from Parent"
@data-sent="handleDataFromChild"
/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
},
methods: {
handleDataFromChild(data) {
console.log(data)
}
}
}
</script>
Vue3响应式原理与实践
响应式系统的原理
Vue3 使用了 Proxy
对象来实现响应式系统,Proxy
是 ES6 引入的一种新的语言特性,它允许你创建一个对象的代理,并在访问或修改对象属性时拦截并处理这些操作。通过 Proxy
,Vue3 能够在属性被访问或修改时自动触发视图更新。
数据劫持
在 Vue3 中,响应式数据通常通过 ref
和 reactive
函数来创建。ref
用于创建一个带有 .value
属性的可变引用,而 reactive
则用于直接创建一个响应式对象。
import { ref, reactive } from 'vue'
const count = ref(0)
const state = reactive({
count: 0
})
console.log(count.value) // 输出 0
console.log(state.count) // 输出 0
count.value++
state.count++
console.log(count.value) // 输出 1
console.log(state.count) // 输出 1
计算属性
计算属性是基于组件内的数据进行计算,并随时响应变化的数据。计算属性和普通方法的主要区别在于计算属性会基于其依赖缓存,只有依赖发生改变时才会重新计算。
<template>
<div>
<p>Count: {{ count }}</p>
<p>Double Count: {{ doubleCount }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
import { ref, computed } from 'vue'
export default {
setup() {
const count = ref(0)
const doubleCount = computed(() => {
return count.value * 2
})
const increment = () => {
count.value++
}
return {
count,
doubleCount,
increment
}
}
}
</script>
常见的响应式编程技巧
使用 watch
监听数据变化
watch
可以用来监听一个响应式数据的变化。每当被监听的数据发生变化时,watch
会触发回调函数。
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
import { ref, watch } from 'vue'
export default {
setup() {
const count = ref(0)
watch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`)
})
const increment = () => {
count.value++
}
return {
count,
increment
}
}
}
</script>
使用 computed
缓存计算结果
计算属性会缓存计算结果,只有在依赖的数据发生变化时才会重新计算。这可以避免不必要的重复计算,提高性能。
<template>
<div>
<p>Original Value: {{ originalValue }}</p>
<p>Computed Value: {{ computedValue }}</p>
</div>
</template>
<script>
import { ref, computed } from 'vue'
export default {
setup() {
const originalValue = ref('Hello')
const computedValue = computed(() => {
return originalValue.value.toUpperCase()
})
return {
originalValue,
computedValue
}
}
}
</script>
监听器的使用
在某些情况下,你可能需要监听更复杂的状态变化,例如数组或对象的嵌套属性。Vue3 提供了 watch
和 watchEffect
两种方式来实现这一点。
使用 watch
如果你需要监听一个具体的属性变化,可以使用 watch
。
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
import { ref, watch } from 'vue'
export default {
setup() {
const count = ref(0)
watch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`)
})
const increment = () => {
count.value++
}
return {
count,
increment
}
}
}
</script>
使用 watchEffect
如果你需要监听多个属性的变化,或者需要在监听器中执行一些复杂的逻辑,可以使用 watchEffect
。
<template>
<div>
<p>Count: {{ count }}</p>
<p>Double Count: {{ doubleCount }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
import { ref, watchEffect } from 'vue'
export default {
setup() {
const count = ref(0)
watchEffect(() => {
console.log(`Count is now ${count.value}`)
console.log(`Double count is now ${count.value * 2}`)
})
const increment = () => {
count.value++
}
return {
count,
increment
}
}
}
</script>
路由与状态管理
Vue Router基础配置
Vue Router 是 Vue.js 官方的路由管理器,用于实现基于 URL 的路由功能。你可以通过它来控制浏览器地址栏中的 URL,并根据不同的路由显示不同的组件。
安装 Vue Router
首先,你需要安装 Vue Router:
npm install vue-router@next
配置 Vue Router
创建一个新的文件 router/index.js
,配置 Vue Router:
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(process.env.BASE_URL),
routes
})
export default router
在主文件 main.js
中,引入并使用 Vue Router:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
在 App.vue
中使用 <router-view>
标签来显示当前路由对应的组件:
<template>
<router-view></router-view>
</template>
<script>
import { createApp } from 'vue'
import router from './router'
export default {
name: 'App',
setup() {
createApp(App).use(router).mount('#app')
}
}
</script>
Vuex的状态管理模式
Vuex 是 Vue.js 的官方状态管理库,它可以帮助你更好地管理应用的状态。使用 Vuex 可以让你的应用更容易进行调试,也更容易进行测试和状态管理。
安装 Vuex
安装 Vuex:
npm install vuex@next
配置 Vuex
创建一个新的文件 store/index.js
,配置 Vuex:
import { createStore } from 'vuex'
export default createStore({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
increment({ commit }) {
commit('increment')
}
},
getters: {
doubleCount: (state) => {
return state.count * 2
}
}
})
在主文件 main.js
中,引入并使用 Vuex:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(router).use(store).mount('#app')
在组件中使用 Vuex:
<template>
<div>
<p>Count: {{ count }}</p>
<p>Double Count: {{ doubleCount }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore()
const count = computed(() => store.state.count)
const doubleCount = computed(() => store.getters.doubleCount)
const increment = () => {
store.dispatch('increment')
}
return {
count,
doubleCount,
increment
}
}
}
</script>
状态管理的基本使用
在 Vuex 中,可以通过 state
来存储应用的状态,通过 mutations
来修改状态,通过 actions
来异步地修改状态,通过 getters
来获取状态。
使用 state
state
是一个对象,用于存储应用的状态。你可以通过 state
来获取当前的状态。
const store = createStore({
state: {
count: 0
}
})
使用 mutations
mutations
是一个方法集合,用来修改 state
。每个 mutation
有一个类型(通常是字符串),对应一个处理函数。
const store = createStore({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
}
})
使用 actions
actions
是一个方法集合,用来异步地修改 state
。actions
可以使用 commit
方法来触发 mutations
。
const store = createStore({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
increment({ commit }) {
commit('increment')
}
}
})
使用 getters
getters
是一个方法集合,用来获取 state
。getters
的返回值会基于其依赖缓存,只有依赖发生变化时才会重新计算。
const store = createStore({
state: {
count: 0
},
getters: {
doubleCount: (state) => {
return state.count * 2
}
}
})
实战项目案例
小项目实战
我们将通过一个简单的待办事项应用(To-Do List)来展示如何使用 Vue3、Vue Router 和 Vuex 来构建一个完整的应用。
项目结构
my-todo-app/
├── node_modules/
├── public/
│ └── index.html
├── src/
│ ├── assets/
│ ├── components/
│ │ ├── AddTodo.vue
│ │ ├── TodoList.vue
│ ├── views/
│ │ ├── Home.vue
│ │ ├── About.vue
│ ├── App.vue
│ ├── main.js
│ ├── router/
│ │ └── index.js
│ ├── store/
│ │ └── index.js
├── .gitignore
├── babel.config.js
├── package.json
└── vue.config.js
创建组件
创建 AddTodo.vue
组件用于添加新的待办事项:
<template>
<div class="add-todo">
<input v-model="newTodo" @keyup.enter="addTodo" placeholder="Add a new todo" />
</div>
</template>
<script>
export default {
data() {
return {
newTodo: ''
}
},
methods: {
addTodo() {
if (this.newTodo) {
this.$store.dispatch('addTodo', this.newTodo)
this.newTodo = ''
}
}
}
}
</script>
<style scoped>
.add-todo {
margin-bottom: 20px;
}
</style>
创建 TodoList.vue
组件用于显示待办事项列表:
<template>
<ul>
<li v-for="(todo, index) in todos" :key="index">
{{ todo }}
<button @click="removeTodo(index)">Remove</button>
</li>
</ul>
</template>
<script>
export default {
computed: {
todos() {
return this.$store.state.todos
}
},
methods: {
removeTodo(index) {
this.$store.dispatch('removeTodo', index)
}
}
}
</script>
<style scoped>
ul {
list-style-type: none;
padding: 0;
}
li {
margin: 10px 0;
}
</style>
创建路由
在 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(process.env.BASE_URL),
routes
})
export default router
创建 Vuex Store
在 store/index.js
中配置 Vuex:
import { createStore } from 'vuex'
export default createStore({
state: {
todos: []
},
mutations: {
addTodo(state, todo) {
state.todos.push(todo)
},
removeTodo(state, index) {
state.todos.splice(index, 1)
}
},
actions: {
addTodo({ commit }, todo) {
commit('addTodo', todo)
},
removeTodo({ commit }, index) {
commit('removeTodo', index)
}
},
getters: {
todos: (state) => {
return state.todos
}
}
})
创建视图组件
创建 views/Home.vue
组件:
<template>
<div>
<h1>Home</h1>
<AddTodo />
<TodoList />
</div>
</template>
<script>
import AddTodo from '../components/AddTodo.vue'
import TodoList from '../components/TodoList.vue'
export default {
components: {
AddTodo,
TodoList
}
}
</script>
创建 views/About.vue
组件:
<template>
<div>
<h1>About</h1>
</div>
</template>
创建主应用组件
在 App.vue
中使用 <router-view>
来显示当前路由组件:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
import { createApp } from 'vue'
import router from './router'
import store from './store'
export default {
name: 'App',
setup() {
createApp(App).use(router).use(store).mount('#app')
}
}
</script>
创建主文件
在 main.js
中引入并使用 Vue Router 和 Vuex:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(router).use(store).mount('#app')
代码优化与调试
在开发过程中,可以通过一些方法来优化代码和调试问题。
代码优化
- 减少重复代码:通过抽象和重用组件来减少重复代码。
- 优化性能:避免不必要的 DOM 操作和计算,使用
v-once
或者v-cache
减少不必要的渲染。 - 使用 TypeScript:使用 TypeScript 可以帮助你更好地管理代码结构和类型。
调试
- 使用 Vue Devtools:Vue Devtools 是一个浏览器插件,可以用来调试 Vue 应用。它提供了许多有用的工具,如检查组件树、查看状态等。
- 使用 console.log:通过
console.log
了解组件的状态变化和数据流动。 - 使用 Vue CLI 的调试模式:在开发环境下使用
npm run serve
启动服务器,Vue CLI 会提供详细的错误信息和警告。
项目部署与上线
在开发完成后,可以通过以下步骤来部署和上线你的项目。
构建生产环境代码
首先,你需要构建生产环境的代码。在项目根目录下运行以下命令:
npm run build
这会生成一个 dist
目录,其中包含了所有生产环境下需要的文件。
部署到服务器
将 dist
目录下的所有文件上传到你的服务器。你可以使用 FTP、SFTP 或其他文件传输工具来完成这一步。
配置服务器
确保服务器上的 Web 服务器(如 Nginx 或 Apache)已经正确配置,可以服务静态文件。
例如,如果你使用 Nginx,可以创建一个配置文件 my-todo-app.conf
:
server {
listen 80;
server_name yourdomain.com;
location / {
root /path/to/dist;
try_files $uri /index.html;
}
}
然后将这个配置文件添加到 Nginx 的配置中,并重启 Nginx 服务:
sudo ln -s /path/to/my-todo-app.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
完成这些步骤后,你的应用就可以通过服务器的域名访问了。
共同學習,寫下你的評論
評論加載中...
作者其他優質文章