当前位置:首页 > 技术 > 正文内容

Vue 3核心特性与开发实践指南

访客 技术 2026年7月17日 3

一、Vue 3主要特性

Vue 3在前代基础上进行了全面重构,引入了多项重要改进:

  1. 组合式API:通过函数方式组织代码逻辑,提升代码复用性和可维护性
  2. 性能优化:渲染效率和数据初始化速度显著提升
  3. TypeScript原生支持:提供完整的类型定义,代码更加可靠
  4. 更小体积:Tree-shaking支持使最终打包体积更紧凑
  5. 响应式系统升级:采用Proxy替代Object.defineProperty,监听效率更高

二、项目目录结构

标准Vue 3项目的文件组织方式:

my-app/
├── node_modules/        # 项目依赖包目录
├── public/              # 公共静态资源
│   └── index.html       # HTML入口文件
├── src/                 # 源代码主目录
│   ├── assets/          # 图片、字体、样式等资源
│   ├── components/      # 业务组件存放目录
│   ├── views/           # 页面级组件
│   ├── App.vue          # 根组件
│   └── main.ts          # 应用入口文件
└── package.json         # 项目配置与依赖声明

三、核心概念解析

1.Vue应用实例

Vue应用本质上是创建一个根实例并将其挂载到DOM元素的过程。

// main.ts
import { createApp } from 'vue';
import App from './App.vue';

const app = createApp(App);
app.mount('#app');
  • createApp():创建Vue应用实例,接收根组件作为参数
  • mount():将应用挂载到指定DOM元素

2.Options API与Composition API对比

Options API(配置式)

将数据、方法、计算属性分散在不同选项中管理:

<template>
    <div class="user-card">
        <h3>用户信息</h3>
        <p>用户名:{{ username }}</p>
        <p>等级:{{ level }}</p>
        <p>邮箱:{{ email }}</p>
        <button @click="updateLevel">升级</button>
        <button @click="showEmail">查看邮箱</button>
    </div>
</template>

<script lang="ts">
export default {
    name: 'UserCard',
    data() {
        return {
            username: '王小明',
            level: 1,
            email: 'wang@example.com'
        }
    },
    methods: {
        updateLevel() {
            this.level++;
        },
        showEmail() {
            console.log(`邮箱:${this.email}`);
        }
    }
}
</script>

<style scoped>
.user-card {
    background-color: #eef2f5;
    padding: 20px;
    border-radius: 8px;
}
button {
    margin-right: 8px;
}
</style>

Composition API(组合式)

以函数形式组织相关逻辑代码,便于功能复用和维护。

3.组件化开发

组件是Vue应用的基本构建单元,每个组件包含模板、逻辑和样式。

<!-- App.vue -->
<template>
  <div id="app">
    <h1>Vue 3学习笔记</h1>
    <ArticleList />
  </div>
</template>

<script setup>
import ArticleList from './components/ArticleList.vue';
</script>

<style scoped>
h1 {
    color: #2c3e50;
    font-size: 24px;
}
</style>
  • <template>:组件的HTML模板结构
  • <script>:组件的业务逻辑
  • <style scoped>:组件私有样式,防止污染其他组件

4.数据绑定机制

Vue实现数据与视图的双向同步。

文本插值

<template>
  <div class="greeting">
    <h1>{{ title }}</h1>
  </div>
</template>

<script setup>
import { ref } from 'vue';
const title = ref('欢迎学习Vue 3');
</script>

属性绑定

![头像]()
<!-- 等价于 -->
![头像]()

表单双向绑定

