总体结构
<template>
<script setup>
<style>
| 部分 | 作用 |
|---|---|
| template | 页面结构(HTML) |
| script setup | 逻辑代码 |
| style | 样式 |
script setup
Vue 3 推荐:这是 Vue 3 最大变化之一。
<script setup>
</script>
取代以前:
export default {}
demo:
VUE2:
export default {
data() {
return {
count: 0
}
},
methods: {
add() {}
}
}
Vue 3:直接写变量:
<script setup>
const count = 0;
</script>
它本质是 Composition API 的语法糖。
特点:
-
不需要
export default -
不需要
setup()函数 -
变量直接可用
-
更简洁
-
更接近原生 JS
<script setup> const msg = "Hello Vue3"; </script>
模板中直接使用:
{{ msg }}
一、响应式数据------等同于VUE2的data
响应式和非响应式变量
看下什么是非响应式变量,也即普通变量,特点:
-
❌ 不可变(不能改)
-
❌ 不响应变化
-
✔ 只是"静态值"
<template>{{ msg }}</template> <script setup> const msg = "Hello Vue3"; </script>
页面会直接显示:Hello Vue3,如果:
<script setup>
const msg = "Hello Vue3";
setTimeout(() => {
msg = "changed"; // ❌ 不允许,也不会更新页面
}, 1000);
</script>
<template>
<div>{{ msg }}</div>
</template>
Vue3 主要有两种响应式 API:
1、 ref(基本类型)
用于:
-
string
-
number
-
boolean
<script setup> import { ref } from 'vue';const count = ref(0);
const add = () => {
count.value++;
};
</script>
特点:
-
JS 中必须
.value -
模板中自动解包,不需要
.value{{ count }}
常见坑
count++ // ❌ 错误
count.value++ // ✅ 正确
2、reactive(对象)
用于对象或复杂结构:
<script setup>
import { reactive } from 'vue';
const user = reactive({
userName: '',
age: '',
address: ''
});
const submit = () => {
console.log(user);
};
</script>
<template>
<div>
<h2>用户表单</h2>
<div>
用户名:
<input v-model="user.userName" />
</div>
<div>
年龄:
<input v-model="user.age" />
</div>
<div>
地址:
<input v-model="user.address" />
</div>
<button @click="submit">
提交
</button>
<hr />
<p>用户名:{{ user.userName }}</p>
<p>年龄:{{ user.age }}</p>
<p>地址:{{ user.address }}</p>
</div>
</template>
特点:
- 不需要
.value - 直接修改属性即可
- 适合对象/表单
ref vs reactive 总结
| 类型 | 用法 |
|---|---|
| 基本类型 | ref |
| 对象 | reactive |
二、VUE3中的methods
Vue3 中没有 methods 这个"必须结构",所有方法就是普通函数
<script setup>
import { reactive } from 'vue';
const user = reactive({
userName: '',
age: '',
address: ''
});
// 👇 这就是 Vue3 的 methods
const submit = () => {
console.log('提交数据:', user);
};
const reset = () => {
user.userName = '';
user.age = '';
user.address = '';
};
</script>
<template>
<div>
<input v-model="user.userName" placeholder="用户名" />
<input v-model="user.age" placeholder="年龄" />
<input v-model="user.address" placeholder="地址" />
<button @click="submit">提交</button>
<button @click="reset">重置</button>
</div>
</template>
三、VUE3中的生命周期写法
Vue2 是"配置式生命周期",Vue3(Composition API)是"函数式生命周期"。对比:
vue2:
export default {
data() {
return {
msg: 'hello'
}
},
created() {
console.log('created')
},
mounted() {
console.log('mounted')
}
}
VUE3:
<script setup>
import { onMounted, onUpdated, onUnmounted } from 'vue';
onMounted(() => {
console.log('组件已挂载 mounted');
});
onUpdated(() => {
console.log('组件更新 updated');
});
onUnmounted(() => {
console.log('组件卸载 unmounted');
});
</script>
| Vue2 | Vue3 |
|---|---|
| beforeCreate | ❌ 不需要(setup 替代) |
| created | ❌ 不需要(setup 内执行) |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeDestroy | onBeforeUnmount |
| destroyed | onUnmounted |
在 Vue3 中:
setup()
↓
onBeforeMount
↓
onMounted
↓
onBeforeUpdate
↓
onUpdated
↓
onBeforeUnmount
↓
onUnmounted
1、mounted(页面加载完成)
2、unmounted(页面销毁)
四、computed(计算属性)
用于"基于数据计算结果"
<script setup>
import { ref, computed } from 'vue';
const firstName = ref('Tom');
const lastName = ref('Jerry');
const fullName = computed(() => {
return firstName.value + ' ' + lastName.value;
});
</script>
特点:
- 自动缓存
- 依赖变化才重新计算
- 不建议做异步
五、watch(监听器)
用于"监听数据变化做操作"
1. 基础 watch
<script setup>
import { ref, watch } from 'vue';
const count = ref(0);
watch(count, (newVal, oldVal) => {
console.log('变化了:', newVal);
});
</script>
2. 监听对象属性
watch(() => user.name, (newVal) => {
console.log(newVal);
});
3. deep 深度监听
watch(user, () => {
console.log('user changed');
}, {
deep: true
});
4. immediate 立即执行
watch(count, () => {
console.log('init + change');
}, {
immediate: true
});
watch vs computed
| 类型 | 用途 |
|---|---|
| computed | 计算结果 |
| watch | 做副作用(请求/日志/联动) |
六、watchEffect(自动监听)
Vue3 新特性。
不用写依赖,自动收集:
<script setup>
import { ref, watchEffect } from 'vue';
const count = ref(0);
watchEffect(() => {
console.log("count =", count.value);
});
</script>
特点:
- 自动追踪依赖
- 简化 watch
- 适合简单逻辑
七、组件通信(非常重要)
1. 父传子 props
<script setup>
defineProps({
title: String
});
</script>
父组件:
<Child :title="msg" />
2. 子传父 emit
<script setup>
const emit = defineEmits(['change']);
const send = () => {
emit('change', 123);
};
</script>
父组件:
<Child @change="handleChange" />
3. provide / inject(跨层级)
父组件:
<script setup>
import { provide } from 'vue';
provide('token', 'abc123');
</script>
子组件:
import { inject } from 'vue';
const token = inject('token');
八、script setup 的进阶能力
1. 获取 DOM(ref)
<script setup>
import { ref, onMounted } from 'vue';
const inputRef = ref(null);
onMounted(() => {
inputRef.value.focus();
});
</script>
<template>
<input ref="inputRef" />
</template>
2. 组件引用
<Child ref="childRef" />
const childRef = ref(null);
childRef.value.someMethod();
九、导入外部逻辑(hooks)
Vue3 推荐"逻辑复用"
示例:useCount.js
import { ref } from 'vue';
export function useCount() {
const count = ref(0);
const add = () => count.value++;
return { count, add };
}
使用:
<script setup>
import { useCount } from './useCount';
const { count, add } = useCount();
</script>