# Vue3
学习手册 (opens new window)
# Vue
声明和参数 data
声明
Vue2
使用new Vue()
初始化 而Vue3
则使用createApp()
初始化组件的参数声明
data
必须是function
案例比较
<body> <div id="app"> <h1>{{msg}}</h1> </div> <!-- Vue2 --> <script> let app = new Vue({ el: "#app", data() { return { counter: 0, msg: `我是标签` } } }) </script> <!-- Vue3 --> <script> Vue.createApp({ data() { return { msg: `我是标签` } } }).mount('#app') </script> </body>
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涉及改动点
# Template
的挂载
在
Vue2
中 挂载一个具有templete
的应用时 被渲染的内容会 替换我们要挂载的目标元素在
Vue3
中 则会 使用innerHTML
作为子元素插入案例比较
<body> <div id="app"></div> <!-- Vue2 --> <script> let app = new Vue({ el: "#app", data() { return { counter: 0, msg: `我是标签` } }, template: `<h1>{{msg}}</h1>` }) </script> <!-- Vue3 --> <script> Vue.createApp({ data() { return { msg: `我是标签` } }, template: `<h1>{{msg}}</h1>` }).mount('#app') </script> </body>
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
29Vue2
Vue3
涉及改动点
# 数据渲染遍历和判断
在
Vue2
遍历时可以直接绑定ref
属性到$refs
在
Vue3
遍历时则需要自定义函数进行动态获取遍历渲染和判断渲染时 不需要再指定
Key
值案例比较
<body> <div id="app"> <!-- Vue2 --> <div v-for="item in list" :ref="item" :key="item">{{item}}</div> <!-- Vue3 --> <div v-for="item in list" :ref="setRefs">{{item}}</div> </div> <!-- Vue2 --> <script> let app = new Vue({ el: "#app", data() { return { list: [11, 22, 33], } } }) </script> <!-- Vue3 --> <script> Vue.createApp({ data() { return { list: [11, 22, 33], itemRefs: [] } }, methods: { setRefs(el) { if (el) { this.itemRefs.push(el) } }, }, }).mount('#app') </script> </body>
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涉及改动点
# 子组件渲染父组件传递的 attribute
在
Vue2
中子组件的根结点会自动渲染父组件传递的class
和style
在
Vue3
中子组件只有通过v-bind="$attrs"
渲染attribute
行内的
attribute
优先级不再永远高于v-bind
案例展示
<body> <div id="app"> <my-inp id="my-id" class="my-class" style="color: red;"></my-inp> </div> <template id="myInput"> <label> <!-- 渲染前 --> 账号: <input type="text" v-bind="$attrs" id="old-id"> <!-- 渲染后 --> 账号: <input type="text" id="old-id" class="my-class" style="color: red;"> </label> </template> <script> Vue.createApp({ components: { "my-inp": { inheritAttrs: false, template: `#myInput` } } }).mount('#app') </script> </body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24涉及改动点
# 数组侦听
在
Vue2
中 对于数组的操作可以触发watch
的侦听在
Vue3
中 则需要开启deep
模式案例展示
<body> <div id="app"> <button @click="add">add</button> <ul> <li v-for="item in list">{{item}}</li> </ul> </div> <script> Vue.createApp({ data() { return { list: [11, 22, 33] } }, methods: { add() { this.list.push(Date.now()) } }, watch: { list: { handler() { console.log(this.list); }, deep: true } } }).mount('#app') </script> </body>
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涉及改动点
# 父子组件间事件的触发
在
Vue2
中 通过.native
事件修饰符 可以使得子组件的根结点继承DOM
原生触发器在
Vue3
中 默认子组件的根结点自动继承DOM
原生触发器 需要通过emits:[事件名]
来单独设置版本比较
<body> <div id="app"> <h1>{{num}}</h1> <hr> <!-- Vue2 --> <my-btn @click.native="fatherClick"></my-btn> <!-- Vue3 --> <my-btn @click="fatherClick"></my-btn> </div> <template id="myBtn"> <section> <button>sonBtn1</button> <button @click="sonClick">sonBtn</button> </section> </template> <!-- Vue2 --> <script> let app = new Vue({ el: "#app", data: { num: 100 }, methods: { fatherClick() { this.num++ } }, components: { "my-btn": { template: "#myBtn", methods: { sonClick() { this.$emit("click"); } } } } }) </script> <!-- Vue3 --> <script> Vue.createApp({ data() { return { num: 100 } }, methods: { fatherClick() { this.num++ } }, components: { "my-btn": { template: "#myBtn", emits: ['click'], methods: { sonClick() { this.$emit("click"); } } } } }).mount('#app') </script> </body>
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71涉及改动点
# 隔代组件传递参数 Provide
和 Inject
- 涉及改动点
# 动画 (opens new window)
动画类名
leave-class
已经被重命名为leave-from-class
动画类名
enter-class
已经被重命名为enter-from-class
transition-group
支持多个根结点案例展示
<body> <style> .fade-enter-active, .fade-leave-active { transition: opacity 0.5s ease; } .fade-enter-from, .fade-leave-to { opacity: 0; } </style> <div id="app"> <button @click="isLogin = !isLogin">Click</button> <transition name="fade" mode="out-in"> <fieldset v-if="isLogin"> <legend>Login</legend> <p>login...</p> </fieldset> <fieldset v-else> <legend>Regist</legend> <p>Regist...</p> </fieldset> </transition> </div> <script> Vue.createApp({ data() { return { isLogin: true } } }).mount('#app') </script> </body>
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涉及改动点
# 异步组件
通过
defineAsyncComponent
显式声明异步组件component
重命名为loader
案例展示
<template> <div id="Index"> <button @click="show = true">加载异步组件</button> <AsyncCom v-if="show"></AsyncCom> </div> </template> <script> import { defineAsyncComponent } from "vue"; import LoadingComponent from "@/components/LoadingComponent.vue"; import ErrorComponent from "@/components/LoadingComponent.vue"; export default { data() { return { show: false, }; }, components: { AsyncCom: defineAsyncComponent({ loader: () => import("@/components/AsyncCom.vue"), delay: 2000, timeout: 3000, loadingComponent: LoadingComponent, ErrorComponent: ErrorComponent, }), }, }; </script>
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涉及改动点
# 自定义指令
- 涉及改动点