<template>
  <div class="form">
    <input v-model="username" placeholder="请输入用户名" />
    <p>当前输入:{{ username }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
const username = ref('');
</script>

5.事件处理

使用@简写形式绑定事件处理器:

<template>
  <div class="actions">
    <button @click="handleSubmit">提交</button>
  </div>
</template>

<script setup>
function handleSubmit() {
  console.log('表单已提交');
}
</script>

6.计算属性

基于响应式数据派生新值,具备缓存机制:

<template>
  <div>
    <p>原字符串:{{ originalText }}</p>
    <p>反转后:{{ reversedText }}</p>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';

const originalText = ref('Vue3学习');
const reversedText = computed(() => {
  return originalText.value.split('').reverse().join('');
});
</script>

计算属性会缓存结果,仅当依赖的响应式数据变化时才重新计算。

7.生命周期钩子

Vue组件在不同的生命周期阶段提供钩子函数:

钩子函数 执行时机
onMounted 组件挂载到DOM后
onUpdated 数据更新后
onUnmounted 组件卸载前
import { ref, onMounted, onUpdated } from 'vue';

export default {
  setup() {
    const message = ref('初始化');
    
    onMounted(() => {
      console.log('组件已挂载');
    });
    
    onUpdated(() => {
      console.log('数据已更新');
    });
    
    return { message };
  }
}

四、Composition API详解

组合式API是Vue 3的核心特性,通过函数方式组织组件逻辑。

1.ref与reactive

ref函数

定义基本类型或对象类型的响应式数据:

import { ref } from 'vue';

const count = ref(0);
const userInfo = ref({
  name: '张三',
  age: 25
});

// 在脚本中修改需使用.value
function increment() {
  count.value++;
}

reactive函数

定义对象类型的响应式数据:

import { reactive } from 'vue';

const state = reactive({
  isLoading: false,
  dataList: [] as string[]
});

function loadData() {
  state.isLoading = true;
}

使用建议

  • 基本类型数据必须使用ref
  • 简单对象(层级不深)可用ref或reactive
  • 复杂深层对象推荐使用reactive

注意

// 错误做法 - 失去响应式
state = { new: 'data' }

// 正确做法 - 使用Object.assign
Object.assign(state, { new: 'data' });

2.toRef与toRefs

将响应式对象的属性转换为独立的ref,保持与源对象的响应式连接:

<template>
    <div class="profile">
        <h3>姓名:{{ name }}</h3>
        <h3>年龄:{{ age }}</h3>
        <h3>地址:{{ address }}</h3>
        <button @click="modifyName">修改姓名</button>
        <button @click="modifyAge">修改年龄</button>
    </div>
</template>

<script lang="ts" setup>
import { reactive, toRefs } from 'vue';

const person = reactive({
    name: '李华',
    age: 28,
    address: '北京'
});

// 使用toRefs批量转换
const { name, age, address } = toRefs(person);

function modifyName() {
    name.value += '~';
}

function modifyAge() {
    age.value++;
}
</script>

<style scoped>
</style>

3.computed计算属性

<template>
    <div class="input-area">
        <label>姓氏:<input v-model="surname" /></label>
        <label>名字:<input v-model="givenName" /></label>
        <button @click="updateFullName">重置为赵六</button>
        <p>完整姓名:{{ fullName }}</p>
    </div>
</template>

<script lang="ts" setup>
import { ref, computed } from 'vue';

const surname = ref('赵');
const givenName = ref('六');

// 可读可写的计算属性
const fullName = computed({
    get: () => `${surname.value}-${givenName.value}`,
    set: (val: string) => {
        const [first, last] = val.split('-');
        surname.value = first;
        givenName.value = last;
    }
});

function updateFullName() {
    fullName.value = '钱-八';
}
</script>

<style scoped>
label {
    display: block;
    margin: 10px 0;
}
</style>

4.watch监听器

监听响应式数据变化并执行相应逻辑。

监听基本类型数据

<template>
    <div>
        <h2>当前计数:{{ counter }}</h2>
        <button @click="add">加一</button>
    </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';

const counter = ref(0);

function add() {
    counter.value++;
}

const stopWatch = watch(counter, (newVal, oldVal) => {
    console.log(`计数从${oldVal}变为${newVal}`);
    if (newVal >= 10) {
        stopWatch();
    }
});
</script>

监听对象类型数据

<template>
    <div>
        <h3>产品信息</h3>
        <p>名称:{{ product.name }}</p>
        <p>价格:{{ product.price }}</p>
        <button @click="changeName">改名称</button>
        <button @click="changePrice">改价格</button>
        <button @click="replaceProduct">替换整个对象</button>
    </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';

const product = ref({
    name: 'iPhone',
    price: 5999
});

function changeName() {
    product.value.name += '~';
}

function changePrice() {
    product.value.price += 100;
}

function replaceProduct() {
    product.value = {
        name: 'iPad',
        price: 4999
    };
}

// 监听对象需要开启深度监听
watch(product, (newVal, oldVal) => {
    console.log('对象变化:', newVal, oldVal);
}, { deep: true, immediate: true });
</script>

监听reactive定义的数据

<template>
    <div>
        <h3>用户资料</h3>
        <p>姓名:{{ user.nickname }}</p>
        <p>积分:{{ user.points }}</p>
        <button @click="updateNickname">修改昵称</button>
        <button @click="updatePoints">增加积分</button>
        <button @click="replaceUser">替换整个对象</button>
    </div>
</template>

<script setup lang="ts">
import { reactive, watch } from 'vue';

const user = reactive({
    nickname: '游客',
    points: 100
});

function updateNickname() {
    user.nickname += '~';
}

function updatePoints() {
    user.points += 50;
}

function replaceUser() {
    Object.assign(user, {
        nickname: '新用户',
        points: 500
    });
}

// reactive定义的对象默认开启深度监听,无法关闭
watch(user, (newVal, oldVal) => {
    console.log('用户数据变化:', newVal);
});
</script>

监听对象内部属性

<template>
    <div>
        <p>车辆信息:{{ car.brand }} - {{ car.model }}</p>
        <button @click="updateBrand">修改品牌</button>
        <button @click="updateModel">修改型号</button>
    </div>
</template>

<script setup lang="ts">
import { reactive, watch } from 'vue';

const car = reactive({
    brand: '比亚迪',
    model: '汉'
});

function updateBrand() {
    car.brand = '红旗';
}

function updateModel() {
    car.model = 'H9';
}

// 监听基本类型属性使用函数形式
watch(() => car.brand, (newVal, oldVal) => {
    console.log(`品牌从${oldVal}变为${newVal}`);
});

// 监听对象类型属性可使用函数形式,开启深度监听
watch(() => car, (newVal, oldVal) => {
    console.log('车辆信息变化', newVal);
}, { deep: true });
</script>

同时监听多个数据源

<template>
    <div>
        <p>姓名:{{ person.name }}</p>
        <p>年龄:{{ person.age }}</p>
        <p>车辆:{{ person.car.brand }}</p>
    </div>
</template>

<script setup lang="ts">
import { reactive, watch } from 'vue';

const person = reactive({
    name: '陈总',
    age: 35,
    car: {
        brand: '特斯拉',
        model: 'Model 3'
    }
});

// 同时监听多个数据源
watch(
    [() => person.name, () => person.car],
    ([newName, newCar], [oldName, oldCar]) => {
        console.log('数据变化:', newName, newCar);
    },
    { deep: true }
);
</script>

5.watchEffect

自动追踪依赖并响应式执行:

<template>
    <div>
        <h2>监控系统</h2>
        <p>温度:{{ temperature }}°C</p>
        <p>压力:{{ pressure }}MPa</p>
        <button @click="increaseTemp">升温</button>
        <button @click="increasePressure">升压</button>
    </div>
</template>

<script setup lang="ts">
import { ref, watchEffect } from 'vue';

const temperature = ref(20);
const pressure = ref(0.5);

function increaseTemp() {
    temperature.value += 10;
}

function increasePressure() {
    pressure.value += 0.2;
}

// 自动追踪函数内使用的所有响应式数据
watchEffect(() => {
    if (temperature.value >= 80 || pressure.value >= 0.8) {
        console.log('触发警报:参数超标!');
    }
});
</script>

<style scoped>
p {
    font-size: 18px;
}
</style>

watch与watchEffect区别

  • watch:需要明确指定监听的数据源
  • watchEffect:自动收集函数内使用的所有响应式依赖

五、setup组件配置

setup是Composition API的入口函数,在组件实例创建前执行:

<template>
  <div>
    <h2>{{ message }}</h2>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const message = ref('Hello Vue 3');

onMounted(() => {
  console.log('setup中的钩子执行了');
});
</script>

setup函数返回的所有属性和方法都可在模板中直接使用,访问this会得到undefined。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。