05 Vue3 Composition API
loyalvi Lv7

05 Vue3 Composition API

setup

created 实例被完全初始化之前

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 对数据做校验的插件
const app = Vue.createApp({
template: `
<div @click="handleClick">{{name}}</div>
`,
methods: {
test() {
console.log(this.$options.setup());
}
},
mounted() {
this.test();
},
// created 实例被完全初始化之前
setup(props, context) {
return {
name: 'dell',
handleClick: () => {
alert(123)
}
}
}
});
const vm = app.mount('#root');

ref和reactive

ref

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ref, reactive 响应式的引用
// 原理,通过 proxy 对数据进行封装,当数据变化时,触发模版等内容的更新
// ref 处理基础类型的数据
const app = Vue.createApp({
template: `
<div>{{name}}</div>
`,
setup(props, context) {
const { ref } = Vue;
// proxy , 'dell' 变成 proxy({value: 'dell'}) 这样的一个响应式引用
let name = ref('dell');
setTimeout(() => {
name.value = 'lee'
}, 2000)
return { name }
}
});

reactive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// reactive 处理非基础类型的数据
const app = Vue.createApp({
template: `
<div>{{nameObj.name}}</div>
`,
setup(props, context) {
const { reactive } = Vue;
// proxy , { name: 'dell'} 变成 proxy({ name: 'dell'}) 这样的一个响应式引用
const nameObj = reactive({name: 'dell', age: 28});
setTimeout(() => {
nameObj.name = 'lee'
}, 2000)
return { nameObj }
}
});
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
// ref, reactive 响应式的引用
// 原理,通过 proxy 对数据进行封装,当数据变化时,触发模版等内容的更新
// ref 处理基础类型的数据
// reactive 处理非基础类型的数据
const app = Vue.createApp({
template: `
<div>{{name}}</div>
`,
setup(props, context) {
// const { ref } = Vue;
// proxy , 'dell' 变成 proxy({value: 'dell'}) 这样的一个响应式引用
// let name = ref('dell');
// setTimeout(() => {
// name.value = 'lee'
// }, 2000)
// return { name }
const { reactive, readonly, toRefs } = Vue;
// proxy , { name: 'dell'} 变成 proxy({ name: 'dell'}) 这样的一个响应式引用
const nameObj = reactive({name: 'dell', age: 28});
setTimeout(() => {
nameObj.name = 'lee'
}, 2000)
// toRefs proxy({ name: 'dell', age: 28}), {
// name: proxy({ value: 'dell'}),
// age: proxy({value: 28})
// }
const { name, age } = toRefs(nameObj);
return { name }
}
});

toRef以及context参数

toRef

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const app = Vue.createApp({
template: `
<div>{{name}}</div>
`,
setup(props, context) {
const { reactive, readonly, toRefs ,toRef } = Vue;
const nameObj = reactive({name: 'dell', age: 28});
setTimeout(() => {
nameObj.name = 'lee'
}, 2000)
const age2 = toRef(nameObj,'age2');
return { age2 }
}
});

context参数 const { attrs, slots, emit } = context;

  • attrs props
  • slots 插槽 => this.$slots
  • emit 事件 => this.$emit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// toRef, context
const app = Vue.createApp({
methods: {
handleChange() {
alert('change');
}
},
template: `<child @change="handleChange">parent</child>`,
});
app.component('child', {
template: '<div @click="handleClick">123123</div>',
setup(props, context) {
const { h } = Vue;
const { attrs, slots, emit } = context;
function handleClick() { emit('change'); }
return { handleClick }
}
})

Composition API实现todolist

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
// 关于 list 操作的内容进行了封装
const listRelativeEffect = () => {
const { reactive } = Vue;
const list = reactive([]);
const addItemToList = (item) => {
list.push(item);
}
return { list, addItemToList }
}
// 关于 inputValue 操作的内容进行了封装
const inputRelativeEffect = () => {
const { ref } = Vue;
const inputValue = ref('');
const handleInputValueChange = (e) => {
inputValue.value = e.target.value
}
return { inputValue, handleInputValueChange}
}
const app = Vue.createApp({
setup() {
// 流程调度中转
const { list, addItemToList } = listRelativeEffect();
const { inputValue, handleInputValueChange} = inputRelativeEffect();
return {
list, addItemToList,
inputValue, handleInputValueChange
}
},
template: `
<div>
<div>
<input :value="inputValue" @input="handleInputValueChange" />
<button @click="() => addItemToList(inputValue)">提交</button>
</div>
<ul>
<li v-for="(item, index) in list" :key="index">{{item}}</li>
</ul>
</div>
`,
});
const vm = app.mount('#root');

