惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
V
Visual Studio Blog
宝玉的分享
宝玉的分享
月光博客
月光博客
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Y
Y Combinator Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
博客园_首页
Recent Announcements
Recent Announcements
小众软件
小众软件
MongoDB | Blog
MongoDB | Blog
Attack and Defense Labs
Attack and Defense Labs
The GitHub Blog
The GitHub Blog
Google DeepMind News
Google DeepMind News
Cisco Talos Blog
Cisco Talos Blog
L
LINUX DO - 最新话题
V2EX - 技术
V2EX - 技术
Simon Willison's Weblog
Simon Willison's Weblog
P
Palo Alto Networks Blog
PCI Perspectives
PCI Perspectives
T
Troy Hunt's Blog
Hacker News: Ask HN
Hacker News: Ask HN
S
Security Affairs
量子位
The Register - Security
The Register - Security
腾讯CDC
T
The Exploit Database - CXSecurity.com
P
Privacy & Cybersecurity Law Blog
V
Vulnerabilities – Threatpost
L
LINUX DO - 热门话题
N
News and Events Feed by Topic
Cloudbric
Cloudbric
Cyberwarzone
Cyberwarzone
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
D
Darknet – Hacking Tools, Hacker News & Cyber Security
TaoSecurity Blog
TaoSecurity Blog
Scott Helme
Scott Helme
C
Cybersecurity and Infrastructure Security Agency CISA
The Last Watchdog
The Last Watchdog
W
WeLiveSecurity
H
Hacker News: Front Page
T
Tor Project blog
C
Cyber Attacks, Cyber Crime and Cyber Security
NISL@THU
NISL@THU
Know Your Adversary
Know Your Adversary
C
CXSECURITY Database RSS Feed - CXSecurity.com

XPoet's Blog

Codex 常用命令 | XPoet's Blog Claude Code 常用命令 | XPoet's Blog AI 编程工程化:Plugin——AI 工具能力的产品化形态 | XPoet's Blog AI 编程工程化:MCP——给你的 AI 员工打通外部能力 | XPoet's Blog AI 编程工程化:Subagent——给你的 AI 员工打造协作助手 | XPoet's Blog AI 编程工程化:Hook——AI 每次操作前后的自动检查站 | XPoet's Blog AI 编程工程化:Skill——给你的 AI 员工装上技能包 | XPoet's Blog AI 编程工程化:Command——给你的 AI 员工编一套操作手册 | XPoet's Blog AI 编程工程化:Rule——给你的 AI 员工立规矩 | XPoet's Blog AI 编程工程化:AI 时代程序员的基本功 | XPoet's Blog 独立开发者的福音:Amazon DynamoDB 数据库 | XPoet's Blog 零基础入门 JavaScript 算法 | XPoet's Blog 微信公众号又双叒叕改名了 | XPoet's Blog 赞赏作者 Admire Author 💕 | XPoet's Blog JavaScript 的并发模型和事件循环 | XPoet's Blog 常考的 JavaScript 手写题 | XPoet's Blog JavaScript 的内存管理 | XPoet's Blog 从 0 开始手把手带你搭建一套企业级 Vue3.x 工程化项目 前端工程化入门 | XPoet's Blog Vue 项目动态修改 DOM 的 CSS 伪类
快速掌握 Vue 3.0 基础语法 | XPoet's Blog
XPoet · 2020-10-05 · via XPoet's Blog

经过两年多的迭代,Vue 3.0 终于在 9 月 18 日 发布了正式版,底层使用 TypeScript 进行大规模重构,有着很大的改变。Vue 3.0 采用 Composition API,类似 React Hook,使用更加灵活。

  • Vue 2 对 TypeScript 支持不友好,所有属性都放在 this 对象上,难以推断出数据类型。
  • Vue 2 大量的 API 挂载在 Vue 对象的原型上,难以实现 tree shaking。
  • Vue 2 架构层面对跨平台 DOM 渲染开发支持不友好。
  • Vue 3 采用 Composition API,受 React Hook 启发。
  • Vue 3 更好地支持 JSX。
  • Vue 3 的 Template 支持多个根标签,Vue 2.x 不支持。
  • Vue 3 对虚拟 DOM 进行了重写、对模板的编译进行了优化。

setup() 函数

setup() 是 Vue 3.0 专门为组件提供的新属性。它为我们使用 Vue 3.0 的 Composition API 新特性提供了统一的入口,setup()beforeCreate() 之后和 created() 之前执行,Vue 3.0 取消了这两个 2.x 版本的生命周期钩子函数,统一用 setup() 代替,该函数相当于一个生命周期函数,Vue 2.x 中的 datamethodswatch 等全部都用对应的新增 API 写在 setup() 中。

