Vue Basic
创建 Vue 项目
脚手架
# vite
pnpm create vue@latest
pnpm create vite@latest项目结构
- Vite 项目中,
index.html是项目的入口文件,在项目最外层 - 加载
index.html后,Vite 解析<script type="module" src="xxx">指向的 JS/TS 文件 src/main.tsVue 应用的入口 JS/TS 文件,导入./App.vue根组件并创建 App 对象挂载到 index.html,也可以导入全局样式, 全局 api,注册插件- Vue 通过
createApp函数创建一个应用实例,<div id="app"></div>是 App 对象的挂载点 - public 公有目录会被直接
cp -r到 dist 目录下, 不会被 vite 打包 - src/assets 静态资源目录会被 vite 打包
setup
setup 概述
setup 是 Vue3 中一个新的配置项,值是一个函数,用于支持 Composition API ,组件中所用到的:数据、方法、计算属性、监视等,均配置在 setup 函数中
特点:
setup函数返回的对象中的内容,可直接在模板中使用setup中访问this是undefinedsetup函数会在beforeCreate之前调用,领先于所有钩子执行
<script lang="ts">
export default {
setup() {
// 定义数据和方法
// 需要 return
return { data, method };
},
};
</script>setup 的返回值
- 若返回一个对象:则对象中的:属性、方法等,在模板中均可以直接使用
- 若返回一个函数:则可以自定义渲染内容
<script lang="ts">
export default {
setup() {
return () => "Hello, world!";
},
};
</script>setup 语法糖
<script setup lang="ts">
// 定义数据和方法
</script>ref
作用:定义响应式变量
语法:const xxx = ref(/* initial value */)
返回值:一个 RefImpl 的实例对象,简称 ref 对象
注意点:
- JS/TS 中操作数据需要:
xxx.value,但模板中不需要.value,直接使用即可 - 若
ref接收的是对象类型,内部也是调用了reactive函数 - 使用
shallowRef,只对顶层属性进行响应式处理
reactive
作用:定义一个响应式对象
语法:const xxx = reactive(/* initial value */)
返回值:一个 Proxy 的实例对象,简称:响应式对象
注意点:
reactive定义的响应式数据是深层次的reactive重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)- 使用
shallowReactive,只对顶层属性进行响应式处理
const person = reactive({
name: "Rico",
age: 24,
});
function changePerson() {
person = { name: "Alice", age: 18 }; // 会失去响应式
Object.assign(person, { name: "Alice", age: 18 });
}toRefs 和 toRef
将一个响应式对象中的每一个属性,转换为 ref 对象,toRefs 和 toRef 功能一致,但 toRefs 可以批量转换
let person = reactive({ name: "rico", age: 24, gender: "female" });
let { name, age } = toRefs(person);
let gender = toRef(person, "gender");computed
计算属性会缓存计算结果,只有当依赖项改变时,才会重新计算。由于需要缓存,computed 不能用于异步操作
let firstName = ref("Rico");
let lastName = ref("White");
// 只读取,不修改
// let fullName = computed(() => {
// return firstName.value + "-" + lastName.value;
// });
let fullName = computed({
// 读取
get() {
return firstName.value + "-" + lastName.value;
},
// 修改 fullName 时触发
set(val) {
firstName.value = val.split("-")[0];
lastName.value = val.split("-")[1];
},
});
function changeFullName() {
fullName.value = "Alice-Green";
}watch 和 watchEffect
watch
作用:监视数据的变化
特点:watch 只能监视以下四种数据:
ref定义的数据。reactive定义的数据。- 函数返回一个值(
getter函数)- 一个包含上述内容的数组
const stopWatch = watch(
/*
watch的第一个参数是:被监视的数据
watch的第二个参数是:监视的回调
watch的第三个参数是:配置对象
(deep, immediate, flush, once)
*/
person,
(newValue, oldValue) => {
console.log(newValue, oldValue);
if (person.value.age === 24) {
stopWatch();
}
},
{ deep: true /* boolean | number */ },
);
- 若修改的是
ref定义的对象中的属性,newValue和oldValue都是新值,因为它们是同一个对象;若修改整个ref定义的对象,newValue是新值,oldValue是旧值,因为不是同一个对象了- 对于
reactive定义的对象,newValue和oldValue都是新值,reactive定义的对象数据默认开启深度监视- 可以传递一个
getter,侦听响应式对象中指定的属性,如() => person.name- 监视多个数据可写成数组形式,如
[() => person.name, person.age]
watchEffect
立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数(不用明确指出监视的数据)
const stopWatch = watchEffect(
(onCleanup) => {
console.log("[watchEffect]", person.age, person.name);
// 清理函数
onCleanup(() => {
console.log("[onCleanup]", person.age, person.name);
});
},
{
flush: "post", // "pre" | "post" | "sync"
// pre: 组件挂载、更新前调用 watchCallback
// post: 组件挂载、更新后调用 watchCallback
// sync: 同步调用 watchCallback
},
);
onCleanup是一个用于注册清理函数的回调函数,在副作用重新运行之前或组件卸载时执行,用于清理上一次副作用产生的结果(如事件监听、定时器等),避免内存泄漏或无效操作。watch和watchEffect的回调函数都可以使用onCleanup来注册清理函数(watch回调的第三个参数,watchEffect回调的第一个参数)
生命周期
概述:组件实例在创建时要经历一系列的初始化步骤,在此过程中 Vue 会在合适的时机,调用特定的函数,从而让开发者有机会在特定阶段运行自己的代码,这些特定的函数统称为:生命周期钩子
组件的生命周期(Vue3 组合式 API):
- 创建阶段:
setup(替代 Vue2 的 beforeCreate 和 created) - 挂载阶段:
onBeforeMount、onMounted - 更新阶段:
onBeforeUpdate、onUpdated - 卸载阶段:
onBeforeUnmount、onUnmounted - 缓存组件:
onActivated、onDeactivated(配合 KeepAlive 使用) - 错误捕获:
onErrorCaptured
常用的钩子:onMounted(挂载完毕)、onUpdated(更新完毕)、onBeforeUnmount(卸载之前)
readonly
作用:用于创建一个对象的深只读副本
注意点:
- 对象的所有嵌套属性都将变为只读
- 任何尝试修改这个对象的操作都会被阻止
- 使用
shallowReadonly只作用于对象的顶层属性
import { reactive, readonly } from "vue";
const items = reactive<string[]>([]);
const readonlyItems = readonly(items);
readonlyItems.push("item");
console.log(items, readonlyItems); // [] []
items.push("item");
console.log(items, readonlyItems); // ["item"] ["item"]toRaw 和 markRaw
toRaw用于获取一个响应式对象的原始对象,toRaw返回的对象不再是响应式的,不会触发视图更新markRaw:标记一个对象,使其永远不会变成响应式的
Vue 指令
- v-text 渲染文本字符串,会忽略子节点
- v-html 渲染 HTML 字符串,会忽略子节点,不支持渲染 Vue 组件
- v-if,v-else-if,v-else 节点的条件渲染,不渲染时将节点卸载,表现为注释节点,操作 DOM
- v-show 节点的显示/隐藏:改变内联 CSS 样式
display: none,操作 CSS - v-for 遍历元素
- v-on 简写为
@,为元素绑定事件 - v-bind 简写为
:,为元素绑定属性(模型到视图的单向绑定),也可以绑定 style - v-model 模型与视图的双向绑定,本质是 v-bind 和 v-on 的语法糖
- v-once 性能优化,只渲染一次
- v-memo 性能优化,缓存依赖变化时重新渲染
- v-slot 简写为
#,用于组件插槽 - v-pre 跳过编译,性能优化
- v-cloak 防止未编译模板闪烁
<input type="text" v-model="userName" />
<!--
模 -> 视 v-bind
型 <- 图 v-on
-->
<input
type="text"
:value="userName"
@input="userName = ($event.target as HTMLInputElement).value"
/>