Vue3 学习笔记

官网: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 refreactive

  • 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>

生命周期阶段与函数

  1. 创建阶段
  • beforeCreate

    • 这是实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。此时,datamethods 等属性都还未初始化,不能访问它们。
    • 示例代码:
javascript 复制代码
new Vue({
  beforeCreate() {
    console.log('实例初始化,data 和 methods 未初始化');
  }
});
  • created

    • 实例已经创建完成之后被调用。在这一步,实例已经完成了数据观测 (data observer)、propertymethod 的计算、watch/event 事件回调的配置等。然而,挂载阶段还没有开始,$el 属性目前不可用。
    • 示例代码:
javascript 复制代码
new Vue({
  data() {
    return {
      message: 'Hello Vue!'
    };
  },
  created() {
    console.log(this.message); // 可以访问 data 中的属性
  }
});
  1. 挂载阶段
  • 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');
  1. 更新阶段
  • 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 已更新');
  }
});
  1. 销毁阶段
  • beforeDestroy

    • 实例销毁之前调用。在这一步,实例仍然完全可用,datamethodswatchevent 等都还可以正常使用。通常用于解绑自定义事件、清除定时器等操作。
    • 示例代码:
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-ifv-elsev-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>
相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax