Vue3
# Vue3.0 工程
# Vue-cli 创建
# 查看@vue/cli版本,保证@vue/cli版本在4.5.0以上
vue --version
vue -V
# 安装或者升级@vue/cli
npm install -g @vue/cli
# 创建项目
vue create <project-name>
# 启动
cd <project-name>
npm run serve
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# Vite 创建
npm init vite-app my-vue3-project
npm init vite@latest my-vue3-project
1
2
2
# 生命周期
# 组合式 API
# 生命周期钩子函数
onBeforeMount; /* 在组件被挂载之前被调用 */
onMounted; /* 在组件挂载完成后执行 */
onBeforeUpdate; /* 在组件即将因为响应式状态变更而更新其 DOM 树之前调用 */
onUpdated; /* 在组件因为响应式状态变更而更新其 DOM 树之后调用 */
onBeforeUnmount; /* 在组件实例被卸载之前调用 */
onUnmounted; /* 在组件实例被卸载之后调用 */
1
2
3
4
5
6
2
3
4
5
6
# setup
- 是所有的
Composition
API(组合 API) - 组件中所用到数据方法等均要配置在 setup 中
- setup 两种返回值
- 返回对象
- 返回渲染函数
- setup 的参数
- props 值为对象,包含外部传递过来,且组件内部声明接收了的属性
- context 上下文对象
attrs
值为对象,包含组件外部传递过来,但没有在 props 配置中声明的属性,相当于 v2 中的 this.$attrsslots
收到的插槽内容,相当于 this.$slotsemit
分发自定义事件的函数,相当于 this.$emit
setup(props,context){
let title = 'hello';
// 对象返回
return{
title,
}
// 渲染函数
return ()=>h('h1','hello')
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
注意
- Vue2 配置(data,methods,computed 等)中可以访问到 setup 中的属性,方法
- setup 中不能访问 Vue2 配置(data,methods,computed...)
- 如果 Vue2 和 Vue3 中有重名,setup 优先
- setup 不能是一个 async 函数,因为返回值不是 return 对象,而上一个 Promise
- setup 在 beforeCreate 之前执行一次,this 时 undefined
# 核心
# ref()
定义一个响应式的数据
说明
- 接受的数据可以是基本类型,也可以是对象类型
- 基本类型的数据:响应式依然是靠
Object.defineProperty()
的get
与set
完成的 - 对象类型的数据:内容使用了 Vue3.0 中的一个新函数
reactive
函数 - 模版中使用不需要
.value
:::
<script>
import { ref } from "vue";
export default {
name: "App",
data() {
return {};
},
setup() {
let city = ref("北京");
function change() {
city.value = "上海";
}
return {
city,
};
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# computed()
import { computed } from "vue";
export default {
setup() {
let person = reactive({
firstName: "张",
lastName: "三",
});
// 只读写法
person.getName = computed(function () {
return person.firstName + "-" + person.lastName;
});
// 完整写法(读和写)
person.getName = computed({
get() {
return person.firstName + "-" + person.lastName;
},
set(value) {
// 赋值
person.firstName = value.split(",")[0];
},
});
},
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# reactive()
定义一个对象类型的响应式数据
说明
reactive
接受一个对象或数组,代理对象(Proxy 的实例对象)- reactive 定义的对象是深层次的
- 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作
<script>
import { reactive } from "vue";
export default {
name: "App",
data() {
return {};
},
setup() {
let citys = reactive(["北京", "上海", "广州", "深圳"]);
function change() {
citys[0] = "杭州";
}
return {
citys,
};
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# ref 与 reactive 区别
- 定义数据角度对比
- ref 用来定义:
基本类型数据
- reactive 用来定义:
对象或数组类型数据
- 注意 ❗️ :ref 也可以用来定义对象或数组类型数据,内部会自动通过
reactive
转为代理对象
- ref 用来定义:
- 从原理角度对比
- ref 通过
Object.defineProperty()
的 get 与 set 来实现响应式(数据劫持) - reactive 通过使用
Proxy
来实现响应式(数据劫持),并通过Reflect
操作源对象内部的数据
- ref 通过
- 从使用角度对比
- ref 定义的数据:操作数据需要
.value
,读取数据时模版直接读取,不需要.value
- reactive 定义的数据:操作数据与读取数据都不需要
.value
- ref 定义的数据:操作数据需要
# watch() - 监听函数
需要指明监视的属性,也要指明监视的回调
import { ref, reactive, watch } from "vue";
export default {
setup() {
/**
* {immediate:true,deep:true}
* immediate:true 在第一次进入页面时就会监听
* deep 用来深度监听
*/
// 1.监听ref中定义的一个数据
watch(a, (newVal, oldVal) => {});
// 2.监听ref中多定义的所有ref数据
watch([a, d], (newVal, oldVal) => {});
// 3.监听reactive所定义的一个响应式数据中的全部数据
/**
* 1. 无法正确的获取oldVal(若需要获取oldVal,需要将属性设置到ref函数中)
* 2. 强制开启深度监听默认deep:true 设置deep:false无效
*/
watch(c, (newVal, oldVal) => {}, { deep: false });
// 4.监听reactive所定义的一个响应式数据中的某个数据
watch(
() => b.num,
(newVal, oldVal) => {}
);
// 5.监听reactive所定义的一个响应式数据中的某些数据
watch([() => b.age, () => b.num], (newVal, oldVal) => {});
// 6.监视reactive所定义的对象中的某个属性(对象),需要设置deep:true,否则监视不到
watch(
() => b.work,
(newVal, oldVal) => {},
{ immediate: true, deep: true }
);
},
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# watchEffect()
不用指明监视哪个属性,回调中用到哪个属性,就监视哪个属性,只要回调中用到的数据发生变化,则直接重新执行回调
watchEffect(() => {});
1
# 工具
# toRef 与 toRefs
作用为将响应式中的对象某个属性单独提供给外部使用
- 创建一个 ref 对象,其中的 value 值指向另一个对象中的某个属性
toRef
创建单个 ref 对象,toRefs
批量创建多个 ref 对象
const x = toRef({}, "属性");
const x = toRefs({});
1
2
2
# hook 函数
本质是一个函数,把 setup 中使用的 Composition API 进行了封装,类似于 Vue2 中的 mixin
- 创建模块文件
import { reactive, onMounted, onBeforeUnmount } from "vue";
export default function () {
let ponent = reactive({
x: 0,
y: 0,
});
function savepon(event) {
ponent.x = event.pageX;
ponent.y = event.pageY;
}
onMounted(() => {
window.addEventListener("click", savepon);
});
onBeforeUnmount(() => {
window.removeEventListener("click", savepon);
});
return ponent;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 引入
import userPon from "../hooks/userpon";
export default {
setup() {
let ponent = userPon();
return {
ponent,
};
},
};
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# provide 与 inject
provide()提供一个值,可以在应用中的所有后代组件中注入使用。用于实现祖组件与后代组件间的通信
// 祖组件
import { provide } from 'vue'
export default {
setup(){
provide('message','hello')
}
}
// 后代组件
import { inject } from 'vue'
export default {
setup(){
// 使用inject接收,后代组件接收的是Proxy格式,是响应式
const x = inject('message')
return {x}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 创建 hooks 文件
import { reactive, onMounted, onBeforeUnmount } from "vue";
export default function () {
let point = reactive({
x: 0,
y: 0,
});
function savePoint(event) {
point.x = event.pageX;
point.y = event.pageY;
}
onMounted(() => {
window.addEventListener("click", savePoint);
});
onBeforeUnmount(() => {
window.removeEventListener("click", savePoint);
});
return point;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 引用
import usepoint from "./usepoint.js";
export default {
setup() {
const point = usepoint;
return { point };
},
};
1
2
3
4
5
6
7
2
3
4
5
6
7
# shallowReactive 与 shallowRef
shallowReactive
: 只处理对象最外层属性的响应式(浅响应式)。shallowRef
: 只处理基本数据类型的响应式, 不进行对象的响应式处理- 使用场景
- 一个结构对象,有多层结构,但只是最外层属性变化 (
shallowReactive
) - 一个结构对象,后续不会修改对象中的属性,而是生成新的对象来替换 (
shallowRef
)
- 一个结构对象,有多层结构,但只是最外层属性变化 (
# readonly 与 shallowReadonly
readonly
让一个人响应式数据变为只读
(深只读)。shallowReadonly
让一个响应式数据变为只读
(浅只读,对象中嵌套的多层结构可以修改)
import { readonly, shallowReadonly } from "vue";
export default {
setup() {
let per = reactive({
name: "东",
age: 20,
work: {
num: {
games: 100,
},
},
});
// 深只读
let person = readonly(per);
// 浅只读
let person = shallowReadonly(per);
},
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# toRaw 与 markRaw
toRaw
- 作用:将一个由
reactive
生成的响应式对象转为普通对象 - 场景:用于读取响应式对象对应的普通对象,对其所有操作,不会引起页面更新
- 作用:将一个由
markRaw
- 作用: 标记一个对象,使其永远不会再成为响应式对象
- 场景:
- 复杂的第三方库
- 渲染具有不可变数据的大列表,跳过响应式转换可以提高性能
# customRef 自定义 ref
创建一个自定义的 ref,显式声明对其依赖追踪和更新触发的控制方式。
import { customRef } from "vue";
export default {
setup() {
function useDebouncedRef(value, delay = 200) {
let timeout;
return customRef((track, trigger) => {
return {
get() {
track(); // 通知vue去跟踪value大变化
return value;
},
set(newValue) {
clearTimeout(timeout);
timeout = setTimeout(() => {
value = newValue;
trigger(); // 通知Vue重新解析模版
}, delay);
},
};
});
}
const x = useDebouncedRef("hello");
return {
x,
};
},
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 判断响应式数据
# isRef()
判断一个值是否为一个 ref 对象
# isReactive()
检查一个对象是否是由
reactive
创建的响应式代理
# isReadonly()
检查一个对象是否是由
readonly
创建的只读代理
# isProxy()
检查一个对象是否是由
reactive
或者readonly
方法创建的代理
# Composition API 的优势
- Options API 问题
使用传统 Options API 当数据复杂时,新增或修改一个需求,就需要在各个函数里面进行修改
- Composition API
通过 hook 函数将各功能模块拆分出去,增强代码的可维护性
2.x 全局 API | 3.x 实例 API |
---|---|
Vue.config.xxx | app.config.xxx |
Vue.congig.productionTip | 移除 |
Vue.component | app.component |
Vue.directive | app.directive |
Vue.mixin | app.mixin |
Vue.use | app.use |
Vue.prototype | app.config.globalProperties |
上次更新: 2025/02/27, 19:02:07