1
2
3
4
5
6
7
8
9
10
11
12
13
setup(props, context) {








return {

}
}
  • props 用来接收 props 数据。
  • context 用来定义上下文,上下文对象中包含了一些有用的属性,这些属性在 Vue 2.x 中需要通过 this 才能访问到,但在 setup() 中无法访问到 this
  • return {} 返回值,返回的是响应式数据,template 模版中需要使用的函数。

reactive() 函数

reactive() 接收一个普通对象,返回一个响应式的数据对象,响应式数据对象创建出来之后,在 setup()return 出去,即可在 template 中使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template> {{ name }} </template>
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from "vue";
export default defineComponent({
setup(props, context) {
const person = reactive({
name: "zhangsan",
age: 18,
});

return person;
},
});
</script>

ref() 函数

ref() 用来根据给定的值创建一个响应式的数据对象,ref() 调用的返回值是一个对象,这个对象上只包含一个 value 属性,只在 setup() 函数内部获取 ref() 对象的值需要加上 .value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div class="mine">{{ count }}</div>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
setup() {
const count = ref<number>(10);
console.log(count.value);
return {
count,
};
},
});
</script>

reactive() 对象中访问 ref() 创建的响应式数据对象时,不需要加 .value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div class="mine">{{ count }} - {{ n }}</div>
</template>

<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from "vue";
export default defineComponent({
setup() {
const count = ref<number>(10);
const obj = reactive({
n: 100,
count,
});

console.log(obj.count);
return {
...toRefs(obj),
};
},
});
</script>

isRef() 函数

isRef() 用来判断某个值是否为 ref() 创建出来的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { defineComponent, isRef, ref } from "vue";
export default defineComponent({
setup(props, context) {
const name: string = "vue";
const age = ref<number>(18);
console.log(isRef(age));
console.log(isRef(name));

return {
age,
name,
};
},
});

toRefs() 函数

toRefs() 可以将 reactive() 创建出来的响应式对象,转换为普通的对象,这个普通对象上的每个属性节点,都是 ref() 类型的响应式数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div class="mine">{{ name }} {{ age }}</div>
</template>

<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from "vue";
export default defineComponent({
setup(props, context) {
const person = reactive({
name: "zhangsan",
});

const age = ref(18);

return {
...toRefs(person),
age,
};
},
});
</script>

computed() 函数

computed() 用来创建计算属性,和前面一样,它返回的值是一个 ref() 对象。里面可以传方法,或者对象,对象中包含 set()get() 方法。

创建只读的计算属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { computed, defineComponent, ref } from "vue";
export default defineComponent({
setup(props, context) {
const age = ref(18);


const readOnlyAge = computed(() => age.value++);

return {
age,
readOnlyAge,
};
},
});

通过 set()、get() 方法创建一个可读可写的计算属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { computed, defineComponent, ref } from "vue";
export default defineComponent({
setup(props, context) {
const age = ref<number>(18);

const computedAge = computed({
get: () => age.value + 1,
set: (value) => age.value + value,
});


age.value = 100;
return {
age,
computedAge,
};
},
});

watch() 函数

watch() 用来监听特定的数据源,并在回调函数中返回。默认情况是懒执行的,仅在监听的源数据变更时才执行回调。

监听 reactive() 创建的数据源

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
import { computed, defineComponent, reactive, toRefs, watch } from "vue";
interface Person {
name: string;
age: number;
}
export default defineComponent({
setup(props, context) {
const person = reactive<Person>({ name: "vue", age: 10 });

watch(
() => person.age,
(newValue, oldValue) => {
console.log(newValue);
console.log(oldValue);
}
);


person.age = 100;

return {
...toRefs(person),
};
},
});

监听用 ref() 创建的数据源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { defineComponent, ref, watch } from "vue";
interface Person {
name: string;
age: number;
}
export default defineComponent({
setup(props, context) {
const age = ref<number>(10);

watch(age, (oldValue, newValue) => {
console.log("oldValue: ", oldValue);
console.log("newValue: ", newValue);
});


age.value = 100;

return {
age,
};
},
});

同时监听多个值

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
import { computed, defineComponent, reactive, toRefs, watch } from "vue";
interface Person {
name: string;
age: number;
}
export default defineComponent({
setup(props, context) {
const state = reactive<Person>({ name: "zhangsan", age: 10 });

watch(
[() => state.age, () => state.name],
([newAge, newName], [oldAge, oldName]) => {
console.log(newAge);
console.log(newName);

console.log(oldAge);
console.log(oldName);
}
);

state.age = 100;
state.name = "lisi";

return {
...toRefs(state),
};
},
});

stop 停止监听