computed 计算属性

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
// computed 计算属性
const app = Vue.createApp({
setup() {
const { reactive, computed } = Vue;
const countObj = reactive({ count: 0});
const handleClick = () => {
countObj.count += 1;
}
let countAddFive = computed({
get: () => {
return countObj.count + 5;
},
set: (param) => {
countObj.count = param - 5;
}
})
setTimeout(() => {
countAddFive.value = 100;
}, 3000)
return { countObj, countAddFive, handleClick }
},
template: `
<div>
<span @click="handleClick">{{countObj.count}}</span> -- {{countAddFive}}
</div>
`,
});

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
// watch 侦听器
// watchEffect 侦听器,偏向于 effect
const app = Vue.createApp({
setup() {
const { reactive, watch, watchEffect, toRefs } = Vue;
const nameObj = reactive({
name: 'dell', englishName: 'lee'
})
// 具备一定的惰性 lazy
// 参数可以拿到原始和当前值
// 可以侦听多个数据的变化,用一个侦听器承载
watch([() => nameObj.name, () => nameObj.englishName], ([curName, curEng], [prevName, preEng]) => {
console.log('watch', curName, prevName, '---', curEng, preEng);
}, { immediate: true })
// 立即执行,没有惰性 immediate
// 不需要传递你要侦听的内容,自动会感知代码依赖,不需要传递很多参数,只要传递一个毁掉函数
// 不能获取之前数据的值
// const stop = watchEffect(() => {
// console.log(nameObj.name);
// console.log(nameObj.englishName);
// setTimeout(() => {
// stop();
// }, 5000)
// })
const { name, englishName } = toRefs(nameObj);
return { name, englishName }
},
template: `
<div>
<div>
Name: <input v-model="name">
</div>
<div>
Name is {{name}}
</div>
<div>
EnglishName: <input v-model="englishName">
</div>
<div>
EnglishName is {{englishName}}
</div>
</div>
`,
});

生命周期函数

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
const app = Vue.createApp({
// beforeMount => onBeforeMount
// mounted => onMounted
// beforeUpdate => onBeforeUpdate
// beforeUnmount => onBeforeUnmount
// unmouted => onUnmounted
setup() {
const {
ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated,
//新功能
onRenderTracked, onRenderTriggered
} = Vue;
const name = ref('dell')
onBeforeMount(() => {
console.log('onBeforeMount')
})
onMounted(() => {
console.log('onMounted')
})
onBeforeUpdate(() => {
console.log('onBeforeUpdate')
})
onUpdated(() => {
console.log('onUpdated')
})
// 每次渲染后重新收集响应式依赖
onRenderTracked(() => {
console.log('onRenderTracked')
})
// 每次触发页面重新渲染时自动执行
onRenderTriggered(() => {
console.log('onRenderTriggered')
})
const handleClick = () => {
name.value = 'lee'
}
return { name, handleClick }
},
template: `
<div @click="handleClick">
{{name}}
</div>
`,
});

provide, inject,模版 ref 的用法

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
// provide, inject
const app = Vue.createApp({
setup() {
const { provide, ref, readonly } = Vue;
const name = ref('dell');
provide('name', readonly(name));
provide('changeName', (value) => {
name.value = value;
});
return { }
},
template: `
<div>
<child />
</div>
`,
});
app.component('child', {
setup() {
const { inject } = Vue;
const name = inject('name');
const changeName = inject('changeName');
const handleClick = () => {
changeName('lee');
}
return { name, handleClick }
},
template: '<div @click="handleClick">{{name}}</div>'
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//dom ref
// CompositionAPI 的语法下,获取真实的 DOM 元素节点
const app = Vue.createApp({
setup() {
const { ref, onMounted } = Vue;
const hello = ref(null);
onMounted(() => {
console.log(hello.value);
})
return { hello }
},
template: `
<div>
<div ref="hello">hello world</div>
</div>
`,
});
由 Hexo 驱动 & 主题 Keep
访客数 访问量