# 快速掌握Vue3 (opens new window)
# setup 函数
setup() 函数是 vue3 中,专门为组件提供的新属性。它为我们使用 vue3 的 Composition API 新特性提供了统一的入口. 它取代了 2.x中的beforeCreate 和Created钩子。
setup函数会在以下方法前执行
- Components
- Props
- Data
- Methods
- Computed Properties
- Lifecycle methods
setup接受两个参数,props和 context,需要返回数据才能在模板中使用
- props: 用来接收 props 数据
- context 用来定义上下文
- 返回值: return {}, 返回响应式数据, 模版中需要使用的函数
代码示例
<template>
<h1>{{name}}</h1>
</template>
<script>
import { ref, watch } from 'vue'
export default {
setup(props, ctx) {
const name = ref('hello')
setTimeout(() => {
name.value = 'world'
}, 2000)
watch(name,(nv) => {
console.log(nv)
})
return {
name
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# reactive 函数
reactive() 函数接收一个普通对象,返回一个响应式的数据对象。在setup函数创立完之后,需要返回整个对象,不能解构。 在模板中使用的时候会自动解开。
代码示例
<template>
<h1>{{state.text}}</h1>
<h1>{{text}}</h1>
</template>
<script>
import { ref, watch, reactive } from 'vue'
export default {
setup(props, ctx) {
const state = reactive({
text: 'hello world'
})
setTimeout(() => {
state.text = "It's responsive"
}, 1000)
return {
state,
...state
}
}
}
</script>
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
# ref() 函数
对数据进行包装,然后返回一个响应式对象。要在js内读取返回的值需要执行 xxx.value的方式,然而在模板中使用可以不用写value。
代码示例
<template>
<h1>{{text}}</h1>
</template>
<script>
import { ref } from 'vue'
export default {
setup(props, ctx) {
const text = ref('hello world')
setTimeout(() => {
text.value = "It's responsive"
}, 1000)
return {
text
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# isRef() 函数
isRef() 用来判断某个值是否为 ref() 创建出来的对象
# toRefs() 函数
toRefs() 函数可以将 reactive() 创建出来的响应式对象,转换为普通的对象. 在setup函数解构也不会丢失响应式。对比reactive
DETAILS
<template>
<h1>{{text}}</h1>
</template>
<script>
import { reactive, toRefs } from 'vue'
export default {
setup(props, ctx) {
const state = reactive({
text: 'hello world'
})
const refState = toRefs(state)
setTimeout(() => {
refState.text.value = "It's responsive"
}, 1000)
return {
...refState
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# computed()
该函数用来创造计算属性,和过去一样,它返回的值是一个ref对象。 里面可以传方法,或者一个对象,对象中包含set()、get()方法
DETAILS
<template>
<h1>{{fullName}}</h1>
</template>
<script>
import { computed } from 'vue'
export default {
setup(props, ctx) {
const state = reactive({
first: 'hello ',
last: 'world'
})
const fullName = computed(() => {
return state.first + state.last
})
setTimeout(() => {
state.first = "hello, ...."
}, 1000)
return {
fullName,
}
}
}
</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
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
# watch() 函数
watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是懒执行的,侦听的源数据变更时才执行回调。
- reactive定义的数据,watch的时候需要写方法,并返回对应属性的值
- ref定义的数据可以直接watch
代码片段
<template>
<h1>{{state.first + state.last}}</h1>
<h1>{{count}}</h1>
<button @click="change">state.first change</button>
<button @click="count++">count++</button>
</template>
<script>
import { watch,reactive,ref } from 'vue'
export default {
setup(props, ctx) {
const state = reactive({
first: 'hello ',
last: 'world'
})
function change() {
state.first = Math.random()
}
// 不能!!不能!!不能!!
watch(state.first, (nv) => {
console.log('state.first 数据是', state.first)
})
// 必须!! 必须!!必须!!
watch(() => state.first, (nv) => {
console.log('state.first 数据是', state.first)
})
// 或者
const count = ref(0)
watch(count, (nv) => {
console.log('count 数据是', count.value)
})
watch([() => state.first,count], ([nfirst,ncount],[ofirst, ocount]) => {
console.log('集中观测===========')
console.log('nfirst:>> ', nfirst);
console.log('ocount :>> ', ocount);
console.log('ofirst :>> ', ofirst);
console.log('ncount :>> ', ncount);
})
return {
state,
count,
change
}
}
}
</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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
# watchEffect() 函数
# LifeCycle Hooks(新的生命后期)
新的生命周期钩子需要从vue中按需引入,这些钩子只能在setup函数中使用
vue2 | vue3 |
---|---|
beforeCreate和created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
activated | onActivated |
deactivated | onDeactivated |
errorCaptured | onErrorCaptured |
- | onRenderTracked |
- | onRenderTriggred |
# Template refs
可以在模板中设置ref属性的值获取真实的DOM,
DETAILS
<template>
<h1 ref="h1RefDom">hello</h1>
</template>
<script>
import { watch,reactive,ref, onMounted } from 'vue'
export default {
setup(props, ctx) {
const h1RefDom = ref(null)
console.log('hRefDom :>> ', h1RefDom.value);
onMounted(() => {
// 获取到真实DOM
console.log('hRefDom :>> ', h1RefDom.value.innerHTML);
})
return {
h1RefDom
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# vue 的全局配置
vue2.x中通过 Vue.prototype.$xxx =xxx
vue3.x中通过 app.config.globalProperties.$xxx 来配置
- errorHandler,指定一个处理函数,来处理组件渲染方法执行期间以及侦听器抛出的未捕获错误。这个处理函数被调用时,可获取错误信息和应用实例。
- warnHandler,为 Vue 的运行时警告指定一个自定义处理函数。注意这只会在开发环境下生效,在生产环境下它会被忽略。
- globalProperties, 添加可以在应用程序内的任何组件实例中访问的全局 property。属性名冲突时,组件的 property 将具有优先权。
- isCustomElement
- optionMergeStrategies,为自定义选项定义合并策略。
- performance:设置为 true 以在浏览器开发工具的 performance/timeline 面板中启用对组件初始化、编译、渲染和更新的性能追踪
# Sharing State - 共享状态
DETAILS
usePromise.js
import { ref } from "vue";
export default function usePromise(fn) {
const results = ref(null);
// is PENDING
const loading = ref(false);
const error = ref(null);
const createPromise = async (...args) => {
loading.value = true;
error.value = null;
results.value = null;
try {
results.value = await fn(...args);
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
};
return { results, loading, error, createPromise };
}
App.vue
import { ref, watch } from "vue";
import usePromise from "./usePromise";
export default {
setup() {
const searchInput = ref("");
function getEventCount() {
return new Promise((resolve) => {
setTimeout(() => resolve(3), 1000);
});
}
const getEvents = usePromise((searchInput) => getEventCount());
watch(searchInput, () => {
if (searchInput.value !== "") {
getEvents.createPromise(searchInput);
} else {
getEvents.results.value = null;
}
});
return { searchInput, ...getEvents };
},
};
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
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
# Suspense 组件
DETAILS
HelloWorld.vue
<template>
<h1>{{ msg }} {{count}}</h1>
</template>
<script>
import { ref } from 'vue'
async function getResult() {
return new Promise((resolve => {
setTimeout(() => {
resolve(Math.random())
}, 1000)
}))
}
export default {
name: 'HelloWorld',
props: {
msg: String
},
async setup(props) {
const count = ref(0);
count.value = await getResult()
return {
count
}
}
}
</script>
App.vue
<template>
<div>
<div v-if="error">Uh oh .. {{ error }}</div>
<Suspense>
<template #default>
<div>
<HelloWorld :msg='"dsfs"'/>
</div>
</template>
<template #fallback> Loading.... </template>
</Suspense>
</div>
</template>
<script>
import { ref, onErrorCaptured, defineAsyncComponent } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
export default {
components: {
HelloWorld,
},
setup() {
const error = ref(null);
onErrorCaptured((e) => {
error.value = e;
// 阻止错误继续冒泡
return true;
});
return { error };
},
};
</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
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
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
# Teleport
DETAILS
App.vue
<template>
<div style="position: relative;">
<h3>Tooltips with Vue 3 Teleport</h3>
<div>
<modal-button></modal-button>
</div>
</div>
</template>
<script>
import ModalButton from './components/ModalButton'
export default {
components :{
ModalButton
}
}
</script>
components/ModalButton.vue
<template>
<teleport to="body">
<button @click="modalOpen = true">
Open full screen modal!
</button>
<div v-if="modalOpen" class="modal">
<div>
I'm a modal!
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
</teleport>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const modalOpen = ref(false)
return {
modalOpen
}
}
}
</script>
<style>
.modal{
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.2)
}
</style>
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
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
# 案例
# 生态
生态 | 地址 |
---|---|
官网 | https://v3.cn.vuejs.org/ |
源码 | https://github.com/vuejs/vue-next |
vite构建器 | https://github.com/vitejs/vite |
脚手架 | https://cli.vuejs.org/ |
vue-router-next | https://github.com/vuejs/vue-router-next |
vuex4.0 | https://github.com/vuejs/vuex/tree/4.0 |
vant2.x | https://vant-contrib.gitee.io/vant/next/#/zh-CN/ |
Ant Design of Vue 2.x | https://2x.antdv.com/docs/vue/introduce-cn/ |
element-plus | https://element-plus.org/#/zh-CN |
模板解析器 | https://vue-next-template-explorer.netlify.app/ |
awesome-vite 官方集合 | https://github.com/vitejs/awesome-vite |