setup() 内创建的 watch() 监视,会在当前组件被销毁的时候自动停止。如果想要明确地停止某个监听,可以调用 watch() 的返回值即可。

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
34
import { computed, defineComponent, reactive, toRefs, watch } from "vue";
interface Person {
name: string;
age: number;
}
export default defineComponent({
setup(props, context) {
const state = reactive<Person>({ name: "zhangsan", age: 10 });

const stop = watch(
[() => state.age, () => state.name],
([newAge, newName], [oldAge, oldName]) => {
console.log(newAge);
console.log(newName);

console.log(oldAge);
console.log(oldName);
}
);
state.age = 100;
state.name = "lisi";

setTimeout(() => {
stop();

state.age = 1000;
state.name = "wangwu";
}, 1000);

return {
...toRefs(state),
};
},
});

LifeCycle Hooks 新的生命周期函数

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
34
35
36
37
38
39
40
import {
defineComponent,
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onErrorCaptured,
onMounted,
onUnmounted,
onUpdated,
} from "vue";
export default defineComponent({
setup(props, context) {
onBeforeMount(() => {
console.log("beformounted!");
});
onMounted(() => {
console.log("mounted!");
});

onBeforeUpdate(() => {
console.log("beforupdated!");
});
onUpdated(() => {
console.log("updated!");
});

onBeforeUnmount(() => {
console.log("beforunmounted!");
});
onUnmounted(() => {
console.log("unmounted!");
});

onErrorCaptured(() => {
console.log("errorCaptured!");
});

return {};
},
});

Template refs

通过 refs 来返回真实 DOM 元素,为了获得对模板内元素或组件实例的引用,我们可以在 setup() 中声明一个 ref() 并返回它。

  1. 在 HTML 添加 ref 的属性。
  2. steup() 中定义一个 ref()
  3. steup() 中返回 ref() 的实例。
  4. onMounted() 中可以得到 ref() 的 RefImpl 的对象,通过 .value 获取真实 DOM。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div ref="elmRefs">
<span>test</span>
</div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from "vue";
export default defineComponent({
setup(props, context) {

const elmRefs = ref<null | HTMLElement>(null);

onMounted(() => {
console.log(elmRefs.value);
});

return {
elmRefs,
};
},
});
</script>

Vue 3 全局配置

通过 Vue 实例上 config 来配置,包含 Vue 应用程序全局配置的对象。在挂载应用程序之前修改下面列出的属性。

1
2
const app = Vue.createApp({})
app.config = {...}

为组件渲染功能和观察程序期间的未捕获错误分配处理程序

1
app.config.errorHandler = (err, vm, info) => {};

可以在应用程序内的任何组件实例中访问的全局属性,组件的属性将具有优先权。这可以代替 Vue 2.x Vue.prototype 扩展。

1
2
3
import axios from "axios";
const app = Vue.createApp({});
app.config.globalProperties.$http = axios;

可以在组件内通过 getCurrentInstance() 来获取全局 globalProperties 中配置的信息,getCurrentInstance() 获取当前组件的实例,然后通过 ctx 属性获得当前上下文,这样我们就能在 setup() 中使用 router 和 vuex,通过这个属性我们就可以操作变量、全局属性、组件属性等等。

1
2
3
4
setup() {
const { ctx } = getCurrentInstance();

}

Suspense 组件

在介绍 Vue 的 Suspense 组件之前,我们有必要先了解一下 React 的 Suspense 组件,因为它们的功能类似。
React.lazy 接受一个函数,这个函数需要动态调用 import()。它必须返回一个 Promise,该 Promise 需要 resolve 一个 default export 的 React 组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
import React, { Suspense } from "react";

const myComponent = React.lazy(() => import("./Component"));

function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<myComponent />
</Suspense>
</div>
);
}

Vue 3 也新增了 React.lazy 类似功能的 defineAsyncComponent 函数,处理动态引入的组件。defineAsyncComponent 可以接受返回 Promise 的工厂函数。从服务器检索到组件定义时,应该调用 Promise 的解析回调。您还可以调用 reject(reason) 来指示负载已经失败。

1
2
3
4
5
6
7
import { defineAsyncComponent } from "vue";

const AsyncComp = defineAsyncComponent(
() => import("./components/AsyncComponent.vue")
);

app.component("async-component", AsyncComp);

Vue 3 也新增了 Suspense 组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<Suspense>
<template #default>
<my-component />
</template>
<template #fallback> Loading ... </template>
</Suspense>
</template>

<script lang="ts">
import { defineComponent, defineAsyncComponent } from "vue";
const MyComponent = defineAsyncComponent(() => import("./Component"));

export default defineComponent({
components: {
MyComponent,
},
setup() {
return {};
},
});
</script>