Vue3 组合式 API

composition

1. reactive、ref、toRef、toRefs

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
<template>
<div>
{{obj.myname}}
{{obj.mylocation}}
{{mystr}}<!-- html中不需要.value -->
<input type="text" ref="myinput">
{{datalist}}
<button @click="handleClick">click</button>

{{mynameref}}
{{myname}}
{{mylocation}}
</div>
</template>
<script>
import { reactive,ref,toRef,toRefs } from 'vue';
export default {
setup(){
console.log(this) // undefined
const mylocation = ref("beijing")
const obj = reactive({ // 响应式对象或数组
myname:"aaa",
myage:11,
mylocation // ref风格转reactive
})
const mystr = ref("hello") // 基本类型:new Proxy({value:"hello"})
const datalist = ref(["111","222","333"])
const myinput = ref(null)
const handleClick = ()=>{
obj.myname = "bbb"
obj.myage=22
mystr.value = "world" // js中需要.value
datalist.value.push(myinput.value.value)
}
return {
obj,
mystr,
myinput,
datalist,
handleClick,
mynameref: toRef(obj, "myname"), // 把obj的属性myname转为ref形式
...toRefs(obj), // 把obj的所有属性转为ref形式
}
}
}
</script>

2. computed、watch、watchEffect

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
<template>
<div>
{{computedName}}
</div>
</template>
<script>
import { reactive,ref,computed,watch,watchEffect } from 'vue';
export default {
setup(){
const obj = reactive({
myname:"aaa",
myage:11,
datalist:[]
})
const mystr = ref("bbb")

/* 1. 计算属性computed */
const computedName = computed(()=>obj.myname.toUpperCase())

/* 2. 监听属性watch */
// 基本用法
watch(mystr,async (value)=>{
var res = await axios.get(`http://localhost:3000/news?author=${value}`)
obj.datalist = res.data
},{immediate:true})
// reactive中的属性
watch(()=>obj.myname,(newValue,oldValue)=>{
console.log("同步/异步",newValue,oldValue)
})
// 多个数据源侦听
watch([obj,mystr],(newValue,oldValue)=>{
console.log("同步/异步",newValue,oldValue)
})

/* 3. 监听属性watchEffect */
// 默认立即执行;自动检测内部依赖变化;不能获取数据之前的值;
watchEffect(async ()=>{
const res = await axios.get(`http://localhost:3000/news?author=${mystr.value}`)
obj.datalist = res.data
})

return {
obj,
mystr,
computedName,

}
}
}
</script>

3. props、emit、parent、root

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
<!-- 父组件 -->
<template>
<div>
<Navbar title="首页" :left="true" @leftevent="handleLeft"/>
</div>
</template>

<!-- 子组件 -->
<template>
<div>
<button v-show="left" @click="handleClick">返回</button>
{{computedTitle}}
<button>首页</button>
</div>
</template>
<script>
import {computed,getCurrentInstance} from 'vue'
export default {
props:{
title:String,
left:Boolean
},
setup(props,{emit}){
const _this = getCurrentInstance()
const computedTitle = computed(()=>props.title+"-11111")
const handleClick = ()=>{
console.log("click",_this.parent)
console.log("click",_this.root)
emit("leftevent","from child")
}
return {
computedTitle,
handleClick
}
}
}
</script>

4. provice、inject

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
<!-- 父组件 -->
<script>
import {provide, ref} from 'vue'
export default {
setup(){
const show = ref(true)
provide("show",show)
return {
show
}
}
}
</script>

<!-- 子组件 -->
<script>
import { inject, onMounted } from 'vue';
export default {
setup(){
const show = inject("show")
onMounted(()=>{
show.value = false
})
}
}
</script>

5. 生命周期

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
<script>
import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, nextTick } from 'vue';
export default {
setup() {
var clearId
onBeforeMount(() => {
console.log("dom创建之前")
})
onMounted(() => {
console.log("dom创建后")
clearId = setInterval(()=>{
console.log(111111)
},100)
})
onBeforeUpdate(() => {
console.log("更新之前")
})
onUpdated(() => {
console.log("更新之后")
})
onBeforeUnmount(()=>{
console.log("销毁之前")
})
onUnmounted(()=>{
console.log("销毁之后")
clearInterval(clearId)
})

const handleClick = ()=>{
nextTick(()=>{
console.log("nextick")
})
}
return {
handleClick
}
}
}
</script>

6. 自定义 Hooks

hooks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { ref,computed } from 'vue';

function useSearch(datalist) {
const mytext = ref("")
const computedList = computed(() =>
datalist.value.filter(item => item.includes(mytext.value))
)
return {
mytext,
computedList
}
}

export default useSearch
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>
<div>
<input type="text" v-model="mytext">
<ul>
<li v-for="data in computedList" :key="data">
{{ data }}
</li>
</ul>
</div>
</template>
<script>
import { reactive, ref } from 'vue';
import useSearch from './search'
export default {
setup() {
const datalist = ref([])
setTimeout(() => {
datalist.value = ["aaa", "aab", "abc", "bbc", "bcd", "aef", "bdf", "cde"]
}, 2000)

const {mytext,computedList} = useSearch(state)

return {
computedList,
mytext
}
}
}
</script>

7. setup 语法糖

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
72
73
74
75
76
77
78
79
80
81
82
<!-- 父组件 -->
<template>
<div>
app-{{msg}}
<button @click="handleClick">click</button>
<div>
{{myname}} --{{myage}}
</div>

<div v-my-color>
{{computedName}}
</div>

<Child title="电影" @rightEvent="handleRight"></Child>

<!-- 动态组件(注意这里不是字符串) -->
<!--
<component :is="Child"></component>
<component :is="condition ? Foo : Bar"></component>
-->
</div>
</template>
<script setup>
import {ref,reactive,toRefs, computed} from 'vue'

// 引用组件
import Child from './Child.vue'

// 定义的变量、函数可以直接在模板中使用
const msg = ref("hello world")
const state = reactive({
myname:"test",
myage:100
})
const {myname,myage} = {...toRefs(state)}
const handleClick = ()=>{
msg.value = "hello world"
myname.value = "qwer"
}

// computed
const computedName = computed(()=>myname.value.substring(0,1).toUpperCase()+myname.value.substring(1))

// 生命周期
onMounted(() => {
state.myage = 99
})

//局部指令(v开头)
const vMyColor = (el)=>{
el.style.background = "yellow"
}

const handleRight = (value)=>{console.log("app",value)}
</script>


<!-- 子组件 -->
<template>
<div>
<button>返回</button>
{{title}}
<button @click="handleHome">首页</button>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from "vue";

// props、emit
const props = defineProps({
title:{
type:String,
default:"000000"
}
})
console.log(props.title)

const emit = defineEmits(["right-event"])
const handleHome = ()=>{
emit("right-event", "msg from clild")
}
</script>