官网:vuejs.org/
1. 项目搭建
使用 Vite 或 Vue CLI 来创建 Vue 3 项目。以 Vite 为例,在命令行执行以下命令:
perl
npm init vite@latest my-vue-app -- --template vue
cd my-vue-app
npm install
npm run dev
2. 组合式 API
Vue 3 引入了组合式 API,它能让你更灵活地组织代码。
2.1 setup
函数
setup
函数是组合式 API 的入口,在组件创建之前执行。
xml
<template>
<div>{{ message }}</div>
</template>
<script setup>
import { ref } from 'vue';
const message = ref('Hello, Vue 3!');
</script>
2.2 ref
和 reactive
ref
用于创建响应式的基本类型数据。reactive
用于创建响应式的对象或数组。
xml
<template>
<div>
<p>{{ count }}</p>
<p>{{ user.name }}</p>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
const count = ref(0);
const user = reactive({ name: 'John' });
</script>
2.3 生命周期钩子
在 setup
函数中使用生命周期钩子,需要从 vue
导入相应的函数。
xml
<template>
<div></div>
</template>
<script setup>
import { onMounted } from 'vue';
onMounted(() => {
console.log('Component is mounted');
});
</script>
生命周期阶段与函数
- 创建阶段
-
beforeCreate
- 这是实例初始化之后,数据观测 (
data observer
) 和event/watcher
事件配置之前被调用。此时,data
和methods
等属性都还未初始化,不能访问它们。 - 示例代码:
- 这是实例初始化之后,数据观测 (
javascript
new Vue({
beforeCreate() {
console.log('实例初始化,data 和 methods 未初始化');
}
});
-
created
- 实例已经创建完成之后被调用。在这一步,实例已经完成了数据观测 (
data observer
)、property
和method
的计算、watch/event
事件回调的配置等。然而,挂载阶段还没有开始,$el
属性目前不可用。 - 示例代码:
- 实例已经创建完成之后被调用。在这一步,实例已经完成了数据观测 (
javascript
new Vue({
data() {
return {
message: 'Hello Vue!'
};
},
created() {
console.log(this.message); // 可以访问 data 中的属性
}
});
- 挂载阶段
-
beforeMount
- 在挂载开始之前被调用:相关的
render
函数首次被调用。此时模板已经编译完成,但还未挂载到页面上,$el
还是虚拟 DOM。 - 示例代码:
- 在挂载开始之前被调用:相关的
javascript
new Vue({
template: '<div>{{ message }}</div>',
data() {
return {
message: 'Hello Vue!'
};
},
beforeMount() {
console.log('模板编译完成,但未挂载到页面');
}
});
-
mounted
el
被新创建的vm.$el
替换,并挂载到实例上去之后调用该钩子。此时,Vue 实例已经将模板渲染到页面上,可以进行 DOM 操作。- 示例代码:
javascript
new Vue({
template: '<div id="app">{{ message }}</div>',
data() {
return {
message: 'Hello Vue!'
};
},
mounted() {
console.log(this.$el.textContent); // 可以访问渲染后的 DOM 内容
}
}).$mount('#app');
- 更新阶段
-
beforeUpdate
- 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在数据更新前访问现有的 DOM,比如手动移除已添加的事件监听器。
- 示例代码:
javascript
new Vue({
data() {
return {
count: 0
};
},
beforeUpdate() {
console.log('数据即将更新,DOM 还未更新');
}
});
-
updated
- 由于数据更改导致的虚拟 DOM 重新渲染和打补丁之后调用。调用时,组件 DOM 已经更新,所以可以执行依赖于 DOM 的操作。不过要注意避免在此期间更改数据,否则可能导致无限循环更新。
- 示例代码:
javascript
new Vue({
data() {
return {
count: 0
};
},
updated() {
console.log('数据更新完成,DOM 已更新');
}
});
- 销毁阶段
-
beforeDestroy
- 实例销毁之前调用。在这一步,实例仍然完全可用,
data
、methods
、watch
、event
等都还可以正常使用。通常用于解绑自定义事件、清除定时器等操作。 - 示例代码:
- 实例销毁之前调用。在这一步,实例仍然完全可用,
javascript
new Vue({
data() {
return {
timer: null
};
},
created() {
this.timer = setInterval(() => {
console.log('定时器运行中');
}, 1000);
},
beforeDestroy() {
clearInterval(this.timer); // 清除定时器
console.log('实例即将销毁');
}
});
-
destroyed
- 实例已经完全销毁之后调用。所有的事件监听器和子实例也已经被销毁。此时实例已经无法再使用。
- 示例代码:
javascript
new Vue({
destroyed() {
console.log('实例已销毁');
}
});
3. 组件通信
3.1 父传子
父组件通过属性向子组件传递数据。
xml
<!-- 父组件 -->
<script setup>
import Header from './components/header.vue'
</script>
<template>
<Header propsName="tom"/>
</template>
<style scoped>
</style>
<!-- 子组件 -->
<script setup>
const props = defineProps(["propsName"]);
console.log(props);
</script>
<template>
<h2>Header</h2>
</template>
<style scoped>
</style>
3.2 子传父
子组件通过触发自定义事件向父组件传递数据。
xml
<!-- 子组件 -->
<script setup>
//子组件向父组件传递数据,使用宏函数
//参数是数组,数组里的元素是会触发自定义事件的名称
const emits = defineEmits(["getStudent"])
emits("getStudent", {name:"mary", age:10});
</script>
<template>
<h2>Header</h2>
</template>
<style scoped>
</style>
<!-- 父组件 -->
<script setup>
import Header from './components/header.vue'
import Footer from './components/footer.vue'
import {reactive} from "vue";
//响应式数据
const student = reactive({
name: 'tom',
age: 18
})
const emitGetStudent = (name, age) => {
student.name = name
student.age = age
}
</script>
<template>
<Header @getStudent="emitGetStudent"/>
{{student.name}}-{{student.age}}
</template>
<style scoped>
</style>
4. 路由管理
使用 vue-router
进行路由管理。
4.1 安装
css
npm install vue-router@4
4.2 配置路由
javascript
// 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(),
routes
});
export default router;
4.3 在主应用中使用路由
javascript
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
app.use(router);
app.mount('#app');
5. 状态管理
使用 Pinia
进行状态管理。
5.1 安装
npm install pinia
5.2 创建 store
javascript
// stores/counter.js
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
actions: {
increment() {
this.count++;
}
}
});
5.3 在组件中使用 store
xml
<template>
<div>
<p>{{ counterStore.count }}</p>
<button @click="counterStore.increment">Increment</button>
</div>
</template>
<script setup>
import { useCounterStore } from '../stores/counter';
const counterStore = useCounterStore();
</script>
前后端通信
Axios是基于Promise的网络请求库,它可以发送http请求并接收服务器返回的响应数据
Axios返回的是一个Promise对象
javascript
//post请求 post
let data = { //参数
name: 'tom',
web: 'baidu.com'
};
axios.post('http://127.0.0.1/post', data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(response => {
console.log("post.data:", response.data)
}).catch(error => {
console.log("post.error:", error)
}).finally(() => {
console.log("post.finally")
});
同步与异步
-
同步
- 执行特点:代码按编写顺序逐行执行,后续代码需等待当前代码完成才能执行。遇到耗时操作(如网络请求)时,主线程会被阻塞,直到操作结束。
- 举例理解:像单车道发生交通事故致堵塞,只有拖走事故车,后续车辆才能通行。
-
异步
-
执行特点:遇到耗时操作,主线程不阻塞,会继续执行后续代码,无需等待耗时操作完成。
-
举例理解:多车道高速路发生事故,可走其他车道继续行驶。
-
async 和 await
-
async
- 函数特性 :标记为
async
的函数会返回一个Promise
对象 。比如:
- 函数特性 :标记为
javascript
async function asyncFunction() {
return '这是async函数的返回值';
}
// 调用async函数,会得到一个Promise对象
asyncFunction().then(result => {
console.log(result);
});
-
await
- 使用规则 :只能在
async
函数内部使用。当执行到await
关键字时,会暂停函数后续执行,等待await
后面的Promise
对象(常为异步操作,如网络请求)完成,然后获取其返回数据继续执行。例如:
- 使用规则 :只能在
javascript
async function getData() {
// 模拟异步操作,返回Promise对象
const promise = new Promise((resolve) => {
setTimeout(() => {
resolve('异步操作结果');
}, 1000);
});
// await等待Promise完成并获取结果
const result = await promise;
console.log(result);
}
getData();
结合网络请求场景(假设使用axios
库发起请求):
javascript
const axios = require('axios');
async function getRemoteData() {
try {
const response = await axios.get('https://api.example.com/data');
console.log(response.data);
} catch (error) {
console.error(error);
}
}
getRemoteData();
上述代码中,await
等待axios
的网络请求完成,获取响应数据后继续后续操作,若请求出错则进入catch
捕获错误。
6. 指令
6.1 内置指令
v-bind
:缩写是:,用于把数据绑定到 HTML 元素的属性上。v-on
:缩写是@
它用于监听 DOM 事件,使用缩写同样能使代码变得更简洁。v-model
:表单数据的双向绑定操作,让开发者能更便捷地处理用户输入。v-if
、v-else
、v-else-if
:用于条件渲染。v-for
:用于列表渲染。
xml
<template>
<div>
<img :src="imageUrl" alt="Example" />
<button @click="handleClick">Click me</button>
<p v-if="showMessage">This message is visible</p>
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const imageUrl = ref('https://example.com/image.jpg');
const showMessage = ref(true);
const items = ref([
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' }
]);
const handleClick = () => {
console.log('Button clicked');
};
</script>
6.2 自定义指令
xml
<template>
<div v-focus>Input will be focused on mount</div>
</template>
<script setup>
import { defineDirective } from 'vue';
const vFocus = defineDirective({
mounted(el) {
el.focus();
}
});
</script>
7. 插件
可以创建和使用插件来扩展 Vue 应用的功能。
javascript
// plugins/myPlugin.js
const myPlugin = {
install(app, options) {
app.config.globalProperties.$myMethod = () => {
console.log('This is a global method');
};
}
};
export default myPlugin;
javascript
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import myPlugin from './plugins/myPlugin';
const app = createApp(App);
app.use(myPlugin);
app.mount('#app');
xml
<template>
<div></div>
</template>
<script setup>
const { proxy } = getCurrentInstance();
proxy.$myMethod();
</script>